Legal Information

DirectX 6.1
Programmer's Reference

Information in this document is subject to change without notice. The example companies, organizations, products, people and events depicted herein are fictitious. No association with any real company, organization, product, person or event is intended or should be inferred. Complying with all applicable copyright laws is the responsibility of the user. Without limiting the rights under copyright, no part of this document may be reproduced, stored in or introduced into a retrieval system, or transmitted in any form or by any means (electronic, mechanical, photocopying, recording, or otherwise), or for any purpose, without the express written permission of Microsoft Corporation.

Portions of this document specify and accompany software that is still in development. Some of the information in this documentation may be inaccurate or may not be an accurate representation of the functionality of final documentation or software. Microsoft assumes no responsibility for any damages that might occur directly or indirectly from these inaccuracies.

Microsoft may have patents, patent applications, trademarks, copyrights, or other intellectual property rights covering subject matter in this document. Except as expressly provided in any written license agreement from Microsoft, the furnishing of this document does not give you any license to these patents, trademarks, copyrights, or other intellectual property.

© 1997-1999 Microsoft Corporation. All rights reserved.

Microsoft, MS-DOS, MS, Windows, Windows NT, ActiveX, Direct3D, DirectAnimation, DirectDraw, DirectInput, DirectMusic, DirectPlay, DirectShow, DirectSound, DirectX, Natural, and Win32 are either registered trademarks or trademarks of Microsoft Corporation in the United States and/or other countries.

GM/GS® Sound Set © Copyright 1996 Roland Corporation U.S.

Roland is a registered trademark of the Roland Corporation.

The names of actual companies and products mentioned herein may be the trademarks of their respective owners.

Copyright Warning

Special Note and Warning The GM.DLS collection supplied with DirectMusic uses the GM/GS Sound Set, trademarked by the Roland Corporation, and is the legal property of the Roland Corporation. It must not be modified and must only be redistributed in its entirety and without alteration. The component sounds and wave forms in the Roland GM.DLS collection must not be used as source material to create other DLS sounds or collections.

Some of the Producer components supplied with DirectMusic and DirectMusic Producer can be modified and used as source material for creating your own components. However, some Producer components contained in DirectMusic have specific copyright restrictions, and must not be modified or used as source material for creating your own components.

This is often true for DLS components, and it is especially true for the GM.DLS supplied with DirectMusic and DirectMusic Producer. This GM.DLS is the property of Roland Corporation. You must conform to the legal restrictions for any component you use, and also read any copyright information contained in the Properties window of the file.


Introducing DirectX 6.1

The Microsoft® DirectX® 6.1 application programming interface (API) provides strategies, technologies and tools that can help you build the next generation of computer games and multimedia applications. This overview covers general introductory information about the DirectX 6.1 Programmer's Reference in the Platform Software Development Kit (SDK) documentation. Information is divided into the following sections:

  • DirectX Goals
  • The DirectX Programmer's Reference
  • DirectX and the Component Object Model
  • What's New in DirectX?
  • Conventions
  • Further Reading
  • Debugging DirectX Applications
  • Compiling DirectX Samples and Other DirectX Applications


DirectX Goals

Microsoft® DirectX® provides a finely tuned set of application programming interfaces (APIs) that provide you with the resources you need to design high-performance, real-time applications. DirectX technology will help build the next generation of computer games and multimedia applications.

Microsoft developed DirectX so that the performance of applications running in the Microsoft Windows® operating system can rival or exceed the performance of applications running in the MS-DOS® operating system or on game consoles. This Programmer's Reference was developed to promote game development for Windows by providing you with a robust, standardized, and well-documented operating environment for which to write games.

DirectX provides you with two important benefits:

  • Benefits of Developing DirectX Windows Applications
  • Providing Guidelines for Hardware Development


Benefits of Developing DirectX Windows Applications

When Microsoft created DirectX, one of its primary goals was to promote games development for the Windows environment. Prior to DirectX, the majority of games developed for the personal computer were MS-DOS-based. Developers of these games had to conform to a number of hardware implementations for a variety of cards. With DirectX, games developers get the benefits of device independence without losing the benefits of direct access to the hardware. The primary goals of DirectX are to provide portable access to the features used with MS-DOS today, to meet or improve on the performance of MS-DOS console-based applications, and to remove the obstacles to hardware innovation on the personal computer.

Additionally, Microsoft developed DirectX to provide Windows-based applications with high-performance, real-time access to available hardware on current and future computer systems. DirectX provides a consistent interface between hardware and applications, reducing the complexity of installation and configuration and using the hardware to its best advantage. By using the interfaces provided by DirectX, software developers can take advantage of hardware features without being concerned about the implementation details of that hardware.

A high-performance Windows-based game will take advantage of the following technologies:

  • Accelerator cards designed specifically for improving performance
  • Plug and Play and other Windows hardware and software
  • Communications services built into Windows, including DirectPlay


Providing Guidelines for Hardware Development

DirectX provides hardware development guidelines based on feedback from developers of high-performance applications and independent hardware vendors (IHVs). As a result, the DirectX Programmer's Reference components might provide specifications for hardware-accelerator features that do not yet exist. In many cases, the software emulates these features. In other cases, the software polls the hardware regarding its capabilities and bypasses the feature if it is not supported.


The DirectX Programmer's Reference

This section describes the DirectX Programmer's Reference, also referred to as the DirectX Software Development Kit (SDK), components and some DirectX implementation details. The following topics are discussed:

  • DirectX Programmer's Reference Components
  • Using Macro Definitions


DirectX Programmer's Reference Components

The DirectX Programmer's Reference, also known as the DirectX SDK, includes several components that address the performance issues of programming Windows-based games and high-performance applications. This section lists these components and provides a link for more information on each component.

  • DirectDraw® accelerates hardware and software animation techniques by providing direct access to bitmaps in off-screen display memory, as well as extremely fast access to the blitting and buffer-flipping capabilities of the hardware. For more information, see About DirectDraw in the DirectDraw documentation.
  • DirectSound® enables hardware and software sound mixing and playback. For more information, see About DirectSound in the DirectSound documentation.
  • DirectMusic™ is the musical component of DirectX. Unlike DirectSound, which is for the capture and playback of digital sound samples, DirectMusic works with message-based musical data. For more information about this newest component of DirectX, see About DirectMusic.
  • DirectPlay® makes connecting games over a modem link or network easy. For more information, see About DirectPlay in the DirectPlay documentation.
  • Direct3D® provides a high-level Retained Mode interface that allows applications to easily implement a complete 3-D graphical system, and a low-level Immediate Mode interface that lets applications take complete control over the rendering pipeline. For more information about Immediate Mode, see About Direct3D Immediate Mode. For more information about Retained Mode, see About Retained Mode.
  • DirectInput® provides input capabilities to your game that are scalable to future Windows-based hardware-input APIs and drivers. Currently the joystick, mouse, keyboard, and force feedback devices are supported. For more information, see About DirectInput in the DirectInput documentation.
  • DirectSetup provides a one-call installation procedure for DirectX. For more information, see About DirectSetup in the DirectSetup documentation.
  • AutoPlay is a Windows feature that starts an installation program or game automatically from a compact disc when you insert the disc in the CD-ROM drive. For more information, see About AutoPlay in the AutoPlay documentation.

The AutoPlay feature is part of the Microsoft Win32® API in the Platform SDK and is not unique to DirectX.

Among the most important parts of the documentation for the DirectX SDK is the sample code. Studying code from working samples is one of the best ways to understand DirectX. Sample applications are located in the \Mssdk\Samples\Multimedia folder of the DirectX SDK or in the DirectX code samples under the Platform SDK References section.


Using Macro Definitions

Many of the header files for the DirectX interfaces include macro definitions for each method. These macros are included to simplify the use of the methods in your programming, and also have the advantage of expanding to appropriate calls in either C or C++ syntax, depending on whether or not __cplusplus is defined.

The following example uses the IDirectDraw4_CreateSurface macro to call the IDirectDraw4::CreateSurface method. The first parameter is a reference to the DirectDraw object that has been created and invokes the method:

ret = IDirectDraw4_CreateSurface (lpDD, &ddsd, &lpDDS,
    NULL);

To obtain a current list of the methods supported by macro definitions, see the appropriate header file for the DirectX component you want to use.


DirectX and the Component Object Model

This section describes the Component Object Model (COM) and how it implements the DirectX objects and interfaces. The following topics are discussed:

  • The Component Object Model
  • IUnknown Interface
  • DirectX COM Interfaces
  • C++ and the COM Interface
  • Retrieving Newer Interfaces
  • Accessing COM Objects by Using C
  • Interface Method Names and Syntax


The Component Object Model

Most APIs in DirectX are composed of objects and interfaces based on COM. COM is a foundation for an object-based system that focuses on reuse of interfaces, and it is the model at the heart of COM programming. It is also an interface specification from which any number of interfaces can be built. It is an object model at the operating-system level.

Many DirectX APIs are created as instances of COM objects. You can consider an object to be a black box that represents the hardware and requires communication with applications through an interface. The commands sent to and from the object through the COM interface are called methods. For example, the IDirectDraw4::GetDisplayMode method is sent through the IDirectDraw4 interface to get the current display mode of the display adapter from the DirectDraw object.

Objects can bind to other objects at run time, and they can use the implementation of interfaces provided by the other object. If you know an object is a COM object, and if you know which interfaces that object supports, your application (or another object) can determine which services the first object can perform. One of the methods all COM objects inherit, the QueryInterface method, lets you determine which interfaces an object supports and creates pointers to these interfaces. For more information about this method, see the IUnknown Interface.


IUnknown Interface

All COM interfaces are derived from an interface called IUnknown. This interface provides DirectX with control of the object's lifetime and the ability to navigate multiple interfaces. IUnknown has three methods:

  • AddRef, which increments the object's reference count by 1 when an interface or another application binds itself to the object.
  • QueryInterface, which queries the object about the features it supports by requesting pointers to a specific interface.
  • Release, which decrements the object's reference count by 1. When the count reaches 0, the object is deallocated.

The AddRef and Release methods maintain an object's reference count. For example, if you create a DirectDrawSurface object, the object's reference count is set to 1. Every time a function returns a pointer to an interface for that object, the function then must call AddRef through that pointer to increment the reference count. You must match each AddRef call with a call to Release. Before the pointer can be destroyed, you must call Release through that pointer. After an object's reference count reaches 0, the object is destroyed and all interfaces to it become invalid.

The QueryInterface method determines whether an object supports a specific interface. If an object supports an interface, QueryInterface returns a pointer to that interface. You then can use the methods contained in that interface to communicate with the object. If QueryInterface successfully returns a pointer to an interface, it implicitly calls AddRef to increment the reference count, so your application must call Release to decrement the reference count before destroying the pointer to the interface.


IUnknown::AddRef

The IUnknown::AddRef method increases the reference count of the object by 1.

ULONG AddRef();

Parameters

None.

Return Values

Returns the new reference count. This value is meant to be used for diagnostic and testing purposes only.

Remarks

When the object is created, its reference count is set to 1. Every time an application obtains an interface to the object or calls the AddRef method, the object's reference count is increased by 1. Use the Release method to decrease the object's reference count by 1.

This method is part of the IUnknown interface inherited by the object.

QuickInfo

Windows NT/2000: Requires Windows NT 3.1 or later.
Windows 95/98: Requires Windows 95 or later.
Windows CE: Unsupported.
Header: Declared in unknwn.h.


IUnknown::QueryInterface

The IUnknown::QueryInterface method determines if the object supports a particular COM interface. If it does, the system increases the object's reference count, and the application can use that interface immediately.

HRESULT QueryInterface(
  REFIID riid,
  LPVOID* obp
);

Parameters

riid
Reference identifier of the interface being requested.
obp
Address of a pointer that will be filled with the interface pointer if the query succeeds.

Return Values

If the method succeeds, the return value is S_OK.

If the method fails, the return value may be E_NOINTERFACE, E_POINTER, or one of the following interface-specific error values. Interface-specific error values are listed by component.

DirectDraw
DDERR_INVALIDOBJECT

DDERR_INVALIDPARAMS

DDERR_OUTOFMEMORY (DirectDrawSurface objects only)

DirectSound
DSERR_GENERIC (IDirectSound and IDirectSoundBuffer only)

DSERR_INVALIDPARAM

DSERR_NOINTERFACE

DirectPlay
DPERR_INVALIDOBJECT

DPERR_INVALIDPARAMS

For Direct3D Retained Mode and Immediate Mode interfaces, the QueryInterface method returns one of the values in Direct3D Retained Mode Return Values and Direct3D Immediate Mode Return Values.

If the application does not need to use the interface retrieved by a call to this method, it must call the Release method for that interface to free it. The QueryInterface method allows Microsoft and third parties to extend objects without interfering with each other's existing or future functionality.

This method is part of the IUnknown interface inherited by the object.

QuickInfo

Windows NT/2000: Requires Windows NT 3.1 or later.
Windows 95/98: Requires Windows 95 or later.
Windows CE: Unsupported.
Header: Declared in unknwn.h.


IUnknown::Release

The IUnknown::Release method decreases the reference count of the object by 1.

ULONG Release();

Parameters

None.

Return Values

Returns the new reference count. This value is meant to be used for diagnostic and testing purposes only.

Remarks

The object deallocates itself when its reference count reaches 0. Use the AddRef method to increase the object's reference count by 1.

This method is part of the IUnknown interface inherited by the object.

Applications must only call this method to release interfaces it explicitly created in a previous call to IUnknown::AddRef, IUnknown::QueryInterface, or a creation function such as DirectDrawCreate.

QuickInfo

Windows NT/2000: Requires Windows NT 3.1 or later.
Windows 95/98: Requires Windows 95 or later.
Windows CE: Unsupported.
Header: Declared in unknwn.h.


DirectX COM Interfaces

The interfaces in the DirectX Programmer's Reference have been created at a very basic level of COM programming hierarchy. Each interface to an object that represents a device, such as IDirectDraw4, IDirectSound, and IDirectPlay, derives directly from the IUnknown COM interface. Creation of these basic objects is handled by specialized functions in the dynamic-link library (DLL) for each object, rather than by the CoCreateInstance function typically used to create COM objects.

Typically, the DirectX object model provides one main object for each device. Other support service objects are derived from this main object. For example, the DirectDraw object represents the display adapter. You can use it to create DirectDrawSurface objects that represent the display memory and DirectDrawPalette objects that represent hardware palettes. Similarly, the DirectSound object represents the audio card and creates DirectSoundBuffer objects that represent the sound sources on that card.

Besides the ability to generate subordinate objects, the main device object determines the capabilities of the hardware device it represents, such as the screen size and number of colors, or whether the audio card has wave-table synthesis.


C++ and the COM Interface

To C++ programmers, a COM interface is like an abstract base class. That is, it defines a set of signatures and semantics but not the implementation, and no state data is associated with the interface. In a C++ abstract base class, all methods are defined as pure virtual, which means they have no code associated with them.

Pure virtual C++ functions and COM interfaces both use a device called a vtable. A vtable contains the addresses of all functions that implement the given interface. If you want a program or object to use these functions, you can use the QueryInterface method to verify that the interface exists on an object and to obtain a pointer to that interface. After sending QueryInterface, your application or object actually receives from the object a pointer to the vtable, through which this method can call the interface methods implemented by the object. This mechanism isolates from one another any private data the object uses and the calling client process.

Another similarity between COM objects and C++ objects is that a method's first argument is the name of the interface or class, called the this argument in C++. Because COM objects and C++ objects are completely binary compatible, the compiler treats COM interfaces like C++ abstract classes and assumes the same syntax. This results in less complex code. For example, the this argument in C++ is treated as an understood parameter and not coded, and the indirection through the vtable is handled implicitly in C++.


Retrieving Newer Interfaces

The component object model dictates that objects update their functionality not by changing the methods within existing interfaces, but by extending new interfaces that encompass new features. In keeping existing interfaces static, an object built on COM can freely extend its services while maintaining compatibility with older applications.

DirectX components follow this philosophy. For example, the DirectDraw component supports three interfaces to access a DirectDrawSurface object: IDirectDrawSurface, IDirectDrawSurface2, IDirectDrawSurface3 and IDirectDrawSurface4. Each version of the interface supports the methods provided by its ancestor, adding new methods to support new features. If your application doesn't need to use these new features, it doesn't need to retrieve newer interfaces. However, to take advantage of features provided by a new interface, you must call the object's IUnknown::QueryInterface method, specifying the globally unique identifier (GUID) of the interface you want to retrieve. Interface GUIDs are declared in the corresponding header file.

The following example shows how to query for a new interface:

    LPDIRECTDRAW    lpDD1;
    LPDIRECTDRAW2   lpDD2;

    ddrval = DirectDrawCreate( NULL, &lpDD1, NULL );
    if( FAILED(ddrval))
        goto ERROROUT;

    // Query for the IDirectDraw2 interface
    ddrval = lpDD1->QueryInterface(IID_IDirectDraw2, (void **)&lpDD2);
    if( FAILED(ddrval))
        goto ERROROUT;

    // Now that we have an IDirectDraw2, release the original interface.
    lpDD1->Release();

In some rare cases, a new interface will not support some methods provided in a previous interface version. The IDirect3DDevice2 interface is an example of this type of interface. If your application requires features provided by an earlier version of an interface, you can query for the earlier version in the same way as shown in the preceding example, using the GUID of the older interface to retrieve it.


Accessing COM Objects by Using C

Any COM interface method can be called from a C program. There are two things to remember when calling an interface method from C:

  • The first parameter of the method always refers to the object that has been created and that invokes the method (the this argument).
  • Each method in the interface is referenced through a pointer to the object's vtable.

The following example creates a surface associated with a DirectDraw object by calling the IDirectDraw4::CreateSurface method with the C programming language:

ret = lpDD->lpVtbl->CreateSurface (lpDD, &ddsd, &lpDDS,
      NULL);

The lpDD parameter references the DirectDraw object associated with the new surface. Incidentally, this method fills a surface-description structure (&ddsd) and returns a pointer to the new surface (&lpDDS).

To call the IDirectDraw4::CreateSurface method, first dereference the DirectDraw object's vtable, and then dereference the method from the vtable. The first parameter supplied in the method is a reference to the DirectDraw object that has been created and which invokes the method.

To illustrate the difference between calling a COM object method in C and C++, the same method in C++ is shown below (C++ implicitly dereferences the lpVtbl parameter and passes the this pointer):

ret = lpDD->CreateSurface(&ddsd, &lpDDS, NULL)


Interface Method Names and Syntax

All COM interface methods described in this document are shown using C++ class names. This naming convention is used for consistency and to differentiate between methods used for different DirectX objects that use the same name, such as QueryInterface, AddRef, and Release. This does not imply that you can use these methods only with C++.

In addition, the syntax provided for the methods uses C++ conventions for consistency. It does not include the this pointer to the interface. When programming in C, the pointer to the interface must be included in each method. The following example shows the C++ syntax for the IDirectDraw4::GetCaps method:

HRESULT GetCaps(
  LPDDCAPS lpDDDriverCaps,
  LPDDCAPS lpDDHELCaps
);

The same example using C syntax looks like this:

HRESULT GetCaps(
  LPDIRECTDRAW4 lpDD,
  LPDDCAPS lpDDDriverCaps,
  LPDDCAPS lpDDHELCaps
);

The lpDD parameter is a pointer to the DirectDraw interface that represents the DirectDraw object.


What's New in DirectX?

Windows NT 5.0 has been renamed to Windows 2000. The DirectX documentation has been changed to reflect the name change; other documentation may not yet reflect the change.

DirectX 6.0 provides more services — and more avenues for innovation — than did DirectX 5.0. (Note that there is no "DirectX 4" — the numbering jumps from version 3 to version 5.) Although this Programmer's Reference contains additional functions and services, all the applications you wrote with previous DirectX APIs will compile and run successfully without changes.

DirectX 6.1 provides the official release of DirectMusic as an API component of DirectX. This version also has a few minor corrections and improvements to other components.

The purpose of this section is to help those of you who are familiar with previous versions of DirectX quickly identify several important areas of this Programmer's Reference that are significantly different. These differences are listed by component.

DirectDraw
DirectDraw for DirectX 6.0 introduces the IDirectDraw4 and IDirectDrawSurface4 interfaces, which include ease-of-use enhancements, as well as private surface data and surface uniqueness values. Primary ease-of-use enhancements include expanded capability reporting for the DirectDraw object and its surfaces. These come in the form of several new capability flags for the DDCAPS structure, and the introduction of the new DDSCAPS2 and DDSURFACEDESC2 surface capability and description structures.

Applications can use the new IDirectDraw4::TestCooperativeLevel method to determine a cooperative level status for DirectDraw. This is helpful when applications need information about when to restore or recreate the surfaces they use. For more information, see Testing Cooperative Levels. In addition, DirectDraw now offers a new cooperative level to improve the performance of Direct3D applications. For more information, see DirectDraw Cooperative Levels and FPU Precision.

A new DirectDraw interface, IDirectDrawGammaControl, enables applications to easily adjust how graphics are displayed without changing the contents of the frame buffer. For more information, see Gamma and Color Controls.

DirectDraw supports multiple monitors on systems running Windows 98 and Windows 2000. For more information, see Multiple Monitor Systems.

DirectSound
The DirectSound documentation has been expanded to include new overviews and tutorials.
DirectMusic
DirectMusic is an entirely new API available as a developer preview in the DirectX 6.0 SDK and as an official release in the DirectX 6.1 SDK.
Direct3D Immediate Mode
Direct3D Immediate Mode now features greatly improved performance, ease-of-use enhancements, and support for new hardware features. Among the most noteworthy are: support for single-pass multiple texture blending, bump mapping, automatic texture cache management, flexible vertex formats and strided vertices, vertex buffers, w-buffering, and stencil buffers (stencil planes).

For much more information about these new features, see Immediate Mode Changes for DirectX 6.0.

Direct3D Retained Mode
Direct3D Retained Mode introduces new interface inheritance semantics and several new interfaces. For more information, see What's New in Direct3D Retained Mode?
DirectInput
The DirectInput documentation has minor corrections and improvements.
DirectPlay
DirectPlay for DirectX 6.0 has a new interface, IDirectPlay4. This interface inherits directly from IDirectPlay3 and by default behaves as IDirectPlay3. All new functionality is enabled through new methods or flags. DirectPlay supports the following new features: guaranteed messaging, asynchronous messaging, message throttling, TCP/IP firewall support, peer-to-peer security, application registration, improved localization support, improved keep-alive support, private service providers, and improved lobby connection features.

For more information about these new features, see What's New in DirectPlay?

DirectSetup
No changes for DirectX 6.0.
AutoPlay
No changes for DirectX 6.0.


Conventions

The following conventions define syntax:

Convention | Meaning
Italic text | Denotes a placeholder or variable. You must provide the actual value. For example, the statement SetCursorPos(X, Y) requires you to substitute values for the X and Y parameters.
Bold text | Denotes a function, structure, macro, interface, method, data type, or other keyword in the programming interface, C, or C++.
[] | Encloses optional parameters.
| | Separates an either/or choice.
... | Specifies that the preceding item may be repeated.
. . . | Represents an omitted portion of a sample application.

In addition, the following typographic conventions are used to help you understand this material:

Convention | Meaning
FULL CAPITALS | Indicates most type and structure names, which also are bold, and constants.
monospace | Sets off code examples and shows syntax spacing.


Further Reading

Further explanation of the graphics and multimedia concepts and terms discussed throughout DirectX, as well as information on Windows programming in general, can be found in the following sources:

  • Bargen, Bradley and Peter Donnelly, Inside DirectX, Microsoft Press, 1998.
  • Begault, Durand R., 3-D Sound for Virtual Reality and Multimedia, Academic Press, 1994.
  • Blinn, James, Jim Blinn's Corner: A Trip Down the Graphics Pipeline, Morgan Kaufmann, 1996.
  • Foley, James D., Computer Graphics: Principles and Practice, Addison-Wesley, 1991 (2nd edition).
  • Hearn, Donald and M. Pauline Baker, Computer Graphics, Prentice-Hall, 1986.
  • Kientzle, Tim, A Programmer's Guide to Sound, Addison-Wesley Developers Press, 1998.
  • Petzold, Charles, Programming Windows 98, Microsoft Press, 1998 (5th edition).
  • Thompson, Nigel, 3D Graphics Programming for Windows 95, Microsoft Press, 1996.
  • Watt, Alan H., and Mark Watt, Advanced Animation and Rendering Techniques, Addison-Wesley, 1992.

Additional sources for the concepts and terms associated with COM can be found in the following sources:

  • Brockschmidt, Kraig, Inside OLE 2, Microsoft Press, 1995 (2nd edition).
  • Rogerson, Dale E., Inside COM, Microsoft Press, 1997.


Debugging DirectX Applications

When using debug builds, in order to ensure that the debugger can find all the relevant symbolic information, the symbol files need to be located as follows:

OS | Debugger | Location for .pdb file | Location for .dbg file
Windows 95 Windows 98 | Visual C++® | same directory as binary | same directory as binary
Windows NT Windows 2000 | Visual C++ | same directory as binary | %SystemRoot%\symbols\<binary ext>\
Windows NT Windows 2000 | NTSD/KD | %SystemRoot%\symbols\<binary ext>\ | %SystemRoot%\symbols\<binary ext>\

Note When debugging with Microsoft® Visual C++® development system on Windows NT/Windows 2000, do not use the WIN32API splitsym development tool. WIN32API splitsym copies private symbolic information from the <binary>.dbg file into the symbol directory under the binary extension (for example, %SystemRoot%\symbols\dll\ ), then deletes the original file from the binary directory. Visual C++ uses relies on finding private symbolic information (<binary>.dbg) file in the same directory as the binary itself, so for debug builds, it is necessary to only copy the private symbolic information and not to delete it. This is only an issue when using Visual C++ with Windows NT/Windows 2000. Consult Visual C++ documentation and Windows NT/Windows 2000 DDK documentation for further debugging information.


Compiling DirectX Samples and Other DirectX Applications

This section provides information about considerations specific to compiling DirectX applications. The following topics are discussed:

  • Preparing for Compilation
  • Component Version Constants


Preparing for Compilation

The samples included in this SDK use Microsoft® Visual C++® project files (MDP files) that describe the appropriate source files, project resources, and linker settings for each sample. However, you may need to make additional preparations to ensure that the samples compile and link properly, or you might need to prepare settings for a new project of your own. (For the samples, developers that use other compilers can reference the generic makefiles included for information about the required libraries, then configure their environment appropriately.) The information provided here applies to the DirectX samples and the DirectX applications you will create.

After opening a project file in Visual C++, you should verify some settings before trying to compile the application. The following descriptions are given in terms of the Microsoft Visual C++ 5.0 and 4.2 options. Previous versions of Microsoft Visual C++ and other compilers have equivalent settings. If you do not use these versions of Microsoft Visual C++, refer to the documentation provided with your development environment for information on changing these settings.

Note The following discussion uses the default installation paths (C:\mssdk\include and C:\mssdk\lib) to describe file locations. Your installation paths might differ.

Include search paths

Make sure the search path for header files is correct, and that the directory for DirectX header files is the first path that the compiler searches. To check the include path, choose Options from the Tools menu, then select the Directories tab. The following dialog box will appear.

The topmost path should indicate the folder that contains the latest DirectX header files. The default path is C:\mssdk\include. If the path is not present, add it to the list and move it to the top of the search list by using the toolbar controls within the Directories tab.

Linker search paths

Check the search paths and search order that the linker uses to search for link libraries. The link search paths are also listed on the Directories tab; choose Options from the Tools menu, then select the Directories tab. When the dialog appears, choose the "Library files" option in the "Show directories for:" drop-down list box. The topmost path should be the folder that contains the latest DirectX link libraries. The default path is C:\mssdk\lib. (Borland link libraries are provided in the Borland folder within the default folder.)

Project link libraries

If you are using the provided sample project files, you shouldn't need to verify these settings, as they are specified with the provided project files. For new applications, choose Settings from the Project menu to make the following dialog box appear. (In Visual C++ 4.2, this is the Settings item on the Build menu.)

All DirectX applications should link to the Dxguid.lib include library, which defines the globally unique identifiers (GUIDs) for all DirectX foundation COM interfaces. (Alternatively, you can define INITGUID prior to all other include and define statements in a single source module.) In addition, verify that the application is linked to the appropriate standard DirectX link libraries. The following table shows the various DirectX foundation components that might be used, and the corresponding link libraries for those components.

Component | Link Library (*.LIB)
DirectDraw | Ddraw.lib
Direct3D Immediate Mode | Ddraw.lib
DirectSound | Dsound.lib
DirectInput | Dinput.lib
DirectSetup | Dsetup.lib
(All components) | Dxguid.lib


Component Version Constants

For backward compatibility with previous versions of DirectX, some DirectX components include variable API element definitions in their header files. Affected elements are typically capability structures or flag sets that are version specific. Parts of some header files are surrounded by preprocessor conditionals that cause the preprocessor to effectively "filter-out" unneeded definitions. The value of the defined constant identifies a specific version of the component; if no value is defined, the headers set a value that identifies the DirectX version for which the header file was written. An example from the DirectDraw header file, ddraw.h, is shown here:

#ifndef   DIRECTDRAW_VERSION
#define   DIRECTDRAW_VERSION 0x0600
#endif /* DIRECTDRAW_VERSION */

The following table includes the components that use these version constants, their labels, and their default value for this release of DirectX.

Component | Label | Value
DirectDraw | DIRECTDRAW_VERSION | 0x0600
Direct3D Immediate Mode | DIRECT3D_VERSION | 0x0600
DirectInput | DIRECTINPUT_VERSION | 0x0600

You can define other values for these constants to use newer versions of the header files with previous versions of the components. For example, to use the latest headers to compile against the DirectX 3.0 version of DirectDraw, you would define DIRECTDRAW_VERSION to be 0x0300. You can set the value for the constant in your development environment, or you can change the value in the header file itself.


DirectDraw

This section provides information about the DirectDraw® component of the DirectX® application programming interface (API). Information is divided into the following groups:

  • About DirectDraw
  • Why Use DirectDraw?
  • Getting Started: Basic Graphics Concepts
  • DirectDraw Architecture
  • DirectDraw Essentials
  • DirectDraw Tutorials
  • DirectDraw Reference
  • DirectDraw Samples


About DirectDraw

DirectDraw® is the component of the DirectX® application programming interface (API) that allows you to directly manipulate display memory, the hardware blitter, hardware overlay support, and flipping surface support. DirectDraw provides this functionality while maintaining compatibility with existing Microsoft® Windows®-based applications and device drivers.

DirectDraw is a software interface that provides direct access to display devices while maintaining compatibility with the Windows graphics device interface (GDI). It is not a high-level application programming interface (API) for graphics. DirectDraw provides a device-independent way for games and Windows subsystem software, such as three-dimensional (3-D) graphics packages and digital video codecs, to gain access to the features of specific display devices.

DirectDraw works with a wide variety of display hardware, ranging from simple SVGA monitors to advanced hardware implementations that provide clipping, stretching, and non-RGB color format support. The interface is designed so that your applications can enumerate the capabilities of the underlying hardware and then use any supported hardware-accelerated features. Features that are not implemented in hardware are emulated by DirectX.

DirectDraw provides device-dependent access to display memory in a device-independent way. Essentially, DirectDraw manages display memory. Your application need only recognize some basic device dependencies that are standard across hardware implementations, such as RGB and YUV color formats and the pitch between raster lines. You need not call specific procedures to use the blitter or manipulate palette registers. Using DirectDraw, you can manipulate display memory with ease, taking full advantage of the blitting and color decompression capabilities of different types of display hardware without becoming dependent on a particular piece of hardware.

DirectDraw provides world-class game graphics on computers running Windows 95 and later and Windows NT® version 4.0 or Windows 2000.


Why Use DirectDraw?

The DirectDraw component brings many powerful features to you, the Windows graphics programmer:

  • The hardware abstraction layer (HAL) of DirectDraw provides a consistent interface through which to work directly with the display hardware, getting maximum performance.
  • DirectDraw assesses the video hardware's capabilities, making use of special hardware features whenever possible. For example, if your video card supports hardware blitting, DirectDraw delegates blits to the video card, greatly increasing performance. Additionally, DirectDraw provides a hardware emulation layer (HEL) to support features when the hardware does not.
  • DirectDraw exists under Windows, gaining the advantage of 32-bit memory addressing and a flat memory model that the operating system provides. DirectDraw presents video and system memory as large blocks of storage, not as small segments. If you've ever used segment:offset addressing, you will quickly begin to appreciate this "flat" memory model.
  • DirectDraw makes it easy for you to implement page flipping with multiple back buffers in full-screen applications. For more information, see Page Flipping and Back Buffering.
  • Support for clipping in windowed or full-screen applications.
  • Support for 3-D z-buffers.
  • Support for hardware-assisted overlays with z-ordering.
  • Access to image-stretching hardware.
  • Simultaneous access to standard and enhanced display-device memory areas.
  • Other features include custom and dynamic palettes, exclusive hardware access, and resolution switching.

These features combine to make it possible for you to write applications that easily outperform standard Windows GDI-based applications and even MS-DOS applications.


Getting Started: Basic Graphics Concepts

This section provides an overview of graphics programming with DirectDraw. Each concept discussed here begins with a non-technical overview, followed by some specific information about how DirectDraw supports it.

You don't need to be a graphics guru to benefit from this overview—in fact, if you are one you might want to skip this section entirely and move on to the more detailed information in the DirectDraw Essentials section. If you're familiar with Windows programming in C and C++, you won't have difficulty digesting this information. When you finish reading these topics, you will have a solid understanding of basic DirectDraw graphics programming concepts.

The following topics are discussed:

  • Device-Independent Bitmaps
  • Drawing Surfaces
  • Blitting
  • Page Flipping and Back Buffering
  • Introduction to Rectangles


Device-Independent Bitmaps

Windows, and therefore DirectX, uses the device-independent bitmap (DIB) as its native graphics file format. Essentially, a DIB is a file that contains information describing an image's dimensions, the number of colors it uses, values describing those colors, and data that describes each pixel. Additionally, a DIB contains some lesser-used parameters, like information about file compression, significant colors (if all are not used), and physical dimensions of the image (in case it will end up in print). DIB files usually have the .bmp file extension, although they might occasionally have a .dib extension.

Because the DIB is so pervasive in Windows programming, the Platform SDK already contains many functions that you can use with DirectX. For example, the following application-defined function, taken from the Ddutil.cpp file that comes with the DirectX APIs in the Platform SDK, combines Win32® and DirectX functions to load a DIB onto a DirectX surface.

extern "C" IDirectDrawSurface * DDLoadBitmap(IDirectDraw *pdd,
    LPCSTR szBitmap, int dx, int dy)
{
    HBITMAP             hbm;
    BITMAP              bm;
    DDSURFACEDESC       ddsd;
    IDirectDrawSurface *pdds;

    //
    //  This is the Win32 part.
    //  Try to load the bitmap as a resource.
    //  If that fails, try it as a file.
   //
    hbm = (HBITMAP)LoadImage(
            GetModuleHandle(NULL), szBitmap,
            IMAGE_BITMAP, dx, dy, LR_CREATEDIBSECTION);

    if (hbm == NULL)
        hbm = (HBITMAP)LoadImage(
                NULL, szBitmap, IMAGE_BITMAP, dx, dy,
                LR_LOADFROMFILE|LR_CREATEDIBSECTION);

    if (hbm == NULL)
        return NULL;

    //
    // Get the size of the bitmap.
    //
    GetObject(hbm, sizeof(bm), &bm);

    //
    // Now, return to DirectX function calls.
    // Create a DirectDrawSurface for this bitmap.
    //
    ZeroMemory(&ddsd, sizeof(ddsd));
    ddsd.dwSize = sizeof(ddsd);
    ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT |DDSD_WIDTH;
    ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
    ddsd.dwWidth = bm.bmWidth;
    ddsd.dwHeight = bm.bmHeight;

    if (pdd->CreateSurface(&ddsd, &pdds, NULL) != DD_OK)
        return NULL;

    DDCopyBitmap(pdds, hbm, 0, 0, 0, 0);

    DeleteObject(hbm);

    return pdds;
}

For more detailed information about DIB files, see the Platform SDK.


Drawing Surfaces

Drawing surfaces receive video data to eventually be displayed on the screen as images (bitmaps, to be exact). In most Windows programs, you get access to the drawing surface using a Win32 function such as GetDC, which stands for get the device context (DC). After you have the device context, you can start painting the screen. However, Win32 graphics functions are provided by an entirely different part of the system, the graphics device interface (GDI). The GDI is a system component that provides an abstraction layer that enables standard Windows applications to draw to the screen.

The drawback of GDI is that it wasn't designed for high-performance multimedia software, it was made to be used by business applications like word processors and spreadsheet applications. GDI provides access to a video buffer in system memory, not video memory, and doesn't take advantage of special features that some video cards provide. In short, GDI is great for most business applications, but its performance is too slow for multimedia or game software.

On the other hand, DirectDraw can give you drawing surfaces that represent actual video memory. This means that when you use DirectDraw, you can write directly to the memory on the video card, making your graphics routines extremely fast. These surfaces are represented as contiguous blocks of memory, making it easy to perform addressing within them.

For more detailed information, see Surfaces.


Blitting

The term blit is shorthand for "bit block transfer," which is the process of transferring blocks of data from one place in memory to another. Graphics programmers use blitting to transfer graphics from one place in memory to another. Blits are often used to perform sprite animation, which is discussed later.

For more information on blitting in DirectDraw, see Blitting to Surfaces.


Page Flipping and Back Buffering

Page flipping is key in multimedia, animation, and game software. Software page flipping is analogous to the way animation can be done with a pad of paper. On each page the artist changes the figure slightly, so that when you flip between sheets rapidly the drawing appears animated.

Page flipping in software is very similar to this process. Initially, you set up a series of DirectDraw surfaces that are designed to "flip" to the screen the way artist's paper flips to the next page. The first surface is referred to as the primary surface, and the surfaces behind it are called back buffers . Your application writes to a back buffer, then flips the primary surface so that the back buffer appears on screen. While the system is displaying the image, your software is again writing to a back buffer. The process continues as long as you're animating, allowing you to animate images quickly and efficiently.

DirectDraw makes it easy for you to set up page flipping schemes, from a relatively simple double-buffered scheme (a primary surface with one back buffer) to more sophisticated schemes that add additional back buffers. For more information see DirectDraw Tutorials and Flipping Surfaces.


Introduction to Rectangles

Throughout DirectDraw and Windows programming, objects on the screen are referred to in terms of bounding rectangles. The sides of a bounding rectangle are always parallel to the sides of the screen, so the rectangle can be described by two points, the top-left corner and bottom-right corner. Most applications use the RECT structure to carry information about a bounding rectangle to use when blitting to the screen or performing hit detection. The RECT structure has the following definition:

typedef struct tagRECT {
    LONG    left;    // This is the top-left corner's x-coordinate.
    LONG    top;     // The top-left corner's y-coordinate.
    LONG    right;   // The bottom-right corner's x-coordinate.
    LONG    bottom;  // The bottom-right corner's y-coordinate.
} RECT, *PRECT, NEAR *NPRECT, FAR *LPRECT;

In the preceding example, the left and top members are the x- and y-coordinates of a bounding rectangle's top-left corner. Similarly, the right and bottom members make up the coordinates of the bottom-right corner. The following diagram illustrates how you can visualize these values.

In the interest of efficiency, consistency, and ease of use, all DirectDraw blitting functions work with rectangles. However, you can create the illusion of nonrectangular blit operations by using transparent blitting. For more information, see Transparent Blitting.


DirectDraw Architecture

This section contains general information about the relationship between the DirectDraw component and the rest of DirectX, the operating system, and the system hardware. The following topics are discussed:

  • Architectural Overview for DirectDraw
  • DirectDraw Object Types
  • Hardware Abstraction Layer (HAL)
  • Software Emulation
  • System Integration


Architectural Overview for DirectDraw

Multimedia software requires high-performance graphics. Through DirectDraw, Microsoft enables a much higher level of efficiency and speed in graphics-intensive applications for Windows than is possible with GDI, while maintaining device independence. DirectDraw provides tools to perform such key tasks as:

  • Manipulating multiple display surfaces
  • Accessing the video memory directly
  • Page flipping
  • Back buffering
  • Managing the palette
  • Clipping

Additionally, DirectDraw enables you to query the display hardware's capabilities at run time, then provide the best performance possible given the host computer's hardware capabilities.

As with other DirectX components, DirectDraw uses the hardware to its greatest possible advantage, and provides software emulation for most features when hardware support is unavailable. Device independence is possible through use of the hardware abstraction layer, or HAL. For more information about the HAL, see the hardware abstraction layer .

The DirectDraw component provides services through COM-based interfaces. In the most recent iteration, these interfaces are IDirectDraw4, IDirectDrawSurface4, IDirectDrawPalette, IDirectDrawClipper, and IDirectDrawVideoPort. Note that, in addition to these interfaces, DirectDraw continues to support all previous versions. The DirectDraw component doesn't expose an IDirectDraw3 interface, the interface versions skipped from IDirectDraw2 to IDirectDraw4.

For more information about COM concepts that you should understand to create applications with the DirectX APIs in the Platform SDK, see DirectX and the Component Object Model.

The DirectDraw object represents the display adapter and exposes its methods through the IDirectDraw, IDirectDraw2, and IDirectDraw4 interfaces. In most cases you will use the DirectDrawCreate function to create a DirectDraw object, but you can also create one with the CoCreateInstance COM function. For more information, see Creating DirectDraw Objects by Using CoCreateInstance.

After creating a DirectDraw object, you can create surfaces for it by calling the IDirectDraw4::CreateSurface method. Surfaces represent the memory on the display hardware, but can exist on either video memory or system memory. DirectDraw extends support for palettes, clipping (useful for windowed applications), and video ports through its other interfaces.


DirectDraw Object Types

You can think of DirectDraw as being composed of several objects that work together. This section briefly describes the objects you use when working with the DirectDraw component, organized by object type. For detailed information, see DirectDraw Essentials.

The DirectDraw component uses the following objects:

DirectDraw object
The DirectDraw object is the heart of all DirectDraw applications. It's the first object you create, and you use it to make all other related objects. You create a DirectDraw object by calling the DirectDrawCreate function. DirectDraw objects expose their functionality through the IDirectDraw, IDirectDraw2, and IDirectDraw4 interfaces. For more information, see The DirectDraw Object.
DirectDrawSurface object
The DirectDrawSurface object (casually referred to as a "surface") represents an area in memory that holds data to be displayed on the monitor as images or moved to other surfaces. You usually create a surface by calling the IDirectDraw4::CreateSurface method of the DirectDraw object with which it will be associated. DirectDrawSurface objects expose their functionality through the IDirectDrawSurface, IDirectDrawSurface2, IDirectDrawSurface3, and IDirectDrawSurface4 interfaces. For more information, see Surfaces.
DirectDrawPalette object
The DirectDrawPalette object (casually referred to as a "palette") represents a 16- or 256-color indexed palette to be used with a surface. It contains a series of indexed RGB triplets that describe colors associated with values within a surface. You do not use palettes with surfaces that use a pixel format depth greater than 8 bits. You can create a DirectDrawPalette object by calling the IDirectDraw4::CreatePalette method. DirectDrawPalette objects expose their functionality through the IDirectDrawPalette interface. For more information, see Palettes.
DirectDrawClipper object
The DirectDrawClipper object (casually referred to as a "clipper") helps you prevent blitting to certain portions of a surface or beyond the bounds of a surface. You can create a clipper by calling the IDirectDraw4::CreateClipper method. DirectDrawClipper objects expose their functionality through the IDirectDrawClipper interface. For more information, see Clippers.
DirectDrawVideoPort object
The DirectDrawVideoPort object represents video-port hardware present in some systems. This hardware allows direct access to the frame buffer without accessing the CPU or using the PCI bus. You can create a DirectDrawVideoPort object by calling a QueryInterface method for the DirectDraw object, specifying the IID_IDDVideoPortContainer reference identifier. DirectDrawVideoPort objects expose their functionality through the IDDVideoPortContainer and IDirectDrawVideoPort interfaces. For more information, see Video Ports.


Hardware Abstraction Layer (HAL)

DirectDraw provides device independence through the hardware abstraction layer (HAL). The HAL is a device-specific interface, provided by the device manufacturer, that DirectDraw uses to work directly with the display hardware. Applications never interact with the HAL. Rather, with the infrastructure that the HAL provides, DirectDraw exposes a consistent set of interfaces and methods that an application uses to display graphics. The device manufacturer implements the HAL in a combination of 16-bit and 32-bit code under Windows. Under Windows NT/Windows 2000, the HAL is always implemented in 32-bit code. The HAL can be part of the display driver or a separate DLL that communicates with the display driver through a private interface that driver's creator defines.

The DirectDraw HAL is implemented by the chip manufacturer, board producer, or original equipment manufacturer (OEM). The HAL implements only device-dependent code and performs no emulation. If a function is not performed by the hardware, the HAL does not report it as a hardware capability. Additionally, the HAL does not validate parameters; DirectDraw does this before the HAL is invoked.


Software Emulation

When the hardware does not support a feature through the hardware abstraction layer (HAL), DirectDraw attempts to emulate it. This emulated functionality is provided through the hardware emulation layer (HEL). The HEL presents its capabilities to DirectDraw just as the HAL would. And, as with the HAL, applications never work directly with the HEL. The result is transparent support for almost all major features, regardless of whether a given feature is supported by hardware or through the HEL.

Obviously, software emulation cannot equal the performance that hardware features provide. You can query for the features the hardware supports by using the IDirectDraw4::GetCaps method. By examining these capabilities during application initialization, you can adjust application parameters to provide optimum performance over varying levels of hardware performance.

In some cases, certain combinations of hardware supported features and emulation can result in slower performance than emulation alone. For example, if the display device driver supports DirectDraw but not stretch blitting, noticeable performance losses will occur when stretch blitting from video memory surfaces. This happens because video memory is often slower than system memory, forcing the CPU to wait when accessing video memory surfaces. If your application uses a feature that isn't supported by the hardware, it is sometimes best to create surfaces in system memory, thereby avoiding performance losses created when the CPU accesses video memory.

For more information, see Hardware Abstraction Layer (HAL).


System Integration

The following diagram shows the relationships between DirectDraw, the graphics device interface (GDI), the hardware abstraction layer (HAL), the hardware emulation layer (HEL) and the hardware.

As the preceding diagram shows, a DirectDraw object exists alongside GDI, and both have direct access to the hardware through a device-dependent abstraction layer. Unlike GDI, DirectDraw makes use of special hardware features whenever possible. If the hardware does not support a feature, DirectDraw attempts to emulate it by using the HEL. DirectDraw can provide surface memory in the form of a device context, making it possible for you to use GDI functions to work with surface objects.


DirectDraw Essentials

This section contains general information about the DirectDraw® component of DirectX®. Information is organized into the following groups:

  • Cooperative Levels
  • Display Modes
  • The DirectDraw Object
  • Surfaces
  • Palettes
  • Clippers
  • Multiple Monitor Systems
  • Advanced DirectDraw Topics


Cooperative Levels

In the following topics, this section introduces the concept of cooperative levels and describes some common usage situations:

  • About Cooperative Levels
  • Testing Cooperative Levels


About Cooperative Levels

Cooperative levels describe how DirectDraw interacts with the display and how it reacts to events that might affect the display. Use the IDirectDraw4::SetCooperativeLevel method to set cooperative level of DirectDraw. For the most part, you use DirectDraw cooperative levels to determine whether your application runs as a full-screen program with exclusive access to the display or as a windowed application. However, DirectDraw cooperative levels can also have the following effects:

  • Enable DirectDraw to use Mode X resolutions. For more information, see Mode X and Mode 13 Display Modes.
  • Prevent DirectDraw from releasing exclusive control of the display or rebooting if the user presses CTRL + ALT + DEL (exclusive mode only).
  • Enable DirectDraw to minimize or maximize the application in response to activation events.

The normal cooperative level indicates that your DirectDraw application will operate as a windowed application. At this cooperative level you won't be able to change the primary surface's palette or perform page flipping.

Because applications can use DirectDraw with multiple windows, IDirectDraw4::SetCooperativeLevel does not require a window handle to be specified if the application is requesting the DDSCL_NORMAL mode. By passing a NULL to the window handle, all of the windows can be used simultaneously in normal Windows mode.

At the full-screen and exclusive cooperative level, you can use the hardware to its fullest. In this mode, you can set custom and dynamic palettes, change display resolutions, and implement page flipping. The exclusive (full-screen) mode does not prevent other applications from allocating surfaces, nor does it exclude them from using DirectDraw or GDI. However, it does prevent applications other than the one currently with exclusive access from changing the display mode or palette.

DirectDraw takes control of window activation events for full-screen, exclusive mode applications, sending WM_ACTIVATEAPP messages to the window handle registered through the SetCooperativeLevel method as needed. DirectDraw only sends activation events to the top-level window. If your application creates child windows that require activation event messages, it is your responsibility to subclass the child windows.

SetCooperativeLevel maintains a binding between a process and a window handle. If SetCooperativeLevel is called once in a process, a binding is established between the process and the window. If it is called again in the same process with a different non-null window handle, it returns the DDERR_HWNDALREADYSET error value. Some applications may receive this error value when DirectSound® specifies a different window handle than DirectDraw—they should specify the same, top-level application window handle.

Note Developers using Microsoft Foundation Classes (MFC) should keep in mind that the window handle given to the SetCooperativeLevel method should identify the application's top-level window, not a derived child window. To retrieve your MFC application's top level window handle, you could use the following code:

    HWND hwndTop = AfxGetMainWnd()->GetSafeHwnd();

See also, Multiple Monitor Systems.


Testing Cooperative Levels

Developers often use messages such as WM_ACTIVATEAPP and WM_DISPLAYCHANGE as notifications that their applications should restore or re-create the surfaces being used. In some cases, applications take action when they don't need to, or don't take action when they should. The IDirectDraw4::TestCooperativeLevel method makes it possible for your application to retrieve more information about the DirectDraw object's cooperative level and take appropriate steps to continue execution without mishap.

The TestCooperativeLevel method succeeds, returning DD_OK, if your application can restore its surfaces (if it has not already done so) and continue to execute. Failure codes, on the other hand, are interpreted differently depending on the cooperative-level your application uses:

Full-screen applications

Full-screen applications receive the DDERR_NOEXCLUSIVEMODE return value if they lose exclusive device access–for example, if the user pressed ALT+TAB to switch away from the current application. In this case, applications might call TestCooperativeLevel in a loop, exiting only when the method returns DD_OK (meaning that exclusive mode was returned). In the body of the loop, the application should relinquish control of the CPU to prevent using cycles unnecessarily. Windows supports functions such as the WaitMessage or Sleep Win32 functions for this purpose.

Any existing surfaces should be restored by calling the IDirectDrawSurface4::Restore or IDirectDraw4::RestoreAllSurfaces methods, and their contents reloaded before displaying them.

Windowed applications

Windowed applications (those that use the normal cooperative level) receive DDERR_EXCLUSIVEMODEALREADYSET if another application has taken exclusive device access. In this case, no action should be taken until the application with exclusive access loses it. This situation is similar to the case for a full-screen application; a windowed application might loop until TestCooperativeLevel returns DD_OK before restoring and reloading its surfaces. As mentioned previously, in a loop like this applications should avoid unnecessarily using CPU cycles by relinquishing CPU control periodically during the loop.

The TestCooperativeLevel method returns DDERR_WRONGMODE to windowed applications when the display mode has changed. In this case, the application should destroy and re-create any surfaces before continuing execution.


Display Modes

This section contains general information about DirectDraw display modes. The following topics are discussed:

  • About Display Modes
  • Determining Supported Display Modes
  • Setting Display Modes
  • Restoring Display Modes
  • Mode X and Mode 13 Display Modes
  • Support for High Resolutions and True-Color Bit Depths


About Display Modes

A display mode is a hardware setting that describes the dimensions and bit-depth of graphics that the display hardware sends to the monitor from the primary surface. Display modes are described by their defining characteristics: width, height, and bit-depth. For instance, most display adapters can display graphics 640 pixels wide and 480 pixels tall, where each pixel is 8 bits of data. In shorthand, this display mode is called 640×480×8. As the dimensions of a display mode get larger or as the bit-depth increases, more display memory is required.

There are two types of display modes: palettized and non-palettized. For palettized display modes, each pixel is a value representing an index into an associated palette. The bit depth of the display mode determines the number of colors that can be in the palette. For instance, in an 8-bit palettized display mode, each pixel is a value from 0 to 255. In such a display mode, the palette can contain 256 entries.

Non-palettized display modes, as their name states, do not use palettes. The bit depth of a non-palettized display mode indicates the total number of bits that are used to describe a pixel.

The primary surface and any surfaces in the primary flipping chain match the display mode's dimensions, bit depth and pixel format. For more information, see Pixel Formats.


Determining Supported Display Modes

Because display hardware varies, not all devices will support all display modes. To determine the display modes supported on a given system, call the IDirectDraw4::EnumDisplayModes method. By setting the appropriate values and flags, the EnumDisplayModes method can list all supported display modes or confirm that a single display mode that you specify is supported. The method's first parameter, dwFlags, controls extra options for the method; in most cases, you will set dwFlags to 0 to ignore extra options. The second parameter, lpDDSurfaceDesc, is the address of a DDSURFACEDESC2 structure that describes a given display mode to be confirmed; you'll usually set this parameter to NULL to request that all modes be listed. The third parameter, lpContext, is a pointer that you want DirectDraw to pass to your callback function; if you don't need any extra data in the callback function, use NULL here. Last, you set the lpEnumModesCallback parameter to the address of the callback function that DirectDraw will call for each supported mode.

The callback function you supply when calling EnumDisplayModes must match the prototype for the EnumModesCallback function. For each display mode that the hardware supports, DirectDraw calls your callback function passing two parameters. The first parameter is the address of a DDSURFACEDESC2 structure that describes one supported display mode, and the second parameter is the address of the application-defined data you specified when calling EnumDisplayModes, if any.

Examine the values in the DDSURFACEDESC2 structure to determine the display mode it describes. The key structure members are the dwWidth, dwHeight, and ddpfPixelFormat members. The dwWidth and dwHeight members describe the display mode's dimensions, and the ddpfPixelFormat member is a DDPIXELFORMAT structure that contains information about the mode's bit depth.

The DDPIXELFORMAT structure carries information describing the mode's bit depth and tells you whether or not the display mode uses a palette. If the dwFlags member contains the DDPF_PALETTEINDEXED1, DDPF_PALETTEINDEXED2, DDPF_PALETTEINDEXED4, or DDPF_PALETTEINDEXED8 flag, the display mode's bit depth is 1, 2, 4 or 8 bits, and each pixel is an index into an associated palette. If dwFlags contains DDPF_RGB, then the display mode is non-palettized and its bit depth is provided in the dwRGBBitCount member of the DDPIXELFORMAT structure.


Setting Display Modes

You can set the display mode by using the IDirectDraw4::SetDisplayMode method. The SetDisplayMode method accepts four parameters that describe the dimensions, bit depth, and refresh rate of the mode to be set. The method uses a fifth parameter to indicate special options for the given mode; this is currently only used to differentiate between Mode 13 and the Mode X 320×200×8 display mode.

Although you can specify the desired display mode's bit depth, you cannot specify the pixel format that the display hardware will use for that bit depth. To determine the RGB bit masks that the display hardware uses for the current bit depth, call IDirectDraw4::GetDisplayMode after setting the display mode. If the current display mode is not palettized, you can examine the mask values in the dwRBitMask, dwGBitMask, and dwBBitMask members to determine the correct red, green, and blue bits. For more information, see Pixel Format Masks.

Modes can be changed by more than one application as long as they are all sharing a display card. You can change the bit depth of the display mode only if your application has exclusive access to the DirectDraw object. All DirectDrawSurface objects lose surface memory and become inoperative when the mode is changed. A surface's memory must be reallocated by using the IDirectDrawSurface4::Restore method.

The DirectDraw exclusive (full-screen) mode does not bar other applications from allocating DirectDrawSurface objects, nor does it exclude them from using DirectDraw or GDI functionality. However, it does prevent applications other than the one that obtained exclusive access from changing the display mode or palette.

Note You can only call the IDirectDraw4::SetDisplayMode method from the thread that created the application window. For single threaded applications (the vast majority), this restriction isn't an issue.


Restoring Display Modes

You can explicitly restore the display hardware to its original mode by calling the IDirectDraw4::RestoreDisplayMode method. If the display mode was set by calling IDirectDraw4::SetDisplayMode and your application takes the exclusive cooperative level, the original display mode is reset automatically when you set the application's cooperative level back to normal. (This behavior was first offered in the IDirectDraw2 interface, and is offered by all newer versions of the interface.)

If you're using the IDirectDraw interface, you must always explicitly restore the display mode by using the RestoreDisplayMode method.


Mode X and Mode 13 Display Modes

DirectDraw supports both Mode 13 and Mode X display modes. Mode 13 is the linear unflippable 320×200×8 bits per pixel palettized mode known widely by its hexadecimal BIOS mode number: 13. For more information, see Mode 13 Support. Mode X is a hybrid display mode derived from the standard VGA Mode 13. This mode allows the use of up to 256 kilobytes (KB) of display memory (rather than the 64 KB allowed by Mode 13) by using the VGA display adapter's EGA multiple video plane system.

DirectDraw provides two Mode X modes (320×200×8 and 320×240×8) for all display cards. Some cards also support linear low-resolution modes. In linear low-resolution modes, the primary surface can be locked and directly accessed. This is not possible in Mode X modes.

Mode X modes are available only if an application uses the DDSCL_ALLOWMODEX, DDSCL_FULLSCREEN, and DDSCL_EXCLUSIVE flags when calling the IDirectDraw4::SetCooperativeLevel method. If DDSCL_ALLOWMODEX is not specified, the IDirectDraw4::EnumDisplayModes method will not enumerate Mode X modes, and the IDirectDraw4::SetDisplayMode method will fail if a Mode X mode is requested.

Windows 95 and Windows NT/Windows 2000 do not natively support Mode X modes; therefore, when your application is in a Mode X mode, you cannot use the IDirectDrawSurface4::Lock or IDirectDrawSurface4::Blt methods to lock or blit to the primary surface. You also cannot use either the IDirectDrawSurface4::GetDC method on the primary surface, or GDI with a screen DC. Mode X modes are indicated by the DDSCAPS_MODEX flag in the DDSCAPS2 structure, which is part of the DDSURFACEDESC2 structure returned by the IDirectDrawSurface4::GetCaps and IDirectDraw4::EnumDisplayModes methods.


Support for High Resolutions and True-Color Bit Depths

DirectDraw supports all of the screen resolutions and depths supported by the display device driver. DirectDraw allows an application to change the mode to any one supported by the computer's display driver, including all supported 24- and 32-bpp (true-color) modes.

DirectDraw also supports HEL blitting in true-color surfaces. If the display device driver supports blitting at these resolutions, the hardware blitter will be used for display-memory-to-display-memory blits. Otherwise, the HEL will be used to perform the blits.

DirectDraw checks a list of known display modes against the display restrictions of the installed monitor. If DirectDraw determines that the requested mode is not compatible with the monitor, the call to the IDirectDraw4::SetDisplayMode method fails. Only modes that are supported on the installed monitor will be enumerated when you call the IDirectDraw4::EnumDisplayModes method.


The DirectDraw Object

This section contains information about DirectDraw objects and how you can manipulate them through their IDirectDraw, IDirectDraw2, or IDirectDraw4 interfaces. The following topics are discussed:

  • What Are DirectDraw Objects?
  • What's New in IDirectDraw4?
  • Parent and Child Object Lifetimes
  • Multiple DirectDraw Objects per Process
  • Creating DirectDraw Objects by Using CoCreateInstance


What Are DirectDraw Objects?

The DirectDraw object is the heart of all DirectDraw applications and is an integral part of Direct3D® applications as well. It is the first object you create and, through it, you create all other related objects. Typically, you create a DirectDraw object by calling the DirectDrawCreate function, which returns an IDirectDraw interface. If you want to work with a different iteration of the interface (such as IDirectDraw4) to take advantage of new features it provides, you can query for it. (See Getting an IDirectDraw4 Interface.) Note that you can create multiple DirectDraw objects, one for each display device installed in a system.

The DirectDraw object represents the display device and makes use of hardware acceleration if the display device for which it was created supports hardware acceleration. Each unique DirectDraw object can manipulate the display device and create surfaces, palettes, and clipper objects that are dependent on (or are, "connected to") the object that created them. For example, to create surfaces, you call the IDirectDraw4::CreateSurface method. Or, if you need a palette object to apply to a surface, call the IDirectDraw4::CreatePalette method. Additionally, the IDirectDraw4 interface exposes similar methods to create clipper objects.

You can create more than one instance of a DirectDraw object at a time. The simplest example of this is using two monitors on a Windows 95 or Windows NT 4.0 and earlier system. Although these operating systems don't support dual monitors on their own, it is possible to write a DirectDraw HAL for each display device. The display device Windows and GDI recognizes is the one that will be used when you create the instance of the default DirectDraw object. The display device that Windows and GDI do not recognize can be addressed by another, independent DirectDraw object that must be created by using the second display device's globally unique identifier (GUID). This GUID can be obtained by using the DirectDrawEnumerate function.

The DirectDraw object manages all of the objects it creates. It controls the default palette (if the primary surface is in 8-bits-per-pixel mode), the default color key, and the hardware display mode. It tracks what resources have been allocated and what resources remain to be allocated.


What's New in IDirectDraw4?

This section details new features provided by the IDirectDraw4 interface and describes it's new features or how it behaves differently than its predecessor, IDirectDraw2 (there is no IDirectDraw3 interface). The following topics are discussed:

  • New Features in IDirectDraw4
  • Getting an IDirectDraw4 Interface

The most obvious difference between the IDirectDraw4 interface and its predecessors is how it works with surfaces—how surfaces are described and which interfaces it automatically provides to access them. All of the surface-related methods in the new interface accept slightly different parameters than their counterparts in former interface versions. Wherever an IDirectDraw2 interface method might accept a DDSURFACEDESC structure or retrieve an IDirectDrawSurface3 interface, the methods of IDirectDraw4 accept a DDSURFACEDESC2 structure and retrieve an IDirectDrawSurface4 interface instead.

Another behavioral change that IDirectDraw4 introduces affects the lifetimes of child objects with respect to their parent DirectDraw object. For more information, see Parent and Child Object Lifetimes.


New Features in IDirectDraw4

The IDirectDraw4 interface extends previous iterations by adding several methods that provide improved surface management and ease of use

The IDirectDraw4 interface exposes the new IDirectDraw4::RestoreAllSurfaces method, which restores all of the surfaces created by a DirectDraw with a single call.

Additionally, you can now retrieve a surface's IDirectDrawSurface4 interface from a Windows device context by using the IDirectDraw4::GetSurfaceFromDC method.


Getting an IDirectDraw4 Interface

The Component Object Model on which DirectX is built specifies that an object can provide new functionality through new interfaces, without affecting backward compatibility. To this end, the IDirectDraw4 interface supersedes the IDirectDraw2 interface. This new interface can be obtained by using the IUnknown::QueryInterface method, as the following C++ example shows:

// Create an IDirectDraw4 interface.
LPDIRECTDRAW  lpDD;
LPDIRECTDRAW4 lpDD4;

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_IDirectDraw4,
    (LPVOID *)&lpDD4);
if(ddrval != DD_OK)
    return;

The preceding example creates a DirectDraw object, then calls the IUnknown::QueryInterface method of the IDirectDraw interface it received to create an IDirectDraw4 interface.

After getting an IDirectDraw4 interface, you can begin calling its methods to take advantage of new features, performance improvements, and behavioral differences. Because some methods might change with the release of a new interface, mixing methods from an interface and its replacement (between IDirectDraw2 and IDirectDraw4, for example) can cause unpredictable results.


Parent and Child Object Lifetimes

All objects you'll use in DirectDraw programming—the DirectDraw object, surfaces, palettes, clippers, and such—only exist in memory for as long as another object, such as an application, needs them. The time that passes from the moment when an object is created and placed in memory to when it is released and subsequently removed from memory is known as the object's lifetime. The Component Object Model (COM) followed by all DirectX components dictates that an object must keep track of how many other objects require its services. This number, known as a reference count, determines the object's lifetime. COM also dictates that an object expose the IUnknown::AddRef and IUnknown::Release methods to enable applications to explicitly manage its reference count; make sure you use these methods in accordance to COM rules.

You aren't the only one who is using the IUnknown methods to manage reference counts for objects—DirectDraw objects use them internally, too. When you use the IDirectDraw4 interface (in contrast to IDirectDraw2 or IDirectDraw) to create a "child" object like a surface, the child uses the IUnknown::AddRef method of the "parent" DirectDraw object to increment the parent's reference count.

When your application no longer needs an object, call the Release method to decrement its reference count. When the count reaches zero, the object is removed from memory. When a child object's reference count reaches zero, it calls the parent's IUnknown::Release method to indicate that there is one less object who will be needing the parent's services.

Implicitly allocated objects, such as the back-buffer surfaces in a flipping chain that you create with a single IDirectDraw4::CreateSurface call, are automatically deallocated when their parent DirectDrawSurface object is released. Also, you can only release a DirectDraw object from the thread that created the application window. For single-threaded applications, this restriction obviously doesn't apply, as there is only one thread. If your application created a primary flipping chain of two surfaces (created by a single CreateSurface call) that used an attached DirectDrawClipper object, the code to release these objects safely might look like:

// For this example, the g_lpDDraw, g_lpDDSurface, and
// g_lpDDClip are valid pointers to objects.
void ReleaseDDrawObjects(void)
{
    // If the DirectDraw object pointer is valid,
    // it should be safe to release it and the objects it owns.
    if(g_lpDDraw)
    {
        // Release the DirectDraw object. (This call wouldn't
        // be safe if the children were created through IDirectDraw2
        // or IDirectDraw. See the following note for
        // more information)
        g_lpDDraw->Release(), g_lpDDraw = NULL;

        // Now, release the clipper that is attached to the surfaces.
        if(g_lpDDClip)
            g_lpDDClip->Release(), g_lpDDClip = NULL;

        // Now, release the primary flipping chain. Note
        // that this is only valid because the flipping
        // chain surfaces were created with a single
        // CreateSurface call. If they were explicitly
        // created and attached, then they must also be
        // explicitly released.
        if(g_lpDDSurface)
            g_lpDDSurface->Release(), g_lpDDSurface = NULL;
    }
}

Note Earlier versions of the DirectDraw interface (IDirectDraw2 and IDirectDraw, to be exact) behave differently than the most recent interface. When using these early interfaces, DirectDraw automatically releases all child objects when the parent itself is released. As a result, if you use these older interfaces, the order in which you release objects is critical. In this case, you should release the children of a DirectDraw object before releasing the DirectDraw object itself (or not release them at all, counting on the parent to do cleanup for you). Because the DirectDraw object releases the child objects, if you release the parent before the children, you are very likely to incur a memory fault for attempting to dereference a pointer that was invalidated when the parent object released its children.

Some older applications relied on the automatic release of child objects and neglected to properly release some objects when no longer needed. At the time, this practice didn't cause any negative side effects, however doing so when using the IDirectDraw4 interface might result in memory leaks.


Multiple DirectDraw Objects per Process

DirectDraw allows a process to call the DirectDrawCreate function as many times as necessary. A unique and independent interface to a unique and independent DirectDraw object is returned after each call. Each DirectDraw object can be used as desired; there are no dependencies between the objects. Each object behaves exactly as if it had been created by a unique process.

DirectDraw objects are independent of one another and the DirectDrawSurface, DirectDrawPalette, and DirectDrawClipper objects they create should not be used with other DirectDraw objects because they are automatically released when the parent DirectDraw object is destroyed. If they are used with another DirectDraw object, they might stop functioning if their parent object is destroyed, causing the remaining DirectDraw object to malfunction.

The exception is DirectDrawClipper objects created by using the DirectDrawCreateClipper function. These objects are independent of any particular DirectDraw object and can be used with one or more DirectDraw objects.


Creating DirectDraw Objects by Using CoCreateInstance

You can create a DirectDraw object by using the CoCreateInstance function and the IDirectDraw4::Initialize method rather than the DirectDrawCreate function. The following steps describe how to create the DirectDraw object:

  1. Initialize COM at the start of your application by calling CoInitialize and specifying NULL.
    if (FAILED(CoInitialize(NULL)))
    return FALSE;
  2. Create the DirectDraw object by using CoCreateInstance and the IDirectDraw4::Initialize method.
    ddrval = CoCreateInstance(&CLSID_DirectDraw,
    NULL, CLSCTX_ALL, &IID_IDirectDraw4, &lpdd);
if(!FAILED(ddrval))
    ddrval = IDirectDraw4_Initialize(lpdd, NULL);

    In this call to CoCreateInstance, the first parameter, CLSID_DirectDraw, is the class identifier of the DirectDraw driver object class, the IID_IDirectDraw4 parameter identifies the particular DirectDraw interface to be created, and the lpdd parameter points to the DirectDraw object that is retrieved. If the call is successful, this function returns an uninitialized object.

  3. Before you use the DirectDraw object, you must call IDirectDraw4::Initialize. This method takes the driver GUID parameter that the DirectDrawCreate function typically uses (NULL in this case). After the DirectDraw object is initialized, you can use and release it as if it had been created by using the DirectDrawCreate function. If you do not call the Initialize method before using one of the methods associated with the DirectDraw object, a DDERR_NOTINITIALIZED error will occur.

Before you close the application, close the COM library by using the CoUninitialize function.

CoUninitialize();


Surfaces

This section contains information about DirectDrawSurface objects. The following topics are discussed:

  • Basic Concepts of Surfaces
  • Creating Surfaces
  • Flipping Surfaces
  • Blitting to Surfaces
  • Losing and Restoring Surfaces
  • COM Reference Count Semantics for Surfaces
  • Enumerating Surfaces
  • Updating Surface Characteristics
  • Accessing Surface Memory Directly
  • Gamma and Color Controls
  • Overlay Surfaces
  • Compressed Texture Surfaces
  • Private Surface Data
  • Surface Uniqueness Values
  • Using Non-local Video Memory Surfaces
  • Converting Color and Format
  • Surfaces and Device Contexts


Basic Concepts of Surfaces

This section contains information about the basic concepts associated with DirectDrawSurface objects. The following topics are discussed:

  • What Are Surfaces?
  • Surface Interfaces
  • Width vs. Pitch
  • Color Keying
  • Pixel Formats


What Are Surfaces?

A surface, or DirectDrawSurface object, represents a linear area of display memory. A surface usually resides in the display memory of the display card, although surfaces can exist in system memory. Unless specifically instructed otherwise during the creation of the DirectDrawSurface object, DirectDraw object will put the DirectDrawSurface object wherever the best performance can be achieved given the requested capabilities. DirectDrawSurface objects can take advantage of specialized processors on display cards, not only to perform certain tasks faster, but to perform some tasks in parallel with the system CPU.

Using the IDirectDraw4::CreateSurface method, you can create a single surface object, complex surface-flipping chains, or three-dimensional surfaces. The CreateSurface method creates the requested surface or flipping chain and retrieves a pointer to the primary surface's IDirectDrawSurface4 interface through which the object exposes its functionality.

The IDirectDrawSurface4 interface enables you to indirectly access memory through blit methods, such as IDirectDrawSurface4::BltFast. The surface object can provide a device context to the display that you can use with GDI functions. Additionally, you can use IDirectDrawSurface4 methods to directly access display memory. For example, you can use the IDirectDrawSurface4::Lock method to lock the display memory and retrieve the address corresponding to that surface. Addresses of display memory might point to visible frame buffer memory (primary surface) or to nonvisible buffers (off-screen or overlay surfaces). Nonvisible buffers usually reside in display memory, but can be created in system memory if required by hardware limitations or if DirectDraw is performing software emulation. In addition, the IDirectDrawSurface4 interface extends other methods that you can use to set or retrieve palettes, or to work with specific types or surfaces, like flipping chains or overlays.

From this illustration, you can see that all surface are created by a DirectDraw object and are often used closely with palettes. Although each surface object can be assigned a palette, palettes aren't required for anything but primary surfaces that use pixel formats of 8-bits in depth or less.


Surface Interfaces

DirectDrawSurface objects expose their functionality through the IDirectDrawSurface, IDirectDrawSurface2, IDirectDrawSurface3, and IDirectDrawSurface4 interfaces. Each new interface version provides the same utility as its predecessors, with additional options available through new methods.

When you create a surface by calling the IDirectDraw4::CreateSurface method (or another creation method from IDirectDraw4), you receive a pointer to the surface's IDirectDrawSurface4 interface. This behavior is different than previous versions of DirectX. Before the introduction of the IDirectDraw4 interface, the CreateSurface method provided a pointer to a surface's IDirectDrawSurface interface. If you wanted to work with a different iteration of the interface, you had to query for it. When using IDirectDraw4 this isn't the case, although you are free to query a surface for a previous iteration of an interface if you choose.


Width vs. Pitch

Although the terms width and pitch are discussed casually, they have very important (and distinctly different) meanings. As a result, you should understand the meanings for each, and how to interpret the values that DirectDraw uses to describe them.

DirectDraw uses the DDSURFACEDESC2 structure to carry information describing a surface. Among other things, this structure is defined to contain information about a surface's dimensions, as well as how those dimensions are represented in memory. The structure uses the dwHeight and dwWidth members to describe the logical dimensions of the surface. Both of these members are measured in pixels. Therefore, the dwHeight and dwWidth values for a 640×480 surface are the same whether it is an 8-bit palettized surface or a 24-bit RGB surface.

The DDSURFACEDESC2 structure contains information about how a surface is represented in memory through the lPitch member. The value in the lPitch member describes the surface's memory pitch (also called stride). Pitch is the distance, in bytes, between two memory addresses that represent the beginning of one bitmap line and the beginning of the next bitmap line. Because pitch is measured in bytes rather than pixels, a 640×480×8 surface will have a very different pitch value than a surface with the same dimensions but a different pixel format. Additionally, the pitch value sometimes reflects bytes that DirectDraw has reserved as a cache, so it is not safe to assume that pitch is simply the width multiplied by the number of bytes per pixel. Rather, you could visualize the difference between width and pitch as shown in the following illustration.

In this figure, the front buffer and back buffer are both 640×480×8, and the cache is 384×480×8.

Pitch values are useful when you are directly accessing surface memory. For example, after calling the IDirectDrawSurface4::Lock method, the lpSurface member of the associated DDSURFACEDESC2 structure contains the address of the top-left pixel of the locked area of the surface, and the lPitch member is the surface pitch. You access pixels horizontally by incrementing or decrementing the surface pointer by the number of bytes per pixel, and you move up or down by adding the pitch value to, or subtracting it from, the current surface pointer.

When accessing surfaces directly, take care to stay within the memory allocated for the dimensions of the surface and stay out of any memory reserved for cache. Additionally, when you lock only a portion of a surface, you must stay within the rectangle you specify when locking the surface. Failing to follow these guidelines will have unpredictable results. When rendering directly into surface memory, always use the pitch returned by the Lock method (or the IDirectDrawSurface4::GetDC method). Do not assume a pitch based solely on the display mode. If your application works on some display adapters but looks garbled on others, this may be the cause of your problem.

For more information, see Accessing Surface Memory Directly.


Color Keying

DirectDraw supports source and destination color keying for blits and overlay surfaces. Color keys enable you to display one image on top of another selectively, so that only certain pixels from the foreground rectangle are displayed, or only certain pixels on the background rectangle are overwritten.

You supply a single color key or a range of colors for source or destination color keying by calling the IDirectDrawSurface4::SetColorKey method.

For more information about color keying, see the following topics:

  • Overlay Color Keys
  • Transparent Blitting


Pixel Formats

Pixel formats dictate how data for each pixel in surface memory is to be interpreted. DirectDraw uses the DDPIXELFORMAT structure to describe various pixel formats. The DDPIXELFORMAT contains members to describe the following traits of a pixel format:

  • Palettized or non-palettized pixel format
  • If non-palettized, whether the pixel format is RGB or YUV
  • Bit depth
  • Bit masks for the pixel format's components

You can retrieve information about an existing surface's pixel format by calling the IDirectDrawSurface4::GetPixelFormat method.


Creating Surfaces

The DirectDrawSurface object represents a surface that usually resides in the display memory, but can exist in system memory if display memory is exhausted or if it is explicitly requested.

Use the IDirectDraw4::CreateSurface method to create one surface or to simultaneously create multiple surfaces (a complex surface). When calling CreateSurface, you specify the dimensions of the surface, whether it is a single surface or a complex surface, and the pixel format (if the surface won't be using an indexed palette). All these characteristics are contained in a DDSURFACEDESC2 structure, whose address you send with the call. If the hardware can't support the requested capabilities or if it previously allocated those resources to another DirectDrawSurface object, the call will fail.

Creating single surfaces or multiple surfaces is a simple matter that requires only a few lines of code. There are a few common situations (and some less common ones) in which you will need to create surfaces. The following situations are discussed:

  • Creating the Primary Surface
  • Creating an Off-Screen Surface
  • Creating Complex Surfaces and Flipping Chains
  • Creating Wide Surfaces
  • Creating Client Memory Surfaces

By default, for all surfaces except client memory surfaces, DirectDraw attempts to create a surface in local video memory. If there isn't enough local video memory available to hold the surface, DirectDraw will try to use non-local video memory (on some Accelerated Graphics Port-equipped systems), and fall back on system memory if all other types of memory are unavailable. You can explicitly request that a surface be created in a certain type of memory by including the appropriate flags in the associated DDSCAPS2 structure when calling IDirectDraw4::CreateSurface.


Creating the Primary Surface

The primary surface is the surface currently visible on the monitor and is identified by the DDSCAPS_PRIMARYSURFACE flag. You can only have one primary surface for each DirectDraw object.

When you create a primary surface, remember that the dimensions and pixel format implicitly match the current display mode. Therefore, this is the one time you don't need to declare a surface's dimensions or pixel format. If you do specify them, the call will fail and return DDERR_INVALIDPARAMS—even if the information you used matches the current display mode.

The following example shows how to prepare the DDSURFACEDESC2 structure members relevant for creating the primary surface.

DDSURFACEDESC2 ddsd;
ddsd.dwSize = sizeof(ddsd);

// Tell DirectDraw which members are valid.
ddsd.dwFlags = DDSD_CAPS;

// Request a primary surface.
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;

After creating the primary surface, you can retrieve information about its dimensions and pixel format by calling its IDirectDrawSurface4::GetSurfaceDesc method.

See also, Display Modes.


Creating an Off-Screen Surface

An off-screen surface is often used to cache bitmaps that will later be blitted to the primary surface or a back buffer. You must declare the dimensions of an off-screen surface by including the DDSD_WIDTH and DDSD_HEIGHT flags and the corresponding values in the dwWidth and dwHeight members. Additionally, you must include the DDSCAPS_OFFSCREENPLAIN flag in the accompanying DDSCAPS2 structure.

By default, DirectDraw creates a surface in display memory unless it will not fit, in which case it creates the surface in system memory. You can explicitly choose display or system memory by including the DDSCAPS_SYSTEMMEMORY or DDSCAPS_VIDEOMEMORY flags in the dwCaps member of the DDSCAPS2 structure. The method fails, returning an error, if it can't create the surface in the specified location.

The following example shows how to prepare for creating a simple off-screen surface:

DDSURFACEDESC2 ddsd;
ddsd.dwSize = sizeof(ddsd);

// Tell DirectDraw which members are valid.
ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;

// Request a simple off-screen surface, sized
// 100 by 100 pixels.
//
// (This assumes that the off-screen surface we are about
// to create will match the pixel format of the
// primary surface.)
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
ddsd.dwHeight = 100;
ddsd.dwWidth = 100;

Additionally, you can create surfaces whose pixel format differs from the primary surface's pixel format. However, in this case there is one drawback—you are limited to using system memory. The following code fragment shows how to prepare the DDSURFACEDESC2 structure members in order to create an 8-bit palettized surface (assuming that the current display mode is something other than 8-bits per pixel).

ZeroMemory(&ddsd, sizeof(ddsd));
ddsd.dwSize  = sizeof(ddsd);
ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
ddsd.dwHeight = 100;
ddsd.dwWidth  = 100;
ddsd.ddpfPixelFormat.dwSize  = sizeof(DDPIXELFORMAT);
ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_PALETTEINDEXED8;

// Set the bit depth for an 8-bit surface, but DO NOT
// specify any RGB mask values. The masks must be zero
// for a palettized surface.
ddsd.ddpfPixelFormat.dwRGBBitCount = 8;

In previous versions of DirectX, the maximum width of off-screen surfaces was limited to the width of the primary surface. Beginning with DirectX 5.0, you can create surfaces as wide as you need, permitting that the display hardware can support them. Be careful when declaring wide off-screen surfaces; if the video card memory cannot hold a surface as wide as you request, the surface is created in system memory. If you explicitly choose video memory and the hardware can't support it, the call fails. For more information, see Creating Wide Surfaces.


Creating Complex Surfaces and Flipping Chains

You can also create complex surfaces. A complex surface is a set of surfaces created with a single call to the IDirectDraw4::CreateSurface method. If the DDSCAPS_COMPLEX flag is set when you call CreateSurface call, DirectDraw implicitly creates one or more surfaces in addition to the surface explicitly specified. You manage complex surfaces just like a single surface—a single call to the IDirectDraw::Release method releases all surfaces, and a single call to the IDirectDrawSurface4::Restore method restores them all. However, implicitly created surfaces cannot be detached. For more information, see IDirectDrawSurface4::DeleteAttachedSurface.

One of the most useful complex surfaces you can create is a flipping chain. Usually, a flipping chain is made of a primary surface and one or more back buffers. The DDSCAPS_FLIP flag indicates that a surface is part of a flipping chain. Creating a flipping chain this way requires that you also include the DDSCAPS_COMPLEX flag.

The following example shows how to prepare for creating a primary surface flipping chain.

DDSURFACEDESC2 ddsd2;
ddsd2.dwSize = sizeof(ddsd2);

// Tell DirectDraw which members are valid.
ddsd2.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;

// Request a primary surface with a single
// back buffer
ddsd2.ddsCaps.dwCaps = DDSCAPS_COMPLEX | DDSCAPS_FLIP |
DDSCAPS_PRIMARYSURFACE;
ddsd2.dwBackBufferCount = 1;

The previous example constructs a double-buffered flipping environment—a single call to the IDirectDrawSurface4::Flip method exchanges the surface memory of the primary surface and the back buffer. If you specify 2 for the value of the dwBackBufferCount member of the DDSURFACEDESC2 structure, two back buffers are created, and each call to Flip rotates the surfaces in a circular pattern, providing a triple-buffered flipping environment. For more information, see Flipping Surfaces.

Note To create a flipping chain that comprises surfaces that will be used as 3-D render targets, be sure to include the DDSCAPS_3DDEVICE capability flag in the surface description, as well as the DDSCAPS_COMPLEX and DDSCAPS_FLIP flags.

Unlike the CreateSurface method exposed by the IDirectDraw3 and earlier interfaces, you cannot use IDirectDraw4::CreateSurface to implicitly create a flipping chain of render target surfaces with an attached depth-buffer. The DDSURFACEDESC2 structure that the IDirectDraw4::CreateSurface method accepts doesn't contain a field to specify a depth-buffer bit depth. As a result, applications must create a depth-buffer surface explicitly, then attach it to the back-buffer render target surface. For more information, see Depth Buffers.


Creating Wide Surfaces

DirectDraw allows you to create off-screen surfaces in video memory that are wider that the primary surface. This is only possible when display device support for wide surfaces is present.

To check for wide surface support, call IDirectDraw4::GetCaps and look for the DDCAPS2_WIDESURFACES flag in the dwCaps2 member of the first DDCAPS structure you send with the call. If the flag is present, you can create video memory off-screen surfaces that are wider that the primary surface.

If you attempt to create a wide surface in video memory when the DDCAPS2_WIDESURFACES flag isn't present, the attempt will fail and return DDERR_INVALIDPARAMS. Note that attempting to create extremely large surfaces might still fail, even if the driver exposes the DDCAPS2_WIDESURFACES flag.

Wide surfaces are always supported for system memory surfaces, video port surfaces, and execute buffers.


Creating Client Memory Surfaces

Client memory surfaces are simply DirectDrawSurface objects that use system memory that your application has previously allocated to hold image data. Creating such a surface isn't common, but it isn't difficult to do and it can be useful for applications that need to use DirectDraw surface features on existing memory buffers.

Like creating all surfaces, DirectDraw needs information about the dimensions of the surface (measured in pixels) and the surface pitch (measured in bytes), as well as the surface's pixel format. However, unlike creating other types of surfaces, this information doesn't tell DirectDraw how you want the surface to be created, it tells DirectDraw how you've already created it. You set these characteristics, plus the memory address of the buffer you've allocated, in the DDSURFACEDESC2 structure you pass to the IDirectDraw4::CreateSurface method.

A client memory surfaces works just like a normal system-memory surface, with the exception that DirectDraw does not attempt to free the surface memory when it's no longer needed; freeing client allocated memory is the application's responsibility.

The following example shows how you might allocate memory and create a DirectDrawSurface object for a 64×64 pixel 24-bit RGB surface:

// For this example, g_lpDD4 is a valid IDirectDraw4 interface pointer.

#define WIDTH  64 // in pixels
#define HEIGHT 64
#define DEPTH  3  // in bytes (3bytes == 24 bits)

    HRESULT hr;
    LPVOID  lpSurface  = NULL;
    HLOCAL  hMemHandle = NULL;
    DDSURFACEDESC2 ddsd2;
    LPDIRECTDRAWSURFACE4 lpDDS4;

    // Allocate memory for a 64 by 64, 24-bit per pixel buffer.
    // REMEMBER: The application is responsible for freeing this
    //           buffer when it is no longer needed.
    if (lpSurface = malloc((size_t)WIDTH*HEIGHT*DEPTH))
        ZeroMemory(lpSurface, (DWORD)WIDTH*HEIGHT*DEPTH);
    else
        return DDERR_OUTOFMEMORY;

    // Initialize the surface description.
    ZeroMemory(&ddsd2, sizeof(DDSURFACEDESC2));
    ZeroMemory(&ddsd2.ddpfPixelFormat, sizeof(DDPIXELFORMAT));
    ddsd2.dwSize = sizeof(ddsd2);
    ddsd2.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_LPSURFACE |
                    DDSD_PITCH | DDSD_PIXELFORMAT;
    ddsd2.dwWidth = WIDTH;
    ddsd2.dwHeight= HEIGHT;
    ddsd2.lPitch  = (LONG)DEPTH * WIDTH;
    ddsd2.lpSurface = lpSurface;

    // Set up the pixel format for 24-bit RGB (8-8-8).
    ddsd2.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
    ddsd2.ddpfPixelFormat.dwFlags= DDPF_RGB;
    ddsd2.ddpfPixelFormat.dwRGBBitCount = (DWORD)DEPTH*8;
    ddsd2.ddpfPixelFormat.dwRBitMask    = 0x00FF0000;
    ddsd2.ddpfPixelFormat.dwGBitMask    = 0x0000FF00;
    ddsd2.ddpfPixelFormat.dwBBitMask    = 0x000000FF;

    // Create the surface
    hr = g_lpDD4->CreateSurface(&ddsd2, &lpDDS4, NULL);
    return hr;


Flipping Surfaces

Any surface in DirectDraw can be constructed as a flipping surface. A flipping surface is any piece of memory that can be swapped between a front buffer and a back buffer. (This construct is commonly referred to as a flipping chain). Often, the front buffer is the primary surface, but it doesn't have to be.

Typically, when you use the IDirectDrawSurface4::Flip method to request a surface flip operation, the pointers to surface memory for the primary surface and back buffers are swapped. Flipping is performed by switching pointers that the display device uses for referencing memory, not by copying surface memory. (The exception to this is when DirectDraw is emulating the flip, in which case it simply copies the surfaces. DirectDraw emulates flip operations if a back buffer cannot fit into display memory or if the hardware doesn't support DirectDraw.) When a flipping chain contains a primary surface and more than one back buffer, the pointers are switched in a circular pattern, as shown in the following illustration.

Other surfaces that are attached to a DirectDraw object, but not part of the flipping chain, are unaffected when the Flip method is called.

Remember, DirectDraw flips surfaces by swapping surface memory pointers within DirectDrawSurface objects, not by swapping the objects themselves. This means that, to blit to the back buffer in any type of flipping scheme, you always use the same DirectDrawSurface object — the one that was the back buffer when you created the flipping chain. Conversely, you always perform a flip operation by calling the front surface's Flip method.

When working with visible surfaces, such as a primary surface flipping chain or a visible overlay surface flipping chain, the Flip method is asynchronous unless you include the DDFLIP_WAIT flag. On these visible surfaces, the Flip method can return before the actual flip operation occurs in the hardware (because the hardware doesn't flip until the next vertical refresh occurs). While the actual flip operation is pending, the back buffer behind the currently visible surface can't be locked or blitted by calling the IDirectDrawSurface4::Lock, IDirectDrawSurface4::Blt, IDirectDrawSurface4::BltFast, or IDirectDrawSurface4::GetDC methods. If you attempt to call these methods while a flip operation is pending, they will fail and return DDERR_WASSTILLDRAWING. However, if you are using a triple buffered scheme, the rearmost buffer is still available.


Blitting to Surfaces

This section is a guide to copying pixels from one DirectDraw surface to another, or from one part of a surface to another.

The following topics are covered:

  • Blitting Basics
  • Blitting with BltFast
  • Blitting with Blt
  • Blit Timing
  • Transparent Blitting
  • Color Fills
  • Blitting to Multiple Windows


Blitting Basics

Two methods are available for copying images to a DirectDraw surface: IDirectDrawSurface4::Blt and IDirectDrawSurface4::BltFast. (A third method, IDirectDrawSurface4::BltBatch, is not implemented in this version of DirectX.) These methods are called on the destination surface and receive the source surface as a parameter. The destination and source surfaces can be one and the same, and you don't have to worry about overlap—DirectDraw takes care to preserve all source pixels before overwriting them.

Of the two implemented methods, Blt is the more flexible and BltFast is the faster—but only if there is no hardware blitter. You can determine the blitting capabilities of the hardware from the DDCAPS structure obtained in the lpDDDriverCaps parameter of the IDirectDraw4::GetCaps method. If the dwCaps member contains DDCAPS_BLT, the hardware has at least minimal blitting capabilities.


Blitting with BltFast

When using IDirectDrawSurface4::BltFast, you supply a valid rectangle in the source surface from which the pixels are to be copied (or NULL to specify the entire surface), and an x-coordinate and y-coordinate in the destination surface. The source rectangle must be able to fit in the destination surface with its top left corner at that point, or the call will fail with a return value of DDERR_INVALIDRECT. BltFast cannot be used on surfaces that have an attached clipper.

No stretching, mirroring, or other effects can be performed when using BltFast.

BltFast Example

The following example copies pixels from an offscreen surface, lpDDSOffOne, to the primary surface, lpDDSPrimary. The flags ensure that the operation will take place as soon as the blitter is free, and that transparent pixels in the source image will not be copied. (For more information on the meaning of these flags, see Blit Timing and Transparent Blitting .)

lpDDSPrimary->BltFast(
        100, 200,    // Upper left xy of destination
        lpDDSOffOne, // Source surface
        NULL,        // Source rectangle = entire surface
        DDBLTFAST_WAIT | DDBLTFAST_SRCCOLORKEY );


Blitting with Blt

When using the IDirectDrawSurface4::Blt method, you supply a valid rectangle in the source surface (or NULL to specify the entire surface), and a rectangle in the destination surface to which the source image will be copied (again, NULL means the rectangle covers the entire surface). If a clipper is attached to the destination surface, the bounds of the destination rectangle can fall outside the surface and clipping will be performed. If there is no clipper, the destination rectangle must fall entirely within the surface or else the method will fail with DDERR_INVALIDRECT. (For more information on clipping, see Clippers.)

Scaling

The Blt method automatically rescales the source image to fit the destination rectangle. If resizing is not your intention, for best performance you should make sure that your source and destination rectangles are exactly the same size, or else use IDirectDrawSurface4:BltFast. (See Blitting with BltFast.)

Hardware acceleration for scaling depends on the DDFXCAPS_BLT* flags in the dwFXCaps member of the DDCAPS structure for the device. If, for example, a device has the DDFXCAPS_BLTSTRETCHXN capability but not DDFXCAPS_BLTSTRETCHX, it can assist when the x-axis of the source rectangle is being multiplied by a whole number but not when non-integral (arbitrary) scaling is being done.

Devices might also support arithmetic scaling, which is scaling by interpolation rather than simple multiplication or deletion of pixels. For instance, if an axis was being increased by one-third, the pixels would be recolored to provide a closer approximation to the original image than would be produced by the doubling of every third pixel on that axis.

Applications cannot control the type of scaling done by the driver, except by setting the DDBLTFX_ARITHSTRETCHY flag in the dwDDFX member of the DDBLTFX structure passed to Blt. This flag requests that arithmetic stretching be done on the y-axis. Arithmetic stretching on the x-axis and arithmetic shrinking are not currently supported in the DirectDraw API, but a driver may perform them by default.

Other Effects

If you do not require any special effects other than scaling when using Blt, you can pass NULL as the lpDDBltFx parameter. Otherwise you can choose among a variety of effects specified in a DDBLTFX structure. Among these, color fills and mirroring are supported by the HEL, so they are always available. Most other effects depend on hardware support.

For a complete view of the effects capabilities of the HEL, run the DDraw Caps utility supplied with the DirectX Programmer's Reference and select HEL FX Caps from the HEL menu. For an explanation of the various flags, see DDCAPS. You can also check HEL capabilities within your own application by using the IDirectDraw4::GetCaps method.

When you specify an effect that requires a value in one of the members of the DDBLTFX structure passed to the IDirectDrawSurface4::Blt method, you must also include the appropriate flags in the dwFlags parameter to show which members of the structure are valid.

Some effects require only the setting of a flag in the dwFlags member of DDBLTFX. One of these is DDBLTFX_NOTEARING. You can use this flag when you are blitting animated images directly to the front buffer, so that the blit is timed to coincide with the screen refresh and the possibility of tearing is minimized. Mirroring and rotation are also set by using flags.

Blitting effects include the standard raster operations (ROPs) used by GDI functions such as BitBlt. The only ROPs supported by the HEL are SRCCOPY (the default), BLACKNESS, and WHITENESS. Hardware support for other ROPs can be examined in the DDCAPS structure for the driver. If you wish to use any of the standard ROPS with the Blt method, you flag them in the dwROP member of the DDBLTFX structure.

The dwDDROP member of the DDBLTFX structure is for specifying ROPs specific to DirectDraw. However, no such ROPs are currently defined.

Alpha and Z Values

Opacity and depth values are not currently supported in DirectDraw blits. If alpha values are stored in the pixel format, they simply overwrite any alpha values in the destination rectangle. Values from alpha buffers and z-buffers are ignored. The members of the DDBLTFX structure that have to do with alpha channels and z-buffers (members whose names begin with "dwAlpha" and "dwZ"), and the corresponding flags for Blt, are not used. The same applies to the DDBLTFX_ZBUFFERBASEDEST and DDBLTFX_ZBUFFERRANGE flags in the dwDDFX member of the DDBLTFX structure.

Although z-buffers are currently used only in Direct3D applications, you can use IDirectDrawSurface4::Blt to set the depth value for a z-buffer surface, by setting the DDBLT_DEPTHFILL flag. For more information, see Clearing Depth Buffers.

For an overview of the use of alpha channels and z-buffers in Direct3D, see the following topics:

  • Alpha States
  • What Are Depth Buffers?

Blt Example

The following example, in which it is assumed that lpDDS is a valid IDirectDrawSurface4 pointer, creates a symmetrical image within the surface by mirroring a rectangle from left to right:

RECT     rcSource, rcDest;
DDBLTFX  ddbltfx;

ZeroMemory(&ddbltfx, sizeof(ddbltfx));
ddbltfx.dwSize = sizeof(ddbltfx);
ddbltfx.dwDDFX = DDBLTFX_MIRRORLEFTRIGHT;

rcSource.top = 0; rcSource.left = 0;
rcSource.bottom = 100; rcSource.right = 200;
rcDest.top = 0; rcDest.left = 201;
rcDest.bottom = 100; rcDest.right = 401;

HRESULT hr = lpDDS->Blt(&rcDest,
                        lpDDS,
                        &rcSource,
                        DDBLT_WAIT | DDBLT_DDFX,
                        &ddbltfx);


Blit Timing

When you copy pixels to a surface using either IDirectDrawSurface4::Blt or IDirectDrawSurface4::BltFast, the method might fail with DDERR_WASSTILLDRAWING because the hardware blitter was not ready to accept the command.

If your application has no urgent business to perform while waiting for the blitter to come back into a state of readiness, you can specify the DDBLT_WAIT flag in the dwFlags parameter of Blt, or the equivalent DDBLTFAST_WAIT flag for BltFast. The flag causes the method to wait until the blit can be handed off to the blitter (or until an error other than DDERR_WASSTILLDRAWING occurs).

Blt accepts another flag, DDBLT_ASYNC, that takes advantage of any hardware FIFO (first in, first out) queuing capabilities.


Transparent Blitting

This section discusses the theory and practice of using transparent blitting to copy parts of a rectangular image selectively, using source and destination color keys.

The concepts are introduced in the following topic:

  • What Is Transparent Blitting?

Information about the implementation of transparent blitting in DirectDraw is contained in the following topics:

  • Color Key Format
  • Setting Color Keys
  • Blitting with Color Keys


What Is Transparent Blitting?

Transparent blitting enables you to create the illusion of nonrectangular blits when animating sprites. A sprite image is usually nonrectangular, but blits are always rectangular, so every pixel within the sprite's bounding rectangle becomes part of the data transfer. With transparent blitting, each pixel that is not part of the sprite image is treated as transparent when the blitter is moving the image to its destination, so that it does not overwrite the color in that pixel on the background image.

The artist creating the sprite chooses an arbitrary color or range of colors to be used as the transparency color key. This is typically a single uncommon color that the artist doesn't use for anything but transparency, and it is used to fill in all parts of the sprite rectangle that are not part of the desired image. At run time you set the color key for the surface containing the sprite. (If you wish, you can automatically set it to the color of the pixel in the upper left corner of the image.) Subsequent blits can take advantage of that color key, ignoring the pixels that match it. This type of color key is known as a source color key.

You can also use a color key on the destination surface, provided the hardware supports destination color keying. This destination color key is used for pixels that can be overwritten by a sprite. For example, the artist might be working on a foreground image that sprites are supposed to pass behind, such as the wall of a room with a window to the outside. The artist chooses an arbitrary color—one that isn't used elsewhere in the image—to represent the sky outside the window. When you set this color key for the destination surface and then blit a sprite to that surface, the sprite's pixels will overwrite only pixels that are using the destination color key. In the example, the sprite appears only in the window, but not on the wall or window frame. As a result, the sprite seems to be outside the room.

Source and destination color keys can be combined. In the example, the sprite could use a source color key so that its entire bounding rectangle does not block out the sky background.


Color Key Format

A color key is described in a DDCOLORKEY structure. If the color key is a single color, both members of this structure should be assigned the same value. Otherwise the color key is a range of colors.

Color keys are specified using the pixel format of a surface. If a surface is in a palettized format, the color key is given as an index or a range of indices. If the surface's pixel format is specified by a FOURCC code that describes a YUV format, the YUV color key is specified by the three low-order bytes in both the dwColorSpaceLowValue and dwColorSpaceHighValue members of the DDCOLORKEY structure. The lowest order byte contains the V data, the second lowest order byte contains the U data, and the highest order byte contains the Y data.

Some examples of valid color keys follow:

8-bit palettized mode

// Palette entry 26 is the color key.
dwColorSpaceLowValue = 26;
dwColorSpaceHighValue = 26;

24-bit true-color mode

// Color 255,128,128 is the color key.
dwColorSpaceLowValue = RGBQUAD(255,128,128);
dwColorSpaceHighValue = RGBQUAD(255,128,128);

FourCC YUV mode

// Any YUV color where Y is between 100 and 110
// and U or V is between 50 and 55 is transparent.
dwColorSpaceLowValue = YUVQUAD(100,50,50);
dwColorSpaceHighValue = YUVQUAD(110,55,55);

Support for a range of colors rather than a single color is hardware-dependent. Check the dwCKeyCaps member of the DDCAPS structure for the hardware. The HEL does not support color ranges.

Some hardware supports color ranges only for YUV pixel data, which is usually video. The transparent background in video footage (the "blue screen" against which the subject was photographed) might not be a single pure color, so a range of colors in the color key is desirable.


Setting Color Keys

You can set the source or destination color key for a surface either when creating it or afterwards.

To set a color key or keys when creating a surface, you assign the appropriate color values to one or both of the ddckCKSrcBlt and ddckCKDestBlt members of the DDSURFACEDESC2 structure that is passed to IDirectDraw4::CreateSurface. To enable the color key for blitting, you must also include one or both of DDSD_CKSRCBLT or DDSD_CKDESTBLT in the dwFlags member.

To set a color key for an existing surface you use the IDirectDrawSurface4::SetColorKey method. You specify a key in the lpDDColorKey parameter and set either DDCKEY_SRCBLT or DDCKEY_DESTBLT in the dwFlags parameter to indicated whether you are setting a source or destination key. If the DDCOLORKEY structure contains a range of colors, you must also set the DDCKEY_COLORSPACE flag. If this flag is not set, only the dwColorSpaceLowValue member of the structure is used.


Blitting with Color Keys

If you want to use color keys for surfaces when calling the IDirectDrawSurface4::BltFast method, you must set one or both of the DDBLTFAST_SRCCOLORKEY or DDBLTFAST_DESTCOLORKEY flags in the dwTrans parameter.

In order to use colors keys when calling IDirectDrawSurface4:Blt, you pass one or both of the DDBLT_KEYSRC or DDBLT_KEYDEST flags in the dwFlags parameter. Alternatively, you can put the appropriate color values in the ddckDestColorkey and ddckSrcColorkey members of the DDBLTFX structure that is passed to the method through the lpDDBltFx parameter. In this case you must also set the DBLT_KEYSRCOVERRIDE or DDBLT_KEYDESTOVERRIDE flag, or both, in the dwFlags parameter, so that the selected keys are taken from the DDBLTFX structure rather than from the surface properties.


Color Fills

In order to fill all or part of a surface with a single color, you can use the IDirectDrawSurface4::Blt method with the DDBLT_COLORFILL flag. This technique allows you to quickly erase an area or draw a solid-colored background.

The following example fills an entire surface with the color blue, after obtaining the numerical value for blue from the pixel format:

/* It is assumed that lpDDS is a valid pointer to
   an IDirectDrawSurface4 interface. */

HRESULT ddrval;
DDPIXELFORMAT ddpf;

ddpf.dwSize = sizeof(ddpf);
if (SUCCEEDED(lpDSS->GetPixelFormat(&ddpf))
{
    DDBLTFX ddbltfx;

    ddbltfx.dwSize = sizeof(ddbltfx);
    ddbltfx.dwFillColor = ddpf.dwBBitMask; // Pure blue

    ddrval = lpDDS->Blt(
        NULL,        // Destination is entire surface
        NULL,        // No source surface
        NULL,        // No source rectangle
        DDBLT_COLORFILL, &ddbltfx);

    switch(ddrval)
    {
        case DDERR_WASSTILLDRAWING:
            .
            .
            .
        case DDERR_SURFACELOST:
            .
            .
            .
        case DD_OK:
            .
            .
            .
        default:
    }
}


Blitting to Multiple Windows

You can use a DirectDraw object and a DirectDrawClipper object to blit to multiple windows created by an application running at the normal cooperative level. For more information, see Using a Clipper with Multiple Windows.

Creating multiple DirectDraw objects that blit to each others' primary surface is not recommended.


Losing and Restoring Surfaces

The surface memory associated with a DirectDrawSurface object may be freed, while the DirectDrawSurface objects representing these pieces of surface memory are not necessarily released. When a DirectDrawSurface object loses its surface memory, many methods return DDERR_SURFACELOST and perform no other action.

Surfaces can be lost because the display mode was changed or because another application received exclusive access to the display card and freed all of the surface memory currently allocated on the card. The IDirectDrawSurface4::Restore method re-creates these lost surfaces and reconnects them to their DirectDrawSurface object. If your application uses more than one surface, you can call the IDirectDraw4::RestoreAllSurfaces method to restore all of your surfaces at once.

Restoring a surface doesn't reload any bitmaps that may have existed in the surface prior to being lost. You must completely reconstitute the graphics they once held.


COM Reference Count Semantics for Surfaces

Being built upon COM means that DirectDraw follows certain rules that employ reference counts to manage object lifetimes. For a conceptual overview, see the COM documentation; a DirectDraw-centered discussion of the topic is found in Parent and Child Object Lifetimes.

By COM rules, when an interface pointer is copied by setting it to another variable or passing to another object, that copy represents another reference to the object, and therefore the IUnknown::AddRef method of the interface must be called to reflect the change. Not only should you follow COM reference counting rules when working with DirectDraw objects, but you should become familiar with the situations in which DirectDraw internally updates reference counts. Some DirectDraw methods—mostly those involving complex surface flipping chains—affect the reference counts of the surfaces involved, while methods involving clippers or palettes affect the reference counts of those objects. Knowing about these situations can make the difference in your application's stability and can prevent memory leaks. This section presents information divided into the following topics:

  • When Reference Counts Will Change
  • Reference Counts for Complex Surfaces
  • Releasing Surfaces

Note: There are some things to remember about the reference count of the DirectDraw object, in addition to the relationships discussed in this section. For more information, see Parent and Child Object Lifetimes in The DirectDraw Object.


When Reference Counts will Change

There are several DirectDraw methods that affect the reference count of a surface, and a few that affect other objects you can associate with a surface. You can think of these situations as "surface-only changes" and "cross-object changes":

Surface-only changes
Surface-only changes, as the name states, only affect the reference count of a surface object. For example, you might use the IDirectDraw4::EnumSurfaces to enumerate the current surfaces that fit a particular description. When the method invokes the callback function that you provide, it passes a pointer to an IDirectDrawSurface4 interface, but it increments the reference count for the object before your application receives the pointer. It's your responsibility to release the object when you are finished with it. This will typically be at the end of your callback routine, or later if you choose to keep the object.

Most other surface-only changes affect the reference counts of complex surfaces, such as a flipping chain. Reference counts are a little more tricky for complex surfaces, because (in most cases) DirectDraw treats a complex surface as if it was a single object, even though it is a set of surfaces. In short, the IDirectDrawSurface4::GetAttachedSurface and IDirectDrawSurface4::AddAttachedSurface methods increment reference counts of surfaces, and IDirectDrawSurface4::DeleteAttachedSurface decrements the reference count. These methods don't affect the counts of any surfaces attached to the current surface. See the references for these methods and Reference Counts for Complex Surfaces for a additional details.

Cross-object changes
Cross-object reference count changes occur when you create an association between a surface and another object that performs a task for the surface, such as a clipper or a palette.

The IDirectDrawSurface4::SetClipper and IDirectDrawSurface4::SetPalette methods increment the reference count of the object being attached. After they are attached, the surface manages them; if the surface is released, it automatically releases any objects it is using. (For this reason, some applications release the interface for the object after these calls succeed. This is a perfectly valid practice.)

Once a clipper or palette is attached to a surface, you can call the IDirectDrawSurface4::GetClipper and IDirectDrawSurface4::GetPalette methods to retrieve them again. Because these methods return a copy of an interface pointer, they implicitly increment the reference count for the object being retrieved. When you're done with the interfaces, don't forget to release them—the objects that the interfaces represent won't disappear so long as the surface they are attached to still holds a reference to them.


Reference Counts for Complex Surfaces

The methods you use to manipulate a complex surface like a flipping chain all use surface interface pointers, and therefore they all affect the reference counts of the surfaces. Because a complex surface is really a series of single surfaces, the reference count relationships require a little more consideration. As you might expect, the IDirectDrawSurface4::GetAttachedSurface method returns the surface interface for a surface attached to the current surface. It does this after incrementing the reference count of the interface being retrieved; it's up to you to release the interface when you no longer need it. The IDirectDrawSurface4::AddAttachedSurface method attaches a new surface to the current one. Similarly, AddAttachedSurface increments the count for the surface being attached. You would use the IDirectDrawSurface4::DeleteAttachedSurface method to remove the surface from the chain and implicitly decrease its reference count.

What isn't immediately clear about these methods is that they don't affect the reference counts of the other objects that make up the complex surface. The GetAttachedSurface method simply increments the reference count of the surface it's retrieving, it doesn't affect the counts of the surfaces on which it depends. (The same situation applies to an explicit call to IUnknown::AddRef.) This means that the reference count for primary surface in a complex surface can reach zero before its subordinate surfaces reach zero. When the primary surface reference count reaches zero, all other surfaces attached to it are released regardless of their current reference counts. (It's like a tree: if you cut the base, the whole thing falls. In this case, the primary surface is the base.) Attempts to access subordinate surfaces after the primary surface has been deallocated will result in memory faults.

To avoid problems, make sure that your application has released all subordinate surface references before attempting to release the primary surface. It might be helpful to track the references you application holds, only accessing subordinate surface interfaces when you're sure that you also hold a reference the primary surface.


Releasing Surfaces

Like all COM interfaces, you must release surfaces by calling their IDirectDrawSurface4::Release method when you no longer need them.

Each surface you individually create must be explicitly released. However, if you implicitly created multiple surfaces with a single call to IDirectDraw4::CreateSurface, such as a flipping chain, you need only release the front buffer. In this case, any pointers you might have to back buffer surfaces are implicitly released and can no longer be used.

Explicitly releasing a back buffer surface doesn't affect the reference count of the other surfaces in the chain.


Enumerating Surfaces

By calling the IDirectDraw4::EnumSurfaces method you can request that DirectDraw enumerate surfaces in various ways. The EnumSurfaces method enables you to look for surfaces that fit, or don't fit, a provided surface description. DirectDraw calls a EnumSurfacesCallback that you include with the call for each enumerated surface.

There are two general ways to search—you can search for surfaces that the DirectDraw object has already created, or for surfaces that the DirectDraw object is capable of creating at the time (given the surface description and available memory). You specify what type of search you want by combining flags in the method's dwFlags parameter.

Enumerating existing surfaces

This is the most common type of enumeration. You enumerate existing surfaces by calling EnumSurfaces, specifying a combination of the DDENUMSURFACES_DOESEXIST search-type flag and one of the matching flags (DDENUMSURFACES_MATCH, DDENUMSURFACES_NOMATCH, or DDENUMSURFACES_ALL) in the dwFlags parameter. If you're enumerating all existing surfaces, you can set the lpDDSD parameter to NULL, otherwise set it to the address of an initialized DDSURFACEDESC2 structure that describes the surface for which you're looking. You can set the third parameter, lpContext, to an address that will be passed to the enumeration function you specify in the fourth parameter, lpEnumSurfacesCallback.

The following code fragment shows what this call might look like to enumerate all of a DirectDraw object's existing surfaces.

    HRESULT ddrval;
    ddrval = lpDD->EnumSurfaces(DDENUMSURFACES_DOESEXIST |
                                DDENUMSURFACES_ALL, NULL, NULL,
                                EnumCallback);
    if (FAILED(ddrval))
        return FALSE;

When searching for existing surfaces that fit a specific description, DirectDraw determines a match by comparing each member of the provided surface description to those of the existing surfaces. Only exact matches are enumerated. DirectDraw increments the reference counts of the enumerated surfaces, so make sure to release a surface if you don't plan to use it (or when you're done with it).

Enumerating possible surfaces

This type of enumeration is less common than enumerating existing surfaces, but it can be helpful to determine if a surface is supported before you attempt to create it. To perform this search, combine the DDENUMSURFACES_CANBECREATED and DDENUMSURFACES_MATCH flags when you call IDirectDraw4::EnumSurfaces (no other flag combinations are valid). The DDSURFACEDESC2 structure you use with the call must be initialized to contain information about the surface characteristics that DirectDraw will use.

To enumerate surfaces that use a particular pixel format, include the DDSD_PIXELFORMAT flag in the dwFlags member of the DDSURFACEDESC2 structure. Additionally, initialize the DDPIXELFORMAT structure in the surface description and set its dwFlags member to contain the desired pixel format flags—DDPF_RGB, DDPF_YUV, or both. You need not set any other pixel format values.

If you include the DDSD_HEIGHT and DDSD_WIDTH flags in the DDSURFACEDESC2 structure, you can specify the desired dimensions in the dwHeight and dwWidth members. If you exclude these flags, DirectDraw uses the dimensions of the primary surface.

The following code fragment shows what this call could look like to enumerate all valid surface characteristics for 96×96 RGB or YUV surfaces:

    DDSURFACEDESC2 ddsd;
    HRESULT        ddrval;
    ZeroMemory(&ddsd, sizeof(ddsd));

    ddsd.dwSize  = sizeof(ddsd);
    ddsd.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT |
                   DDSD_HEIGHT | DDSD_WIDTH;
    ddsd.ddpfPixelFormat.dwFlags = DDPF_YUV | DDPF_RGB;
    ddsd.dwHeight = 96;
    ddsd.dwWidth  = 96;

    ddrval = lpDD->EnumSurfaces(
                     DDENUMSURFACES_CANBECREATED | DDENUMSURFACES_MATCH,
                     &ddsd, NULL, EnumCallback);
    if (ddrval != DD_OK)
        return FALSE;

When DirectDraw enumerates possible surfaces, it actually attempts to create a temporary surface that has the desired characteristics. If the attempt succeeds, then DirectDraw calls the provided EnumSurfacesCallback function with only the characteristics that worked; it does not provide the callback function with pointer to the temporary surface. Do not assume that a surface isn't supported if it isn't enumerated. DirectDraw's attempt to create a temporary surface could fail due to memory constraints that exist at the time of the call, resulting in those characteristics not being enumerated, even if the driver actually supports them.


Updating Surface Characteristics

You can update the characteristics of an existing surface by using the IDirectDrawSurface4::SetSurfaceDesc method. With this method, you can change the pixel format and location of a DirectDrawSurface object's surface memory to system memory that your application has explicitly allocated. This is useful as it allows a surface to use data from a previously allocated buffer without copying. The new surface memory is allocated by the client application and, as such, the client application must also deallocate it.

When calling the IDirectDrawSurface4::SetSurfaceDesc method, the lpddsd parameter must be the address of a DDSURFACEDESC2 structure that describes the new surface memory as well as a pointer to that memory. Within the structure, you can only set the dwFlags member to reflect valid members for the location of the surface memory, dimensions, pitch, and pixel format. Therefore, dwFlags can only contain combinations of the DDSD_WIDTH, DDSD_HEIGHT, DDSD_PITCH, DDSD_LPSURFACE, and DDSD_PIXELFORMAT flags, which you set to indicate valid structure members.

Before you set the values in the structure, you must allocate memory to hold the surface. The size of the memory you allocate is important. Not only do you need to allocate enough memory to accommodate the surface's width and height, but you need to have enough to make room for the surface pitch, which must be a QWORD (8 byte) multiple. Remember, pitch is measured in bytes, not pixels.

When setting surface values in the structure, the lpSurface member is a pointer to the memory you allocated and the dwHeight and dwWidth members describe the surface dimensions in pixels. If you specify surface dimensions, you must fill the lPitch member to reflect the surface pitch as well. Pitch must be a DWORD multiple. Likewise, if you specify pitch, you must also specify a width value. Lastly, the ddpfPixelFormat member describes the pixel format for the surface. With the exception of the lpSurface member, if you don't specify a value for these members, the method defaults to using the value from the current surface.

There are some restrictions you must be aware of when using IDirectDrawSurface4::SetSurfaceDesc, some of which are common sense. For example, the lpSurface member of the DDSURFACEDESC2 structure must be a valid pointer to a system memory (the method doesn't support video memory pointers at this time). Also, the dwWidth and dwHeight members must be nonzero values. Lastly, you cannot reassign the primary surface or any surfaces within the primary's flipping chain.

You can set the same memory for multiple DirectDrawSurface objects, but you must take care that the memory is not deallocated while it is assigned to any surface object.

Using the SetSurfaceDesc method incorrectly will cause unpredictable behavior. The DirectDrawSurface object will not deallocate surface memory that it didn't allocate. Therefore, when the surface memory is no longer needed, it is your responsibility to deallocate it. However, when SetSurfaceDesc is called, DirectDraw frees the original surface memory that it implicitly allocated when creating the surface.


Accessing Surface Memory Directly

You can directly access the frame buffer or off-screen surface memory by using the IDirectDrawSurface4::Lock method. When you call this method, the lpDestRect parameter is a pointer to a RECT structure that describes the rectangle on the surface you want to access directly. To request that the entire surface be locked, set lpDestRect to NULL. Also, you can specify a RECT that covers only a portion of the surface. Providing that no two rectangles overlap, two threads or processes can simultaneously lock multiple rectangles in a surface.

The Lock method fills a DDSURFACEDESC2 structure with all the information you need to properly access the surface memory. The structure includes information about the pitch (or stride) and the pixel format of the surface, if different from the pixel format of the primary surface. When you finish accessing the surface memory, call the IDirectDrawSurface4::Unlock method to unlock it.

While you have a surface locked, you can directly manipulate the contents. The following list describes some tips for avoiding common problems with directly rendering surface memory:

  • Never assume a constant display pitch. Always examine the pitch information returned by the IDirectDrawSurface4::Lock method. This pitch can vary for a number of reasons, including the location of the surface memory, the type of display card, or even the version of the DirectDraw driver. For more information, see Width vs. Pitch.
  • Make certain you blit to unlocked surfaces. DirectDraw blit methods will fail, returning DDERR_SURFACEBUSY or DDERR_LOCKEDSURFACES, if called on a locked surface. Similarly, GDI blit functions fail without returning error values if called on a locked surface that exists in display memory.
  • Limit your application's activity while a surface is locked. While a surface is locked, DirectDraw often holds the Win16Mutex (also known as the Win16Lock) so that gaining access to surface memory can occur safely. The Win16Mutex serializes access to GDI and USER dynamic-link libraries, shutting down Windows for the duration between the IDirectDrawSurface4::Lock and IDirectDrawSurface4::Unlock calls. The IDirectDrawSurface4::GetDC method implicitly calls Lock, and the IDirectDrawSurface4::ReleaseDC implicitly calls Unlock.
  • Always copy data aligned to display memory. (Windows 95 and Windows 98 use a page fault handler, Vflatd.386, to implement a virtual flat-frame buffer for display cards with bank-switched memory. The handler allows these display devices to present a linear frame buffer to DirectDraw. Copying data unaligned to display memory can cause the system to suspend operations if the copy spans memory banks.)

Unless you include the DDLOCK_NOSYSLOCK flag when you call the Lock method, locking the surface typically causes DirectDraw to take the Win16Mutex. During the Win16Mutex all other applications, including Windows, cease execution. Since the Win16Mutex stops applications from executing, standard debuggers cannot be used while the lock is held. Kernel debuggers can be used during this period. DirectDraw always takes the Win16Mutex when locking the primary surface.

If a blit is in progress when you call IDirectDrawSurface4::Lock, the method will return immediately with an error, as a lock cannot be obtained. To prevent the error, use the DDLOCK_WAIT flag to cause the method to wait until a lock can be successfully obtained.

Locking portions of the primary surface can interfere with the display of a software cursor. If the cursor intersects the locked rectangle, it is hidden for the duration of the lock. If it doesn't intersect the rectangle, it is frozen for the duration of the lock. Neither of these effects occurs if the entire surface is locked.


Gamma and Color Controls

This section contains information about the gamma and color control interfaces used with DirectDrawSurface objects. Information is organized into the following topics:

  • What Are Gamma and Color Controls?
  • Using Gamma Controls
  • Using Color Controls

Note You should not attempt to use both the IDirectDrawGammaControl and IDirectDrawColorControl interfaces on a single surface. Their effects are undefined when used together.


What Are Gamma and Color Controls?

Through the gamma and color control interfaces, DirectDrawSurface objects enable you to change how the system displays the contents of the surface, without affecting the contents of the surface itself. You can think of these controls as very simple filters that DirectDraw applies to the data as it leaves a surface before being rendered on the screen. Surface objects implement the IDirectDrawGammaControl and IDirectDrawColorControl interfaces which expose methods to adjust how the surface's contents are filtered. You can retrieve a pointer to either interface by using the IUnknown::QueryInterface method of the target surface, specifying the IID_IDirectDrawGammaControl or IID_IDirectDrawColorControl reference identifiers.

Gamma controls, represented by the IDirectDrawGammaControl interface, make it possible for you to dynamically change how a surface's individual red, green, and blue levels map to the actual levels that the system displays. By setting gamma levels, you can cause the user's screen to flash colors—red when the user's character is shot, green when they pick up a new item, and so on—without blitting new images to the frame buffer to achieve the effect. Or, you might adjust color levels to apply a color bias to the images in the frame buffer. Although this interface is similar to the color control interface, this one is the easiest to use, making it the best choice for game applications. For details, see Using Gamma Controls.

The IDirectDrawColorControl interface allows you to control color in a surface much like the color controls you might find on a television. The similarity between IDirectDrawColorControl and the actual controls on a TV is no mistake—this interface is most appropriate for adjusting how broadcast video looks in an overlay surface, so it makes sense that it should provide similar control over colors. You can use color controls to allow a user to change video characteristics such as hue, saturation, contrast, and several others. For more information, see Using Color Controls.


Using Gamma Controls

The IDirectDrawGammaControl interface, which you retrieve by querying the surface with the IID_IDirectDrawGammaControl reference identifier, allows you to manipulate ramp levels that affect the red, green, and blue color components of pixels from the surface before they are sent to the digital-to-analog converter (DAC) for display. Although all surface types support the IDirectDrawGammaControl interface, you are only allowed to adjust gamma on the primary surface. Attempts to call IDirectDrawGammaControl::GetGammaRamp or IDirectDrawGammaControl::SetGammaRamp on a surface other than the primary surface will fail.

In the following topics, this section describes the general concept of ramp levels, and provides information about working with those levels through the methods of IDirectDrawGammaControl:

  • About Gamma Ramp Levels
  • Detecting Gamma Ramp Support
  • Setting and Retrieving Gamma Ramp Levels


About Gamma Ramp Levels

A gamma ramp in DirectDraw is a term used to describe a set of values that map the level of a particular color component (red, green, blue) for all pixels in the frame buffer to new levels that are received by the digital-to-analog converter (DAC) for display on the monitor. The remapping is performed by way of three simple look-up tables, one for each color component.

Here's how it works: DirectDraw takes a pixel from the frame buffer, and looks at it in terms of its individual red, green, and blue color components. Each component is represented by a value from 0 to 65535. DirectDraw takes the original value, and uses it to index into an 256-element array (the ramp), where each element contains a value that replaces the original one. DirectDraw performs this "look-up and replace" process for each color component of each pixel within the frame buffer, thereby changing the final colors for all of the on-screen pixels.

It's handy to visualize the ramp values by graphing them. The left graph of the two following graphs shows a ramp that doesn't modify colors at all, and the right graph shows a ramp that imposes a negative bias to the color component to which it is applied.

The array elements for the graph on the left would contain values identical to their index (0 in the element at index 0, and 65535 at index 255). This type of ramp is the default, as it doesn't change the input values before they're displayed. The right graph is a little more interesting; its ramp contains values that range from 0 in the first element to 32768 in the last element, with values ranging relatively uniformly in between. The effect is that the color component that uses this ramp appears muted on the display. You are not limited to using linear graphs; if your application needs to assign arbitrary mapping, it's free to do so. You can even set the entries to all zeroes to leech a particular color component completely from the display.


Detecting Gamma Ramp Support

You can determine whether the hardware supports dynamic gamma ramp adjustment by calling the IDirectDraw4::GetCaps method. After the call, if the DDCAPS2_PRIMARYGAMMA flag is present in the dwFlags2 member of the associate DDCAPS structure, the hardware supports dynamic gamma ramps. DirectDraw does not attempt to emulate this feature, so if the hardware doesn't support it, you can't use it.


Setting and Retrieving Gamma Ramp Levels

Gamma ramp levels are effectively look-up tables that DirectDraw uses to map the frame buffer color components to new levels that will be displayed. For more information, see About Gamma Ramp Levels. You set and retrieve ramp levels for the primary surface by calling the IDirectDrawGammaControl::SetGammaRamp and IDirectDrawGammaControl::GetGammaRamp methods. Both methods accept two parameters, but the first parameter is reserved for future use, and should be set to zero. The second parameter, lpRampData, is the address of a DDGAMMARAMP structure. The DDGAMMARAMP structure contains three 256-element arrays of WORDs, one array each to contain the red, green, and blue gamma ramps.

You can include the DDSGR_CALIBRATE value when calling the IDirectDrawGammaControl::SetGammaRamp to invoke the calibrator when setting new gamma levels. Calibrating gamma ramps incurs some processing overhead, and should not be used frequently. Setting a calibrated gamma ramp will provide a consistent and absolute gamma value for the viewer, regardless of the display adapter and monitor.

Not all systems support gamma calibration. To determine if gamma calibration is supported, call IDirectDraw4::GetCaps, and examine the dwCaps2 member of the associated DDCAPS structure after the method returns. If the DDCAPS2_CANCALIBRATEGAMMA capability flag is present, then gamma calibration is supported.

When setting new ramp levels, keep in mind that that the levels you set in the arrays are only used when your application is in full-screen, exclusive mode. Whenever your application changes to normal mode, the ramp levels are set aside, taking effect again when the application reinstates full-screen mode. In addition, remember that you cannot set ramp levels for any surface other than the primary.

Note Those very familiar with the Win32® API might wonder why DirectDraw exposes an interface like IDirectDrawGammaControl, when Win32 offers the GetDeviceGammaRamp and SetDeviceGammaRamp functions for the same surfaces. Although the Win32 API includes these functions, they do not always succeed on all Windows platforms like the methods of the IDirectDrawGammaControl interface.


Using Color Controls

You set and retrieve surface color controls through the IDirectDrawColorControl interface, which can be retrieved by querying the DirectDrawSurface object using the IID_IDirectDrawColorControl reference identifier.

Color control information is represented by a DDCOLORCONTROL structure, which is used with both methods of the interface, IDirectDrawColorControl::SetColorControls and IDirectDrawColorControl::GetColorControls. The first structure member, dwSize, should be set to the size of the structure, in bytes, before you use it. How you use the next member, dwFlags, depends on whether you are setting or retrieving color controls. If you are setting new color controls, set dwFlags to a combination of the appropriate flags to indicate which of the other structure members contain valid data that you've set. However, when retrieving color controls, you don't need to set the dwFlags before using it—it will contain flags telling you which members are valid after the IDirectDrawColorControl::GetColorControls method returns.

The remaining DDCOLORCONTROL structure members can contain values that describe the brightness, contrast, hue, saturation, sharpness, gamma, and whether color is used. Note that the structure contains information about gamma correction. This is a single gamma value that affects overall brightness, and it should not be confused with the gamma adjustment features provided through the IDirectDrawGammaControl interface.


Overlay Surfaces

This section contains information about DirectDraw overlay surface support. The following topics are discussed:

  • Overlay Surface Overview
  • Significant DDCAPS Members and Flags
  • Source and Destination Rectangles
  • Boundary and Size Alignment
  • Minimum and Maximum Stretch Factors
  • Overlay Color Keys
  • Positioning Overlay Surfaces
  • Creating Overlay Surfaces
  • Overlay Z-Orders
  • Flipping Overlay Surfaces

For information about implementing overlay surfaces, see Tutorial 6: Using Overlay Surfaces.


Overlay Surface Overview

Overlay surfaces, casually referred to as overlays, are surfaces with special hardware-supported capabilities. Overlay surfaces are frequently used to display live video, recorded video, or still bitmaps over the primary surface without blitting to the primary surface or changing the primary surface's contents in any way. Overlay surface support is provided entirely by the hardware; DirectDraw supports any capabilities as reported by the display device driver. DirectDraw does not emulate overlay surfaces.

An overlay surface is analogous to a clear piece of plastic that you draw on and place in front of the monitor. When the overlay is in front of the monitor, you can see both the overlay and the contents of the primary surface together, but when you remove it, the primary surface's contents are unchanged. In fact, the mechanics of overlays work much like the clear plastic analogy. When you display an overlay surface, you're telling the device driver where and how you want it to be visible. While the display device paints scan lines to the monitor, it checks the location of each pixel in the primary surface to see if an overlay should be visible there instead. If so, the display device substitutes data from the overlay surface for the corresponding pixel, as shown in the following illustration.

By using this method, the display adapter produces a composite of the primary surface and the overlay on the monitor, providing transparency and stretching effects, without modifying the contents of either surface. The composited surfaces are injected into the video stream and sent directly to the monitor. Because this on-the-fly processing and pixel substitution is handled at the hardware level, no noticeable performance loss occurs when displaying overlays. Additionally, this method makes it possible to seamlessly composite primary and overlay surfaces with different pixel formats.

You create overlay surfaces by calling the IDirectDraw4::CreateSurface method, specifying the DDSCAPS_OVERLAY flag in the associated DDSCAPS2 structure. Overlay surfaces can only be created in video memory, so you must also include the DDSCAPS_VIDEOMEMORY flag. As with other types of surfaces, by including the appropriate flags you can create either a single overlay or a flipping chain made up of multiple overlay surfaces.


Significant DDCAPS Members and Flags

You can retrieve information about the supported overlay features by calling the IDirectDraw4::GetCaps method. The method fills a DDCAPS structure with information describing all features.

When reporting hardware features, the device driver sets flags in the dwCaps structure member to indicate when a given type of restriction is enforced by the hardware. After retrieving the driver capabilities, examine the flags in the dwCaps member for information about which restrictions apply. The DDCAPS structure contains nine members that carry information describing hardware restrictions for overlay surfaces. The following table lists the overlay related members and their corresponding flags:

Member | Flag
dwMaxVisibleOverlays | This member is always valid
dwCurrVisibleOverlays | This member is always valid
dwAlignBoundarySrc | DDCAPS_ALIGNBOUNDARYSRC
dwAlignSizeSrc | DDCAPS_ALIGNSIZESRC
dwAlignBoundaryDest | DDCAPS_ALIGNBOUNDARYDEST
dwAlignSizeDest | DDCAPS_ALIGNSIZEDEST
dwAlignStrideAlign | DDCAPS_ALIGNSTRIDE
dwMinOverlayStretch | DDCAPS_OVERLAYSTRETCH
dwMaxOverlayStretch | DDCAPS_OVERLAYSTRETCH

The dwMaxVisibleOverlays and dwCurrVisibleOverlays members carry information about the maximum number of overlays the hardware can display, and how many of them are currently visible.

Additionally, the hardware reports rectangle position and size alignment restrictions in the dwAlignBoundarySrc, dwAlignSizeSrc, dwAlignBoundaryDest, dwAlignSizeDest, and dwAlignStrideAlign members. The values in these members dictate how you must size and position source and destination rectangles when displaying overlay surfaces. For more information, see Source and Destination Rectangles and Boundary and Size Alignment.

Also, the hardware reports information about stretch factors in the dwMinOverlayStretch and dwMaxOverlayStretch members. For more information, see Minimum and Maximum Stretch Factors.


Source and Destination Rectangles

To display an overlay surface, you call the overlay surface's IDirectDrawSurface4::UpdateOverlay method, specifying the DDOVER_SHOW flag in the dwFlags parameter. The method requires you to specify a source and destination rectangle in the lpSrcRect and lpDestRect parameters. The source rectangle describes a rectangle on the overlay surface that will be visible on the primary surface. To request that the method use the entire surface, set the lpSrcRect parameter to NULL. The destination rectangle describes a portion of the primary surface on which the overlay surface will be displayed.

Source and destination rectangles do not need to be the same size. You can often specify a destination rectangle smaller or larger than the source rectangle, and the hardware will shrink or stretch the overlay appropriately when it is displayed.

To successfully display an overlay surface, you might need to adjust the size and position of both rectangles. Whether this is necessary depends on the restrictions imposed by the device driver. For more information, see Boundary and Size Alignment and Minimum and Maximum Stretch Factors.


Boundary and Size Alignment

Due to various hardware limitations, some device drivers impose restrictions on the position and size of the source and destination rectangles used to display overlay surfaces. To find out which restrictions apply for a device, call the IDirectDraw4::GetCaps method and then examine the overlay-related flags in the dwCaps member of the DDCAPS structure. The following table shows the members and flags specific to boundary and size alignment restrictions:

Category | Flag | Member
Boundary (position) restrictions | DDCAPS_ALIGNBOUNDARYSRC | dwAlignBoundarySrc
 | DDCAPS_ALIGNBOUNDARYDEST | dwAlignBoundaryDest
Size restrictions | DDCAPS_ALIGNSIZESRC | dwAlignSizeSrc
 | DDCAPS_ALIGNSIZEDEST | dwAlignSizeDest

There are two types of restrictions, boundary restrictions and size restrictions. Both types of restrictions are expressed in terms of pixels (not bytes) and can apply to the source and destination rectangles. Also, these restrictions can vary depending on the pixel formats of the overlay and primary surface.

Boundary restrictions affect where you can position a source or destination rectangle. The values in the dwAlignBoundarySrc and dwAlignBoundaryDest members tell you how to align the top left corner of the corresponding rectangle. The x-coordinate of the top left corner of the rectangle (the left member of the RECT structure), must be a multiple of the reported value.

Size restrictions affect the valid widths for source and destination rectangles. The values in the dwAlignSizeSrc and dwAlignSizeDest members tell you how to align the width, in pixels, of the corresponding rectangle. Your rectangles must have a pixel width that is a multiple of the reported value. If you stretch the rectangle to comply with a minimum required stretch factor, be sure that the stretched rectangle is still size aligned. After stretching the rectangle, align its width by rounding up, not down, so you preserve the minimum stretch factor. For more information, see Minimum and Maximum Stretch Factors.


Minimum and Maximum Stretch Factors

Due to hardware limitations, some devices restrict how wide a destination rectangle can be compared with the corresponding source rectangle. DirectDraw communicates these restrictions as stretch factors. A stretch factor is the ratio between the widths of the source and destination rectangles. If the driver provides information about stretch factors, it sets the DDCAPS_OVERLAYSTRETCH flag in the DDCAPS structure after you call the IDirectDraw4::GetCaps method. Note that stretch factors are reported multiplied by 1000, so a value of 1300 actually means 1.3 (and 750 would be 0.75).

Devices that do not impose limits on stretching or shrinking an overlay destination rectangle often report a minimum and maximum stretch factor of 0.

The minimum stretch factor tells you how much wider or narrower than the source rectangle the destination rectangle needs to be. If the minimum stretch factor is greater than 1000, then you must increase the destination rectangle's width by that ratio. For instance, if the driver reports 1300, you must make sure that the destination rectangle's width is at least 1.3 times the width of the source rectangle. Similarly, a minimum stretch factor less than 1000 indicates that the destination rectangle can be smaller than the source rectangle by that ratio.

The maximum stretch factor tells the maximum amount you can stretch the width of the destination rectangle. For example, if the maximum stretch factor is 2000, you can specify destination rectangles that are up to, but not wider than, twice the width of the source rectangle. If the maximum stretch factor is less than 1000, then you must shrink the width of the destination rectangle by that ratio to be able to display the overlay.

After stretching, the destination rectangle must conform to any size alignment restrictions the device might require. Therefore, it's a good idea to stretch the destination rectangle before adjusting it to be size aligned. For more information, see Boundary and Size Alignment.

Hardware does not require that you adjust the height of destination rectangles. You can increase a destination rectangle's height to preserve aspect ratio without negative effects.


Overlay Color Keys

Like other types of surfaces, overlay surfaces use source and destination color keys for controlling transparent blit operations between surfaces. Because overlay surfaces are not displayed by blitting, there needs to be a different way to control how an overlay surface is displayed over the primary surface when you call the IDirectDrawSurface4::UpdateOverlay method. This need is filled by overlay color keys. Overlay color keys, like their blit-related counterparts, have a source version and a destination version that you set by calling the IDirectDrawSurface4::SetColorKey method. (For more information, see Setting Color Keys.) You use the DDCKEY_SRCOVERLAY or DDCKEY_DESTOVERLAY flags to set a source or destination overlay color key. Overlay surfaces can employ blit and overlay color keys together to control blit operations and overlay display operations appropriately; the two types of color keys do not conflict with one another.

The IDirectDrawSurface4::UpdateOverlay method uses the source overlay color key to determine which pixels in the overlay surface should be considered transparent, allowing the contents of the primary surface to show through. Likewise, the method uses the destination overlay color key to determine the parts of the primary surface that will be covered up by the overlay surface when it is displayed. The resulting visual effect is the same as that created by blit-related color keys.


Positioning Overlay Surfaces

After initially displaying an overlay by calling the IDirectDrawSurface4::UpdateOverlay method, you can update the destination rectangle's by calling the IDirectDrawSurface4::SetOverlayPosition method.

Make sure that the positions you specify comply with any boundary alignment restrictions enforced by the hardware. For more information, see Boundary and Size Alignment. Also remember that SetOverlayPosition doesn't perform clipping for you; using coordinates that would potentially make the overlay run off the edge of the target surface will cause the method to fail, returning DDERR_INVALIDPOSITION.


Creating Overlay Surfaces

Like all surfaces, you create an overlay surface by calling the IDirectDraw4::CreateSurface method. To create an overlay, include the DDSCAPS_OVERLAY flag in the associated DDSCAPS2 structure.

Overlay support varies widely across display devices. As a result, you cannot be sure that a given pixel format will be supported by most drivers and must therefore be prepared to work with a variety of pixel formats. You can request information about the non-RGB formats that a driver supports by calling the IDirectDraw4::GetFourCCCodes method.

When you attempt to create an overlay surface, it is advantageous to try creating a surface with the most desirable pixel format, falling back on other pixel formats if a given pixel format isn't supported.

You can create overlay surface flipping chains. For more information, see Creating Complex Surfaces and Flipping Chains.


Overlay Z-Orders

Overlay surfaces are assumed to be on top of all other screen components, but when you display multiple overlay surfaces, you need some way to visually organize them. DirectDraw supports overlay z-ordering to manage the order in which overlays clip each other. Z-order values represent conceptual distances from the primary surface toward the viewer. They range from 0, which is just on top of the primary surface, to 4 billion, which is as close to the viewer as possible, and no two overlays can share the same z-order. You set z-order values by calling the IDirectDrawSurface4::UpdateOverlayZOrder method.

Destination color keys are affected only by the bits on the primary surface, not by overlays occluded by other overlays. Source color keys work on an overlay whether or not a z-order was specified for the overlay.

Overlays without a specified z-order are assumed to have a z-order of 0. Overlays that do not have a specified z-order behave in unpredictable ways when overlaying the same area on the primary surface.

A DirectDraw object does not track the z-orders of overlays displayed by other applications.

Note You can ensure proper clipping of multiple overlay surfaces by calling UpdateOverlayZOrder in response to WM_KILLFOCUS messages. When you receive this message, set your overlay surface to the rearmost z-order position by calling the UpdateOverlayZOrder method with the dwFlags parameter set to DDOVERZ_SENDTOBACK.


Flipping Overlay Surfaces

Like other types of surfaces, you can create overlay flipping chains. After creating a flipping chain of overlays, call the IDirectDrawSurface4::Flip method to flip between them. For more information, see Flipping Surfaces.

Software decoders displaying video with overlay surfaces can use the DDFLIP_ODD and DDFLIP_EVEN flags when calling the Flip method to use features that reduce motion artifacts. If the driver supports odd-even flipping, the DDCAPS2_CANFLIPODDEVEN flag will be set in the DDCAPS structure after retrieving driver capabilities. If DDCAPS2_CANFLIPODDEVEN is set, you can include the DDOVER_BOB flag when calling the IDirectDrawSurface4::UpdateOverlay method to inform the driver that you want it to use the "Bob" algorithm to minimize motion artifacts. Later, when you call Flip with the DDFLIP_ODD or DDFLIP_EVEN flag, the driver will automatically adjust the overlay source rectangle to compensate for jittering artifacts.

If the driver doesn't set the DDCAPS2_CANFLIPODDEVEN flag when you retrieve hardware capabilities, UpdateOverlay will fail if you specify the DDOVER_BOB flag.

For more information about the Bob algorithm, see Solutions to Common Video Artifacts.


Compressed Texture Surfaces

A surface can contain a bitmap to be used for texturing 3-D objects. When creating the surface you must specify the DDSCAPS_TEXTURE flag in the dwFlags member of the DDSCAPS structure.

For more information on the use of textures in Direct3D Immediate Mode, see Textures.

In order to reduce the amount of memory consumed by textures, DirectDraw supports the compression of texture surfaces.

Some Direct3D devices support compressed texture surfaces natively. On such devices, once you have created a compressed surface and loaded the data into it, the surface can be used in Direct3D just like any other texture surface. Direct3D handles decompression when the texture is mapped to a 3-D object.

Other devices do not support compressed texture surfaces natively. When using such devices, you may still find it useful to use compressed surfaces to represent textures on disk or for textures that are loaded into memory but not currently being used. You can use DirectDraw to convert the compressed textures to an uncompressed format before giving the texture to Direct3D.

For more information on texture compression in DirectDraw, see the following topics:

  • Creating Compressed Textures
  • Decompressing Compressed Textures
  • Transparency in Blits to Compressed Textures
  • Compressed Texture Formats

For information on using compressed textures in Direct3D Immediate Mode, see Texture Compression.


Creating Compressed Textures

To describe a compressed texture surface in the DDSURFACEDESC2 structure when creating the surface, you must include the following steps:

  • Specify the DDSCAPS_TEXTURE flag in the dwFlags member of the DDSCAPS structure, just as you would for any texture.
  • Set the dwFourCC member of the DDPIXELFORMAT structure to one of the DXT codes described later.
  • Include DDPF_FOURCC in the dwFlags member of DDPIXELFORMAT. Do not set the DDPF_RGB flag.
  • Specify a width and height that are a multiple of 4 pixels.

There are two ways to load image data into a compressed texture surface:

  • Create a regular RGB or ARGB surface and load a normal bitmap into it, then use IDirectDrawSurface4::Blt or IDirectDrawSurface4::BltFast to blit from the uncompressed surface to the compressed surface. DirectDraw does the compression for you.
  • Load the compressed data from a file and copy it directly into the surface memory. (See Accessing Surface Memory Directly.) You can create and convert compressed texture (DDS) files using the DirectX Texture Tool (Dxtex.exe) supplied with the Programmer's Reference. You can also create your own DDS files and either copy the data from compressed surfaces or else use your own routines to convert regular bitmap data to one of the compressed formats.

Note When you call IDirectDrawSurface4::Lock or IDirectDrawSurface4::GetSurfaceDesc on a compressed surface, the DDSD_LINEARSIZE flag is set in the dwFlags member of the DDSURFACEDESC structure, and the dwLinearSize member contains the number of bytes allocated to contain the compressed surface data. The dwLinearSize parameter resides in a union with the lPitch parameter, so these parameters are mutually exclusive, as are the flags DDSD_LINEARSIZE and DDSD_PITCH.

The advantage of this behavior is that an application can copy the contents of a compressed surface to a file without having to calculate for itself how much storage is required for a surface of a particular width and height in the specific format.

The following table shows the five types of compressed textures. For more information on how the data is stored (you need to know this only if you are writing your own compression routines) see Compressed Texture Formats.

FOURCC | Description | Alpha premultiplied?
DXT1 | Opaque / one-bit alpha | n/a
DXT2 | Explicit alpha | Yes
DXT3 | Explicit alpha | No
DXT4 | Interpolated alpha | Yes
DXT5 | Interpolated alpha | No

Note When you blit from a non-premultiplied format to a premultiplied format, DirectDraw scales the colors based on the alpha values. Blitting from a premultiplied format to a non-premultiplied format is not supported. If you try to blit from a premultiplied-alpha source to a non-premultiplied-alpha destination, the method will return DDERR_INVALIDPARAMS. If you blit from a premultiplied-alpha source to a destination that has no alpha, the source color components, which have been scaled by alpha, will be copied as is.


Decompressing Compressed Textures

As with compressing a texture surface, decompressing a compressed texture is performed through DirectDraw blitting services. The HEL performs decompressing blits between system memory surfaces, so these always supported. Likewise, the HEL always performs blits for compressed managed textures (the DDSCAPS2_TEXTUREMANAGE capability). For other situations, the restrictions discussed in the following paragraphs apply.

If the driver supports the creation of compressed video-memory surfaces, then the driver can also perform decompressing blits from a compressed video-memory surface to an uncompressed video or system memory surface, so long as the destination surface has the DDSCAPS_OFFSCREENPLAIN capability.

Blits from compressed system-memory surfaces to uncompressed video-memory surfaces are largely unsupported and should not be attempted, even when the driver supports compressed textures. This does not mean that it is impossible to decompress a compressed system-memory surface and move its contents into a video memory surface; it merely requires an additional step:

To decompress a system memory surface into video memory:

  1. Create an uncompressed, offscreen-plain, surface in system memory of the desired dimensions and pixel format.
  2. Blit from the compressed system-memory surface to the uncompressed system-memory surface. (The DirectDraw HEL performs decompression in this case.)
  3. Blit the uncompressed surface to the uncompressed video-memory surface.


Transparency in Blits to Compressed Textures

DirectDraw provides a special trick for creating compressed textures with alpha from plain RGB surfaces. If a source color key is provided on the source RGB surface, DirectDraw assigns an alpha value of 0 to all pixels of that color in the destination. This technique is especially useful for creating DXT1 textures, since they effectively have only 1 bit of alpha information per pixel.

Note There are no flags that control this behavior. If you do not want any transparency in your compressed texture, do not set a source color key on the source surface.


Compressed Texture Formats

This section contains information on the internal organization of compressed texture formats. You don't need these details in order to use compressed textures, because DirectDraw handles conversion to and from compressed formats. However, you might find this information useful if you want to operate on compressed surface data directly.

DirectDraw uses a compression format that divides texture maps into 4x4 texel blocks. If the texture contains no transparency (is opaque), or if the transparency is specified by a one-bit alpha, an 8-byte block represents the texture map block. If the texture map does contain transparent texels, using an alpha channel, a 16-byte block represents it.

These two types of format are discussed in the following sections:

  • Opaque and One-bit Alpha Textures
  • Textures with Alpha Channels

Note Any single texture must specify that its data is stored as 64 or 128 bits per group of 16 texels. If 64-bit blocks—that is, format DXT1—are used for the texture, it is possible to mix the opaque and one-bit alpha formats on a per-block basis within the same texture. In other words, the comparison of the unsigned integer magnitude of color_0 and color_1 is performed uniquely for each block of 16 texels.

When 128-bit blocks are used, then the alpha channel must be specified in either explicit (format DXT2 or DXT3) or interpolated mode (format DXT4 or DXT5) for the entire texture. Note that as with color, once interpolated mode is selected then either 8 interpolated alphas or 6 interpolated alphas mode can be used on a block-by-block basis. Again the magnitude comparison of alpha_0 and alpha_1 is done uniquely on a block-by-block basis.


Opaque and One-bit Alpha Textures

Texture format DXT1 is for textures that are opaque or have a single transparent color.

For each opaque or one-bit alpha block, two 16-bit values (RGB 5:6:5 format) and a 4x4 bitmap with 2-bits-per-pixel are stored. This totals 64 bits for 16 texels, or 4-bits-per-texel. In the block bitmap, there are two bits per texel to select between the four colors, two of which are stored in the encoded data. The other two colors are derived from these stored colors by linear interpolation.

The one-bit alpha format is distinguished from the opaque format by comparing the two 16-bit color values stored in the block. They are treated as unsigned integers. If the first color is greater than the second, it implies that only opaque texels are defined. This means four colors will be used to represent the texels. In four-color encoding, there are two derived colors and all four colors are equally distributed in RGB color space. This format is analogous to RGB 5:6:5 format. Otherwise, for one-bit alpha transparency, three colors are used and the fourth is reserved to represent transparent texels.

In three-color encoding, there is one derived color and the fourth two-bit code is reserved to indicate a transparent texel (alpha information). This format is analogous to RGBA 5:5:5:1, where the final bit is used for encoding the alpha mask.

The following piece of pseudo-code illustrates the algorithm for deciding whether three- or four-color encoding is selected:

if (color_0 > color_1)
{
    // Four-color block: derive the other two colors.
    // 00 = color_0, 01 = color_1, 10 = color_2, 11 = color_3
    // These two bit codes correspond to the 2-bit fields
    // stored in the 64-bit block.
     color_2 = (2 * color_0 + color_1) / 3;
     color_3 = (color 0 + 2 * color_1) / 3;
}
else
{
    // Three-color block: derive the other color.
    // 00 = color_0,  01 = color_1,  10 = color_2,
    // 11 = transparent.
    // These two bit codes correspond to the 2-bit fields
    // stored in the 64-bit block.
     color_2 = (color_0 + color_1) / 2;
     color_3 = transparent;
}

The following tables show the memory layout for the 8-byte block. It is assumed that the first index corresponds to the y-coordinate and the second corresponds to the x-coordinate. For example, Texel[1][2] refers to the texture map pixel at (x,y) = (2,1).

Here is the memory layout for the 8-byte (64-bit) block:

Word address | 16-bit word
0 | Color_0
1 | Color_1
2 | Bitmap Word_0
3 | Bitmap Word_1

Color_0 and Color_1 (colors at the two extremes) are laid out as follows:

Bits | Color
4:0 (LSB) | Blue color component
10:5 | Green color component
15:11 | Red color component

Bitmap Word_0 is laid out as follows:

Bits | Texel
1:0 (LSB) | Texel[0][0]
3:2 | Texel[0][1]
5:4 | Texel[0][2]
7:6 | Texel[0][3]
9:8 | Texel[1][0]
11:10 | Texel[1][1]
13:12 | Texel[1][2]
15:14 (MSB) | Texel[1][3]

Bitmap Word_1 is laid out as follows:

Bits | Texel
1:0 (LSB) | Texel[2][0]
3:2 | Texel[2][1]
5:4 | Texel[2][2]
7:6 | Texel[2][3]
9:8 | Texel[3][0]
11:10 | Texel[3][1]
13:12 | Texel[3][2]
15:14 (MSB) | Texel[3][3]

Example of Opaque Color Encoding

As an example of opaque encoding, we will assume that the colors red and black are at the extremes. We will call red color_0 and black color_1. There will be four interpolated colors that form the uniformly distributed gradient between them. To determine the values for the 4x4 bitmap, the following calculations are used:

00 ? color_0
01 ? color_1
10 ? 2/3 color_0 + 1/3 color_1
11 ? 1/3 color_0 + 2/3 color_1

Example of One-bit Alpha Encoding

This format is selected when the unsigned 16-bit integer, color_0, is less than the unsigned 16-bit integer, color_1. An example of where this format could be used is leaves on a tree to be shown against a blue sky. Some texels could be marked as transparent while three shades of green are still available for the leaves. Two of these colors fix the extremes, and the third color is an interpolated color.

The bitmap encoding for the colors and the transparency is determined using the following calculations:

00 ? color_0
01 ? color_1
10 ? 1/2 color_0 + 1/2 color_1
11   ?   Transparent


Textures with Alpha Channels

There are two ways to encode texture maps that exhibit more complex transparency. In each case, a block that describes the transparency precedes the 64-bit block already described. The transparency is either represented as a 4x4 bitmap with four bits per pixel (explicit encoding), or with fewer bits and linear interpolation analogous to what is used for color encoding.

The transparency block and the color block are laid out as follows:

Word Address | 64-bit Block
3:0 | Transparency block
7:4 | Previously described 64-bit block

Explicit Texture Encoding

For explicit texture encoding (DXT2 and DXT3 formats), the alpha components of the texels that describe transparency are encoded in a 4x4 bitmap with 4 bits per texel. These 4 bits can be achieved through a variety of means such as dithering or by simply using the 4 most significant bits of the alpha data. However they are produced, they are used just as they are, without any form of interpolation.

Note DirectDraw's compression method uses the 4 most significant bits.

The following tables illustrate how the alpha information is laid out in memory, for each 16-bit word.

This is the layout for Word 0:

Bits | Alpha
3:0 (LSB) | [0][0]
7:4 | [0][1]
11:8 | [0][2]
15:12 (MSB) | [0][3]

This is the layout for Word 1:

Bits | Alpha
3:0 (LSB) | [1][0]
7:4 | [1][1]
11:8 | [1][2]
15:12 (MSB) | [1][3]

This is the layout for Word 2:

Bits | Alpha
3:0 (LSB) | [2][0]
7:4 | [2][1]
11:8 | [2][2]
15:12 (MSB) | [2][3]

This is the layout for Word 3:

Bits | Alpha
3:0 (LSB) | [3][0]
7:4 | [3][1]
11:8 | [3][2]
15:12 (MSB) | [3][3]

Three-Bit Linear Alpha Interpolation

The encoding of transparency for the DXT4 and DXT5 formats is based on a concept similar to the linear encoding used for color. Two 8-bit alpha values and a 4x4 bitmap with three bits per pixel are stored in the first eight bytes of the block. The representative alpha values are used to interpolate intermediate alpha values. Additional information is available in the way the two alpha values are stored. If alpha_0 is greater than alpha_1, then six intermediate alpha values are created by the interpolation. Otherwise, four intermediate alpha values are interpolated between the specified alpha extremes. The two additional implicit alpha values are 0 (fully transparent) and 255 (fully opaque).

The following pseudo-code illustrates this algorithm:

// 8-alpha or 6-alpha block?
if (alpha_0 > alpha_1) {
     // 8-alpha block:  derive the other 6 alphas.
    // 000 = alpha_0, 001 = alpha_1, others are interpolated
    alpha_2 = (6 * alpha_0 + alpha_1) / 7;      // bit code 010
    alpha_3 = (5 * alpha_0 + 2 * alpha_1) / 7;  // Bit code 011
    alpha_4 = (4 * alpha_0 + 3 * alpha_1) / 7;  // Bit code 100
    alpha_5 = (3 * alpha_0 + 4 * alpha_1) / 7;  // Bit code 101
    alpha_6 = (2 * alpha_0 + 5 * alpha_1) / 7;  // Bit code 110
    alpha_7 = (alpha_0 + 6 * alpha_1) / 7;      // Bit code 111
  }
else {  // 6-alpha block:  derive the other alphas.
    // 000 = alpha_0, 001 = alpha_1, others are interpolated
    alpha_2 = (4 * alpha_0 + alpha_1) / 5;      // Bit code 010
    alpha_3 = (3 * alpha_0 + 2 * alpha_1) / 5;  // Bit code 011
    alpha_4 = (2 * alpha_0 + 3 * alpha_1) / 5;  // Bit code 100
    alpha_5 = (alpha_0 + 4 * alpha_1) / 5;      // Bit code 101
    alpha_6 = 0;                                // Bit code 110
    alpha_7 = 255;                              // Bit code 111
}

The memory layout of the alpha block is as follows:

Byte | Alpha
0 | Alpha_0
1 | Alpha_1
2 | [0][2] (2 LSBs), [0][1], [0][0]
3 | [1][1] (1 LSB), [1][0], [0][3], [0][2] (1 MSB)
4 | [1][3], [1][2], [1][1] (2 MSBs)
5 | [2][2] (2 LSBs), [2][1], [2][0]
6 | [3][1] (1 LSB), [3][0], [2][3], [2][2] (1 MSB)
7 | [3][3], [3][2], [3][1] (2 MSBs)


Private Surface Data

You can store any kind of application-specific data with a surface. For example, a surface representing a map in a game might contain information about terrain.

A surface can have more than one private data buffer. Each buffer is identified by a GUID which you supply when attaching the data to the surface.

To store private surface data, you use the IDirectDrawSurface4::SetPrivateData method, passing in a pointer to the source buffer, the size of the data, and an application-defined GUID for the data. Optionally, the source data can exist in the form of a COM object; in this case, you pass a pointer to the object's IUnknown interface pointer and you set the DDSPD_IUNKNOWNPOINTER flag. Another flag, DDSPD_VOLATILE, indicates that the data being attached to the surface is valid only as long as the contents of the surface do not change. (See Surface Uniqueness Values.)

SetPrivateData allocates an internal buffer for the data and copies it. You can then safely free the source buffer or object. The internal buffer or interface reference is released when IDirectDrawSurface4::FreePrivateData is called. This happens automatically when the surface is freed.

To retrieve private data for a surface, you must allocate a buffer of the correct size and then call the IDirectDrawSurface4::GetPrivateData method, passing the GUID that was assigned to the data by SetPrivateData. You are responsible for freeing any dynamic memory you use for this buffer. If the data is a COM object, this method retrieves the IUnknown pointer.

If you don't know how big a buffer to allocate, first call GetPrivateData with zero in *lpcbBufferSize. If the method fails with DDERR_MOREDATA, it returns the necessary number of bytes in *lpcbBufferSize.


Surface Uniqueness Values

The uniqueness value of a surface allows you to determine whether the surface has changed. When DirectDraw creates a surface, it assigns a uniqueness value, which you can retrieve and store by using the IDirectDrawSurface4::GetUniquenessValue method. Then, whenever you need to determine whether the surface has changed, you call the method again and compare the new value against the old one. If it's different, the surface has changed.

The actual value returned by GetUniquenessValue is irrelevant, unless it is 0. DirectDraw assigns this value to a surface when it knows that the surface might be changed by some process beyond its control. When GetUniquenessValue returns 0, you know only that the state of the surface is indeterminate.

To force the uniqueness value for a surface to change, an application can use the IDirectDrawSurface4::ChangeUniquenessValue method. This method could be called, for example, by an application or component that changed the private data for a surface without changing the surface itself, and wished to notify some other process of the change. Most applications, however, never need to change the uniqueness value.


Using Non-local Video Memory Surfaces

DirectDraw supports the Accelerated Graphics Port (AGP) architecture for creating surfaces in non-local video memory. On AGP-equipped systems, DirectDraw will use non-local video memory if local video memory is exhausted or if non-local video memory is explicitly requested, depending on the type of AGP implementation that is in place.

Currently, there are two implementations of the AGP architecture, known as the "execute model" and the "DMA model." In the execute model implementation, the display device supports the same features for non-local video memory surfaces and local video memory surfaces. As a result, when you retrieve hardware capabilities by calling the IDirectDraw4::GetCaps method, the blit-related flags in the dwNLVBCaps, dwNLVBCaps2, dwNLVBCKeyCaps, dwNLVBFXCaps, and dwNLVBRops members of the DDCAPS structure will be identical to those for local video memory. Under the execute model, if local video memory is exhausted, DirectDraw will automatically fall back on non-local video memory unless the caller specifically requests otherwise.

In the DMA model implementation, support for blitting and texturing from non-local video memory surfaces is limited. When the display device uses the DMA model, the DDCAPS2_NONLOCALVIDMEMCAPS flag will be set in the dwCaps2 member when you retrieve device capabilities. In the DMA model, the blit-related flags included in the dwNLVBCaps, dwNLVBCaps2, dwNLVBCKeyCaps, dwNLVBFXCaps, and dwNLVBRops members of the DDCAPS structure describe the features that are supported; these features will often be a smaller subset of those supported for local video memory surfaces. Under the DMA model, when local video memory is exhausted, DirectDraw will automatically fall back on non-local video memory for texture surfaces only, unless the caller had explicitly requested local video memory. Texture surfaces are the only types of surfaces that will be treated this way; all other types of surfaces cannot be created in non-local video memory unless the caller explicitly requests it.

DMA model implementations vary in support for texturing from non-local video memory surfaces. If the driver supports texturing from non-local video memory surfaces, the D3DDEVCAPS_TEXTURENONLOCALVIDMEM flag will be set when you retrieve the 3-D device's capabilities by calling the IDirect3DDevice3::GetCaps method.


Converting Color and Format

Non-RGB surface formats are described by four-character codes (FOURCC). If an application calls the IDirectDrawSurface4::GetPixelFormat method to request the pixel format, and the surface is a non-RGB surface, the DDPF_FOURCC flag will be set and the dwFourCC member of the DDPIXELFORMAT structure will be valid. If the FOURCC code represents a YUV format, the DDPF_YUV flag will also be set and the dwYUVBitCount, dwYBitMask, dwUBitMask, dwVBitMask, and dwYUVAlphaBitMask members will be valid masks that can be used to extract information from the pixels.

If an RGB format is present, the DDPF_RGB flag will be set and the dwRGBBitCount, dwRBitMask, dwGBitMask, dwBBitMask, and dwRGBAlphaBitMask members will be valid masks that can be used to extract information from the pixels. The DDPF_RGB flag can be set in conjunction with the DDPF_FOURCC flag if a nonstandard RGB format is being described.

During color and format conversion, two sets of FOURCC codes are exposed to the application. One set of FOURCC codes represents the capabilities of the blitting hardware; the other represents the capabilities of the overlay hardware.

For more information, see Four Character Codes (FOURCC).


Surfaces and Device Contexts

It is often convenient to mix-and-match DirectDraw and GDI services to manipulate the contents of DirectDraw surfaces. DirectDraw offers methods to enable GDI to access DirectDraw surfaces through device contexts, and to retrieve a surface given the surface's device context. This section contains the follows topics that describe these features in detail:

  • Retrieving the Device Context for a Surface
  • Finding a Surface with a Device Context


Retrieving the Device Context for a Surface

If you want to modify the contents of a DirectDraw surface object by using GDI functions, you must retrieve a GDI-compatible device context handle. This could be useful if you wanted to display text in a DirectDraw surface by calling the DrawText Win32 function, which accepts a handle to a device context as a parameter. It is possible to retrieve a GDI-compatible device context for a surface by calling the IDirectDrawSurface4::GetDC method for that surface. The following example shows how this might be done:

// For this example the lpDDS4 variable is a valid pointer
// to an IDirectDrawSurface4 interface.

    HDC     hdc;
    HRESULT HR;

    hr = lpDDS4->GetDC(&hdc);
    if(FAILED(hr))
        return hr;

    // Call DrawText, or some other GDI
    // function here.

    lpDDS4->ReleaseDC(hdc);

Note that the code calls the IDirectDrawSurface4::ReleaseDC method when the surface's device context is no longer needed. This step is required, because the IDirectDrawSurface4::GetDC method uses an internal version of the IDirectDrawSurface4::Lock method to lock the surface. The surface remains locked until the IDirectDrawSurface4::ReleaseDC method is called.


Finding a Surface with a Device Context

You can retrieve a pointer to a surface's IDirectDrawSurface4 interface from the device context for the surface by calling the IDirectDraw4::GetSurfaceFromDC method. This feature might be very useful for component applications or ActiveX® controls, that are commonly given a device context to draw into at run-time, but could benefit by exploiting the features exposed by the IDirectDrawSurface4 interface.

A device context might identify memory that isn't associated with a DirectDraw object, or the device context might identify a surface for another DirectDraw object entirely. The latter case is most likely to occur on a system with multiple monitors. If the device context doesn't identify a surface that wasn't created by that DirectDraw object, the method fails, returning DDERR_NOTFOUND.

The following sample code shows what a very simple scenario might look like:

    // For this example, the hdc variable is a valid
    // handle to a video memory device context, and the
    // lpDD4 variable is a valid IDirectDraw4 interface pointer.

    LPDIRECTDRAWSURFACE4 lpDDS4;
    HRESULT hr;

    hr = lpDD4->GetSurfaceFromDC(hdc, &lpDDS4);
    if(SUCCEEDED(hr)) {
        // Use the surface interface.
    }
    else if(DDERR_NOTFOUND == hr) {
        OutputDebugString("HDC not from this DirectDraw surface\n");
    }


Palettes

This section contains information about DirectDrawPalette objects. The following topics are discussed:

  • What Are Palettes?
  • Palette Types
  • Setting Palettes on Nonprimary Surfaces
  • Sharing Palettes
  • Palette Animation


What Are Palettes?

Palettized surfaces need palettes to be meaningfully displayed. A palettized surface, also known as a color-indexed surface, is simply a collection of numbers where each number represents a pixel. The value of the number is an index into a color table that tells DirectDraw what color to use when displaying that pixel. DirectDrawPalette objects, casually referred to as palettes, provide you with an easy way to manage a color table. Surfaces that use a 16-bit or greater pixel format do not use palettes.

A DirectDrawPalette object represents an indexed color table that has 2, 4, 16 or 256 entries to be used with a color indexed surface. Each entry in the palette is an RGB triplet that describes the color to be used when displaying pixels within the surface. The color table can contain 16- or 24-bit RGB triplets representing the colors to be used. For 16-color palettes, the table can also contain indexes to another 256-color palette. Palettes are supported for textures, off-screen surfaces, and overlay surfaces, none of which is required to have the same palette as the primary surface.

You can create a palette by calling the IDirectDraw4::CreatePalette method. This method retrieves a pointer to the palette object's IDirectDrawPalette interface. You can use the methods of this interface to manipulate palette entries, retrieve information about the object's capabilities, or initialize the object (if you used the CoCreateInstance COM function to create it).

You apply a palette to a surface by calling the surface's IDirectDrawSurface4::SetPalette method. A single palette can be applied to multiple surfaces.

DirectDrawPalette objects reserve entry 0 and entry 255 for 8-bit palettes, unless you specify the DDPCAPS_ALLOW256 flag to request that these entries be made available to you.

You can retrieve palette entries by using the IDirectDrawPalette::GetEntries method, and you can change entries by using the IDirectDrawPalette::SetEntries method.

The Ddutil.cpp source file included with the SDK contains some handy application-defined functions for working with palettes. For more information, see the DDLoadPalette functions in that source file.


Palette Types

DirectDraw supports 1-bit (2 entry), 2-bit (4 entry), 4-bit (16 entry), and 8-bit (256 entry) palettes. A palette can only be attached to a surface that has a matching pixel format. For example, a 2-entry palette created with the DDPCAPS_1BIT flag can be attached only to a 1-bit surface created with the DDPF_PALETTEINDEXED1 flag.

Additionally, you can create palettes that don't contain a color table at all, known as index palettes. Instead of a color table, an index palette contains index values that represent locations in another palette's color table.

To create an indexed palette, specify the DDPCAPS_8BITENTRIES flag when calling the IDirectDraw4::CreatePalette method. For example, to create a 4-bit indexed palette, specify both the DDPCAPS_4BIT and DDPCAPS_8BITENTRIES flags. When you create an indexed palette, you pass a pointer to an array of bytes rather than a pointer to an array of PALETTEENTRY structures. You must cast the pointer to the array of bytes to an LPPALETTEENTRY type when you use the IDirectDraw4::CreatePalette method.

Note that DirectDraw does not dereference index palette entries during blit operations.


Setting Palettes on Nonprimary Surfaces

Palettes can be attached to any palettized surface (primary, back buffer, off-screen plain, or texture map). Only those palettes attached to primary surfaces will have any effect on the system palette. It is important to note that DirectDraw blits never perform color conversion; any palettes attached to the source or destination surface of a blit are ignored.

Nonprimary surface palettes are intended for use by Direct3D applications.


Sharing Palettes

Palettes can be shared among multiple surfaces. The same palette can be set on the front buffer and the back buffer of a flipping chain or shared among multiple texture surfaces. When an application attaches a palette to a surface by using the IDirectDrawSurface4::SetPalette method, the surface increments the reference count of that palette. When the reference count of the surface reaches 0, the surface will decrement the reference count of the attached palette. In addition, if a palette is detached from a surface by using IDirectDrawSurface4::SetPalette with a NULL palette interface pointer, the reference count of the surface's palette will be decremented.

Note If IDirectDrawSurface4::SetPalette is called several times consecutively on the same surface with the same palette, the reference count for the palette is incremented only once. Subsequent calls do not affect the palette's reference count.


Palette Animation

Palette animation refers to the process of modifying a surface's palette to change how the surface itself looks when displayed. By repeatedly changing the palette, the surface appears to change without actually modifying the contents of the surface. To this end, palette animation gives you a way to modify the appearance of a surface without changing its contents and with very little overhead.

There are two methods for providing straightforward palette animation:

  • Modifying palette entries within a single palette
  • Switching between multiple palettes

Using the first method, you change individual palette entries that correspond to the colors you want to animate, then reset the entries with a single call to the IDirectDrawPalette::SetEntries method.

The second method requires two or more DirectDrawPalette objects. When using this method, you perform the animation by attaching one palette object after another to the surface object by calling the IDirectDrawSurface4::SetPalette method.

Neither method is hardware intensive, so use whichever technique works best for your application.

For specific information and an example of how to implement palette animation, see Tutorial 5: Dynamically Modifying Palettes.


Clippers

This section contains information about DirectDrawClipper objects. The following topics are discussed:

  • What Are Clippers?
  • Clip Lists
  • Sharing DirectDrawClipper Objects
  • Independent DirectDrawClipper Objects
  • Creating DirectDrawClipper Objects with CoCreateInstance
  • Using a Clipper with the System Cursor
  • Using a Clipper with Multiple Windows


What Are Clippers?

Clippers, or DirectDrawClipper objects, allow you to blit to selected parts of a surface represented by a bounding rectangle or a list of several bounding rectangles. (See Clip Lists.)

One common use for a clipper is to define the boundaries of the screen or window. For example, imagine that you want to display a sprite as it enters the screen from an edge. You don't want to make the sprite pop suddenly onto the screen; you want it to appear as though it is smoothly moving into view. Without a clipper object, DirectDraw does not allow you to blit the entire sprite, because part of it would fall outside the destination surface. A straight copy of the pixel values in the sprite to the destination surface buffer would result in an incorrect display and even memory access violations. With a clipper that has the screen rectangle as its clip list, DirectDraw knows how to trim the sprite as it performs the blit so that only the visible portion is copied.

The following illustration shows this type of clipping.

You can also use clipper objects to designate certain areas within a destination surface as writable. DirectDraw clips blit operations in these areas, protecting the pixels outside the specified clipping rectangle.

The following illustration shows this use of a clipper.


Clip Lists

A clip list consists of one or more RECT structures, in pixel coordinates. DirectDraw manages clip lists by using a DirectDrawClipper object, which can be attached to any surface.

The IDirectDrawSurface4::Blt method copies data only to rectangles in the clip list. For instance, if the upper-right quarter of a surface was excluded by the rectangles in the clip list, and an application blitted to the entire area of the clipped surface, DirectDraw would effectively perform two blits, the first being to the upper-left corner of the surface, and the second being to the bottom half of the surface, as shown in the following diagram.

You can manage a surface's clip list manually or, for a primary surface, have it done automatically by DirectDraw.

To manage the clip list yourself, create a list of rectangles in the form of a RGNDATA structure and pass this to the IDirectDrawClipper::SetClipList method.

To have DirectDraw manage the clip list for a primary surface, you attach the clipper to a window (even a full-screen window) by calling the IDirectDrawClipper::SetHWnd method, specifying the target window's handle. This has the effect of setting the clipping region to the client area of the window and ensuring that the clip list is automatically updated as the window is resized, covered, or uncovered.

If you set a clipper using a window handle, you cannot set additional rectangles.

Clipping for overlay surfaces is supported only if the overlay hardware can support clipping and if destination color keying is not active.


Sharing DirectDrawClipper Objects

DirectDrawClipper objects can be shared between multiple surfaces. For example, the same DirectDrawClipper object can be set on both the front buffer and the back buffer of a flipping chain. When an application attaches a DirectDrawClipper object to a surface by using the IDirectDrawSurface4::SetClipper method, the surface increments the reference count of that object. When the reference count of the surface reaches 0, the surface will decrement the reference count of the attached DirectDrawClipper object. In addition, if a DirectDrawClipper object is detached from a surface by calling IDirectDrawSurface4::SetClipper with a NULL clipper interface pointer, the reference count of the surface's DirectDrawClipper object will be decremented.

Note If IDirectDrawSurface4::SetClipper is called several times consecutively on the same surface for the same DirectDrawClipper object, the reference count for the object is incremented only once. Subsequent calls do not affect the object's reference count.


Independent DirectDrawClipper Objects

You can create DirectDrawClipper objects that are not directly owned by any particular DirectDraw object. These DirectDrawClipper objects can be shared across multiple DirectDraw objects. Driver-independent DirectDrawClipper objects are created by using the new DirectDrawCreateClipper DirectDraw function. An application can call this function before any DirectDraw objects are created.

Because DirectDraw objects do not own these DirectDrawClipper objects, they are not automatically released when your application's objects are released. If the application does not explicitly release these DirectDrawClipper objects, DirectDraw will release them when the application closes.

You can still create DirectDrawClipper objects by using the IDirectDraw4::CreateClipper method. These DirectDrawClipper objects are automatically released when the DirectDraw object from which they were created is released.


Creating DirectDrawClipper Objects with CoCreateInstance

DirectDrawClipper objects have full class-factory support for COM compliance. In addition to using the standard DirectDrawCreateClipper function and IDirectDraw4::CreateClipper method, you can also create a DirectDrawClipper object either by using the CoGetClassObject function to obtain a class factory and then calling the CoCreateInstance function, or by calling CoCreateInstance directly. The following example shows how to create a DirectDrawClipper object by using CoCreateInstance and the IDirectDrawClipper::Initialize method.

ddrval = CoCreateInstance(&CLSID_DirectDrawClipper,
    NULL, CLSCTX_ALL, &IID_IDirectDrawClipper, &lpClipper);
if (!FAILED(ddrval))
    ddrval = IDirectDrawClipper_Initialize(lpClipper,
        lpDD, 0UL);

In this call to CoCreateInstance, the first parameter, CLSID_DirectDrawClipper, is the class identifier of the DirectDrawClipper object class, the IID_IDirectDrawClipper parameter identifies the currently supported interface, and the lpClipper parameter points to the DirectDrawClipper object that is retrieved.

An application must use the IDirectDrawClipper::Initialize method to initialize DirectDrawClipper objects that were created by the class-factory mechanism before it can use the object. The value 0UL is the dwFlags parameter, which in this case has a value of 0 because no flags are currently supported. In the example shown here, lpDD is the DirectDraw object that owns the DirectDrawClipper object. However, you could supply a NULL value instead, which would create an independent DirectDrawClipper object. (This is equivalent to creating a DirectDrawClipper object by using the DirectDrawCreateClipper function.)

Before you close the application, close the COM library by using the CoUninitialize function.


Using a Clipper with the System Cursor

DirectDraw applications often need to provide a way for users to navigate using the mouse. For full-screen exclusive mode applications that use page-flipping, the only option is to implement a mouse cursor manually with a sprite, moving the sprite based on data retrieved from the device by DirectInput® or by responding to Windows mouse messages. However, any application that doesn't use page-flipping can still use the system's mouse cursor support.

When you use the system mouse cursor, you will sometimes fall victim to graphic artifacts that occur when you blit to parts of the primary surface. These artifacts appear as portions of the mouse cursor seemingly left behind by the system.

A DirectDrawClipper object can prevent these artifacts from appearing by preventing the mouse cursor image from "being in the way" during a blit operation. It's a relatively simple matter to implement, as well. To do so, create a DirectDrawClipper object by calling the IDirectDraw4::CreateClipper method. Then, assign your application's window handle to the clipper with the IDirectDrawClipper::SetHWnd method. Once a clipper is attached, any subsequent blits you perform on the primary surface with the IDirectDrawSurface4::Blt method will not exhibit the artifact.

Note that the IDirectDrawSurface4::BltFast method, and its counterparts in the IDirectDrawSurface, IDirectDrawSurface2, and IDirectDrawSurface3 interfaces, will not work on surfaces with attached clippers.


Using a Clipper with Multiple Windows

You can use a DirectDrawClipper object to blit to multiple windows created by an application running at the normal cooperative level.

To do this, create a single DirectDraw object with a primary surface. Then, create a DirectDrawClipper object and assign it to your primary surface by calling the IDirectDrawSurface4::SetClipper method. To blit only to the client area of a window, set the clipper to that window's client area by calling the IDirectDrawClipper::SetHWnd method before blitting to the primary surface. Whenever you need to blit to another window's client area, call the IDirectDrawClipper::SetHWnd method again with the new target window handle.

Creating multiple DirectDraw objects that blit to each others' primary surface is not recommended. The technique just described provides an efficient and reliable way to blit to multiple client areas with a single DirectDraw object.


Multiple Monitor Systems

Windows 98 and Windows 2000 support multiple display devices and monitors on a single system. The multiple monitor architecture (sometimes referred to as "MultiMon") enables the operating system to use the display area from two or more display devices and monitors to create a single logical desktop. For example, in a MultiMon system with two monitors, the user could display applications on either monitor, or even drag windows from one monitor to another. DirectDraw supports this architecture, allowing applications to directly access hardware on multiple display devices in a MultiMon system.

Note As long as it is created on the null device and is not rendering directly to the primary surface, a non-full-screen DirectDraw application will work automatically with MultiMon, and the user will be able to drag the window from one monitor to another. However, DirectDraw will take advantage of hardware acceleration only when the window is entirely within the primary display. It is recommended that windowed DirectDraw applications be specifically designed for MultiMon by maintaining separate DirectDraw objects and surfaces for each monitor. For more information, see Devices and Acceleration in MultiMon Systems.

This section contains information about using DirectDraw on systems with multiple monitor support. The following topics are discussed:

  • Enumerating Devices on MultiMon Systems
  • DirectDraw Objects on Multiple Monitors
  • Focus and Device Windows
  • Devices and Acceleration in MultiMon Systems
  • Debugging Full-Screen DirectDraw Applications with MultiMon

The Multimon.h header file included with the DirectX Programmer's Reference makes it possible for code written around Windows 98 multiple monitor functions to compile and run successfully on operating systems that do not support MultiMon.

The following sample applications demonstrate the implementation of MultiMon in DirectDraw:

  • Stretch2 Sample
  • Stretch3 Sample
  • Multimonitor Space Donuts Sample


Enumerating Devices on MultiMon Systems

Use the DirectDrawEnumerateEx function to enumerate devices on systems with multiple monitors, specifying flags to determine what types of DirectDraw devices should be enumerated. The function calls an application-defined DDEnumCallbackEx function for each enumerated device.

The DirectDrawEnumerateEx function is supported on Windows 98 and Windows 2000 operating systems. It is available in Ddraw.lib for applications compiled under DirectX 6.0 and later versions. Applications that statically link to the function will always run under DirectX 6.0 and later, and will always run under any version of DirectX on Windows 98 and Windows 2000. Such applications will fail if run on previous versions of DirectX under Windows 95.

If your application needs to run on versions of DirectX older than DirectX 5.0, it should use GetProcAddress to see if DirectDrawEnumerateEx is available. The following example shows one way you can do this:

    HINSTANCE h = LoadLibrary("ddraw.dll");

    // If ddraw.dll doesn't exist in the search path,
    // then DirectX probably isn't installed, so fail.
    if (!h)
        return FALSE;

    // Note that you must know which version of the
    // function to retrieve (see the following text).
    // For this example, we use the ANSI version.
    LPDIRECTDRAWENUMERATEEX lpDDEnumEx;
    lpDDEnumEx = (LPDIRECTDRAWENUMERATEEX) GetProcAddress(h,"DirectDrawEnumerateExA");

    // If the function is there, call it to enumerate all display
    // devices attached to the desktop, and any non-display DirectDraw
    // devices.
    if (lpDDEnumEx)
        lpDDEnumEx(Callback, NULL,
            DDENUM_ATTACHEDSECONDARYDEVICES |
            DDENUM_NONDISPLAYDEVICES
            );
    else
    {
        /*
         * We must be running on an old version of DirectDraw.
         * Therefore MultiMon isn't supported. Fall back on
         * DirectDrawEnumerate to enumerate standard devices on a
         * single-monitor system.
         */
        DirectDrawEnumerate(OldCallback,NULL);

        /* Note that it could be handy to let the OldCallback function
         * be a wrapper for a DDEnumCallbackEx.
         *
         * Such a function would look like:
         *    BOOL FAR PASCAL OldCallback(GUID FAR *lpGUID,
         *                                LPSTR pDesc,
         *                                LPSTR pName,
         *                                LPVOID pContext)
         *    {
         *         return Callback(lpGUID,pDesc,pName,pContext,NULL);
         *    }
         */
    }

    // If the library was loaded by calling LoadLibrary(),
    // then you must use FreeLibrary() to let go of it.
    FreeLibrary(h);

The previous example will work for applications that link to Ddraw.dll at run-time or load-time.

Note that you must retrieve the address of either the ANSI or Unicode version of the DirectDrawEnumerateEx function, depending of the type of strings your application uses. When declaring the corresponding callback function, use the LPTSTR data type for the string parameters. The LPTSTR data type compiles to use Unicode strings if you declare the _UNICODE symbol, and ANSI strings otherwise. By using the LPTSTR data type, the function should compile properly regardless of the string type you use in your application.


DirectDraw Objects on Multiple Monitors

Windowed DirectDraw applications written for the null or default display driver will work on MultiMon systems, but in applications optimized for MultiMon you will want to create a separate DirectDraw object for each device, using the GUID returned in the enumeration callback. (See Enumerating Devices on MultiMon Systems.)

Avoid setting the cooperative level multiple times on a MultiMon system. If you need to switch from full-screen to normal mode, it is best to create a new DirectDraw object.

It is good practice to release all DirectDraw objects at the same time. If you release only the secondary device or devices, the primary device goes back to its original desktop mode, but only the taskbar is redrawn and the DirectDraw primary surface is still present. You cannot draw to this surface without first releasing the DirectDraw object and then re-creating it.


Focus and Device Windows

Each DirectDraw application that uses one or more monitors in full-screen exclusive mode must have a single focus window, which is the window that receives keyboard input.

Each device that is to hold a full-screen DirectDraw surface must be represented by a DirectDraw object and a device window. The device window is the one that is sized to fit the window and is put on top of all other windows.

For single-monitor applications, there is no distinction between the device and focus window. They are one and the same.For multiple-monitor applications, however, you need to set a device window for each monitor, and you have to let each DirectDraw object know about the application's focus window. The focus window can also serve as the device window for one of the monitors. Other device windows should be children of the focus window so that the application does not minimize when the user clicks on one of them.

See also:

  • Setting the Focus Window
  • Setting Device Windows


Setting the Focus Window

To set the focus window, you call the IDirectDraw4::SetCooperativeLevel method for each of the DirectDraw objects. You pass in a window handle (normally the application window handle) and set the DDSCL_SETFOCUSWINDOW flag, as in the following example:

/* It is presumed that lpDD is a valid IDirectDraw interface pointer,
   and that hWnd is a valid window handle. */

HRESULT ddrval = lpDD->SetCooperativeLevel( hWnd,
        DDSCL_SETFOCUSWINDOW );

The focus window must be the same for all devices.


Setting Device Windows

There are two ways to set a device window:

  • Create a window yourself and pass its handle to the IDirectDraw4::SetCooperativeLevel method of the DirectDraw object representing the monitor, setting the DDSCL_SETDEVICEWINDOW, DDSCL_FULLSCREEN, and DDSCL_EXCLUSIVE flags. This creates a full-screen window and sets it as the device window for the monitor. Your application will receive mouse messages for the window, and you are responsible for destroying the window at the appropriate time. The window you pass to SetCooperativeLevel should be either the focus window (possible only if it is on the same device) or a child of the focus window.
  • Let DirectDraw create the window. You pass the focus window handle to SetCooperativeLevel and set the DDSCL_CREATEDEVICEWINDOW, DDSCL_FULLSCREEN, and DDSCL_EXCLUSIVE flags. DirectDraw creates a default device window that is a child of the focus window. It manages this window and will destroy it at the appropriate time. Your application will not receive any mouse messages for the window.

The following example sets an existing device window for the DirectDraw object represented by lpDD.

/* It is presumed that lpDD is a valid IDirectDraw interface pointer,
   and that hWnd is the handle to an appropriate device window. */

HRESULT hr = lpDD->SetCooperativeLevel( hWnd,
        DDSCL_SETDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN );

The following example sets a default device window created by DirectDraw. In this case, hWnd is the handle to the existing focus window.

HRESULT hr = lpDD->SetCooperativeLevel( hWnd,
        DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN );

Although a focus window can be a device window, you cannot set a window as both the focus window and a device window with a single call to SetCooperativeLevel. You must first set it as the focus window and then set it as a device window. However, it is possible to set a focus window and a default device window on the same device with a single call to SetCooperativeLevel. The following example shows how this can be done:

HRESULT hr = lpDD->SetCooperativeLevel(
        hwndFocus,
        DDSCL_SETFOCUSWINDOW | DDSCL_FULLSCREEN |
        DDSCL_EXCLUSIVE | DDSCL_CREATEDEVICEWINDOW);

In this example, an existing window (probably the application window) is set as the focus window, and DirectDraw creates a default device window.


Devices and Acceleration in MultiMon Systems

Full-screen exclusive mode DirectDraw objects will take advantage of hardware acceleration regardless of whether they are running on the primary device or on a secondary device. However, they cannot use built-in support for spanning graphics operations across display devices. It is the application's responsibility to perform operations on the appropriate device.

When the normal cooperative level is set, DirectDraw uses hardware acceleration only when the window is wholly within the display area of the primary device. When a window straddles two or more monitors, all blits are done in emulation and performance can be significantly slower. This is necessarily the case, because hardware buffers cannot blit to a display surface controlled by another piece of hardware.

As long as you create the DirectDraw object for the null device—that is, pass NULL to DirectDrawCreate as the lpGUID parameter—DirectDraw will blit to the entire window regardless of where it is located. However, if the device is created by its actual GUID, this is not the case, and blit operations that cross an edge of the primary surface will be clipped (if you are using a clipper) or will fail, returning DDERR_INVALIDRECT.

Note When you are blitting to a window in a MultiMon application, negative coordinates are valid when the logical location of the secondary monitor is to the left of the primary monitor.

To get the best performance in a windowed MultiMon application, you need to create a DirectDraw object for each device, maintain off-screen surfaces in parallel on each device, keep track of which part of the window resides on each device, and perform separate blits to each device.


Debugging Full-Screen DirectDraw Applications with MultiMon

It is possible to use a multimonitor system rather than remote debugging in order to step through code while debugging a full-screen DirectDraw application.

You should use the primary monitor for your development environment and the secondary monitor for the DirectDraw output. Also, you need to change a registry setting through the DirectX property sheet in Control Panel. On the DirectDraw page, click Advanced Settings and select the Enable Multi-Monitor Debugging checkbox. This setting will prevent DirectDraw from minimizing your application when it loses focus.

Under Windows 98, you cannot step through code when a surface is locked. For more information, see Accessing Surface Memory Directly.


Advanced DirectDraw Topics

This section supplements the DirectDraw overview, providing information about advanced DirectDraw issues. The following topics are discussed:

  • Mode 13 Support
  • Taking Advantage of DMA Support
  • Using DirectDraw Palettes in Windowed Mode
  • Video Ports
  • Getting the Flip and Blit Status
  • Determining the Capabilities of the Display Hardware
  • Storing Bitmaps in Display Memory
  • Triple Buffering
  • DirectDraw Applications and Window Styles
  • Matching True RGB Colors to the Frame Buffer's Color Space
  • Displaying a Window in Full-Screen Mode


Mode 13 Support

This section contains information about DirectDraw Mode 13 graphics mode support. The following topics are discussed:

  • About Mode 13
  • Setting Mode 13
  • Mode 13 and Surface Capabilities
  • Using Mode 13


About Mode 13

DirectDraw supports access to the linear unflippable 320x200 8 bits per pixel palettized mode known widely by the name Mode 13, its hexadecimal BIOS mode number. DirectDraw treats this mode like a Mode X mode, but with some important differences imposed by the physical nature of Mode 13.


Setting Mode 13

Mode 13 has similar enumeration and mode-setting behavior as Mode X. DirectDraw will only enumerate Mode 13 if the DDSCL_ALLOWMODEX flag was passed to the IDirectDraw4::SetCooperativeLevel method.

You enumerate the Mode 13 display mode like all other modes, but you make a surface capabilities check before calling IDirectDraw4::EnumDisplayModes. To do this, call IDirectDraw4::GetCaps and check for the DDSCAPS_STANDARDVGAMODE flag in the DDSCAPS2 structure after the method returns. If this flag is not present, then Mode 13 is not supported, and attempts to enumerate with the DDEDM_STANDARDVGAMODES flag will fail, returning DDERR_INVALIDPARAMS.

The EnumDisplayModes method now supports a new enumeration flag, DDEDM_STANDARDVGAMODES, which causes DirectDraw to enumerate Mode 13 in addition to the 320x200x8 Mode X mode. There is also a new IDirectDraw4::SetDisplayMode flag, DDSDM_STANDARDVGAMODE, which you must pass in order to distinguish Mode 13 from 320x200x8 Mode X.

Note that some video cards offer linear accelerated 320x200x8 modes. On such cards DirectDraw will not enumerate Mode 13, enumerating the linear mode instead. In this case, if you attempt to set Mode 13 by passing the DDSDM_STANDARDVGAMODE flag to SetDisplayMode, the method will succeed, but the linear mode will be used. This is analogous to the way that linear low resolution modes override Mode X modes.


Mode 13 and Surface Capabilities

When DirectDraw calls an application's EnumModesCallback callback function, the ddsCaps member of the associated DDSURFACEDESC or DDSURFACEDESC2 structure contains flags that reflect the mode being enumerated. You can expect DDSCAPS_MODEX for a Mode X mode or DDSCAPS_STANDARDVGAMODE for Mode 13. These flags are mutually exclusive. If neither of these bits is set, then the mode is a linear accelerated mode. This behavior also applies to the flags retrieved by the IDirectDraw4::GetDisplayMode method.


Using Mode 13

Because Mode 13 is a linear mode, unlike the Mode X modes, DirectDraw can give an application direct access to the frame buffer.You can call the IDirectDrawSurface4::Lock, IDirectDrawSurface4::Blt, and IDirectDrawSurface4::BltFast methods to gain direct access to the primary surface.

When using Mode 13, DirectDraw supports an emulated IDirectDrawSurface4::Flip that is implemented as a straight copy of the contents of a back buffer to the primary surface. You can emulate this yourself by copying all or part of the back-buffer's contents to the primary surface using Blt or BltFast.

There is one warning concerning Lock and Mode 13. Although DirectDraw allows direct linear access to the Mode 13 VGA frame buffer, do not assume that the buffer is always located at address 0xA0000, since DirectDraw can return an aliased virtual-memory pointer to the frame buffer which will not be 0xA0000. Similarly, do not assume that the pitch of a Mode 13 surface is 320, because display cards that support an accelerated 320x200x8 mode will very likely use a different pitch.


Taking Advantage of DMA Support

This section contains information about how you can take advantage of device support for Direct Memory Access (DMA) to increase performance in completing certain tasks. The following topics are discussed:

  • About DMA Device Support
  • Testing for DMA Support
  • Typical Scenarios for DMA
  • Using DMA


About DMA Device Support

Some display devices can perform blit operations (or other operations) on system memory surfaces. These operations are commonly referred to as Direct Memory Access (DMA) operations. You can exploit DMA support to accelerate certain combinations of operations. For example, on such a device, you could perform a blit from system memory to video memory while using the processor to prepare the next frame. In order to use such facilities, you must assume certain responsibilities. This section details these tasks.


Testing for DMA Support

Before using DMA operations, you must test the device for DMA support and, if it does support DMA, how much support it provides. Begin by retrieving the driver capabilities by calling the IDirectDraw4::GetCaps method, then look for the DDCAPS_CANBLTSYSMEM flag in the dwCaps member of the associated DDCAPS structure. If the flag is set, the device supports DMA.

If you know that DMA is generally supported, you also need to find out how well the driver supports it. You do so by looking at some other structure members that provide information about system-to-video, video-to-system, and system-to-system blit operations. These capabilities are provided in 12 DDCAPS structure members that are named according to blit and capability type. The following table shows these new members.

System-to-video | Video-to-system | System-to-system
dwSVBCaps | dwVSBCaps | dwSSBCaps
dwSVBCKeyCaps | dwVSBCKeyCaps | dwSSBCKeyCaps
dwSVBFXCaps | dwVSBFXCaps | dwSSBFXCaps
dwSVBRops | dwVSBRops | dwSSBRops

For example, the system-to-video blit capability flags are provided in the dwSVBCaps, dwSVBCKeyCaps, dwSVBFXCaps and dwSVBRops members. Similarly, video-to-system blit capabilities are in the members whose names begin with "dwVSB," and system-to system capabilities are in the "dwSSB" members. Examine the flags present in these members to determine the level of hardware support for that blit category.

The flags in these members are parallel with the blit-related flags included in the dwCaps, dwCKeyCaps, and dwFXCaps members, with respect to that member's blit type. For example, the dwSVBCaps member contains general blit capabilities as specified by the same flags you might find in the dwCaps member. Likewise, the raster operation values in the dwSVBRops, dwVSBRops, and dwSSBRops members provide information about the raster operations supported for a given type of blit operation.

One of the key features to look for in these members is support for asynchronous DMA blit operations. If the driver supports asynchronous DMA blits between surfaces, the DDCAPS_BLTQUEUE flag will be set in the dwSVBCaps, dwVSBCaps, or dwSSBCaps member. (Generally, you'll see the best support for system-memory-to-video-memory surfaces.) If the flag isn't present, the driver isn't reporting support for asynchronous DMA blit operations.


Typical Scenarios for DMA

System memory to video memory transfers that use the SRCCOPY raster operation are the most common type of hardware-supported blit operation. (The SRCCOPY raster operation, which is documented in the Platform SDK, causes the data within the source rectangle to be copied directly to the destination rectangle.) The most typical use for such an operation is to move textures from a large collection of system memory surfaces to a surface in video memory in preparation for subsequent operations. System-to-video DMA transfers are about as fast as processor-controlled transfers (for example, HEL blits), but are of great utility since they can operate in parallel with the host processor.


Using DMA

Hardware transfers use physical memory addresses, not the virtual addresses which are home to applications. Some device drivers require that you provide the surface's physical memory address. This mechanism is implemented by the IDirectDrawSurface4::PageLock method. If the device driver does not require page locking, the DDCAPS2_NOPAGELOCKREQUIRED flag will be set when you retrieve the hardware capabilities by calling the IDirectDraw4::GetCaps method.

Page locking a surface prevents the system from committing a surface's physical memory to other uses, and guarantees that the surface's physical address will remain constant until a corresponding IDirectDrawSurface4::PageUnlock call is made. If the device driver requires page locking, DirectDraw will allow asynchronous DMA operations only on system memory surfaces that the application has page locked. If you do not call IDirectDrawSurface4::PageLock in such a situation, DirectDraw will perform the transfers by using software emulation. Note that locking a large amount of system memory will make Windows run poorly. Therefore, it is highly recommended that only full-screen exclusive mode applications use IDirectDrawSurface4::PageLock for large amounts of system memory, and that such applications take care to unlock these surfaces when the application is minimized. Of course, when the application is restored, you should page lock the system memory surface again.

Responsibility for managing page locking is entirely in the hands of the application developer. DirectDraw will never page lock or page unlock a surface. Additionally, it is up to you to determine how much memory you can safely page lock without adversely affecting system performance.


Using DirectDraw Palettes in Windowed Mode

IDirectDrawPalette interface methods write directly to the hardware when the display is in exclusive (full-screen) mode. However, when the display is in nonexclusive (windowed) mode, the IDirectDrawPalette interface methods call the GDIs palette handling functions to work cooperatively with other windowed applications.

The discussion in the following topics assumes that the desktop is in an 8-bit palettized mode and that you have created a primary surface and a typical window.

  • Types of Palette Entries in Windowed Mode
  • Creating a Palette in Windowed Mode
  • Setting Palette Entries in Windowed Mode


Types of Palette Entries in Windowed Mode

Unlike full-screen exclusive mode applications, windowed applications must share the desktop palette with other applications. This imposes several restrictions on which palette entries you can safely modify and how you can modify them. The PALETTEENTRY structure you use when working with DirectDrawPalette objects and GDI contains a peFlags member to carry information that describes how the system should interpret the PALETTEENTRY structure.

The peFlags member describes three types of palette entries, discussed in this topic:

  • Windows static entries
  • Animated entries
  • Nonanimated entries

Windows static entries

In normal mode, Windows reserves palette entries 0 through 9 and 246 through 255 for system colors that it uses to display menu bars, menu text, window borders, and so on. In order to maintain a consistent look for your application and avoid damaging the appearance of other applications, you need to protect these entries in the palette you set to the primary surface. Often, developers retrieve the system palette entries by calling the GetSystemPaletteEntries Win32® function, then explicitly set the identical entries in a custom palette to match before assigning it to the primary surface. Duplicating the system palette entries in a custom palette will work initially, but it becomes invalid if the user changes the desktop color scheme.

To avoid having your palette look bad when the user changes color schemes, you can protect the appropriate entries by providing a reference into the system palette instead specifying a color value. This way, no matter what color the system is using for a given entry, your palette will always match and you won't need to do any updating. The PC_EXPLICIT flag, used in the peFlags member, makes it possible for you to directly refer to a system palette entry. When you use this flag, the system no longer assumes that the other structure members include color information. Rather, when you use PC_EXPLICIT, you set the value in the peRed member to the desired system palette index and set the other colors to zero.

For instance, if you want to ensure that the proper entries in your palette always match the system's color scheme, you could use the following code:

// Set the first and last 10 entries to match the system palette.
PALETTEENTRY pe[256];
ZeroMemory(pe, sizeof(pe));
for(int i=0;i<10;i++){
    pe[i].peFlags  = pe[i+246].peFlags = PC_EXPLICIT;
    pe[i].peRed = i;
    pe[i+246].peRed = i+246;
}

You can force Windows to use only the first and last palette entry (0 and 255) by calling the SetSystemPaletteUse Win32 function. In this case, you should set only entries 0 and 255 of your PALETTEENTRY structure to PC_EXPLICIT.

Animated entries

You specify palette entries that you will be animating by using the PC_RESERVED flag in the corresponding PALETTEENTRY structure. Windows will not allow any other application to map its logical palette entry to that physical entry, thereby preventing other applications from cycling their colors when your application animates the palette.

Nonanimated entries

You specify normal, nonanimated palette entries by using the PC_NOCOLLAPSE flag in the corresponding PALETTEENTRY structure. The PC_NOCOLLAPSE flag informs Windows not to substitute some other already-allocated physical palette entry for that entry.


Creating a Palette in Windowed Mode

The following example illustrates how to create a DirectDraw palette in nonexclusive (windowed) mode. In order for your palette to work correctly, it is vital that you set up every one of the 256 entries in the PALETTEENTRY structure that you submit to the IDirectDraw4::CreatePalette method.

LPDIRECTDRAW4        lpDD; // Assumed to be initialized previously
PALETTEENTRY         pPaletteEntry[256];
int                  index;
HRESULT              ddrval;
LPDIRECTDRAWPALETTE2 lpDDPal;

// First set up the Windows static entries.
for (index = 0; index < 10 ; index++)
{
    // The first 10 static entries:
    pPaletteEntry[index].peFlags = PC_EXPLICIT;
    pPaletteEntry[index].peRed = index;
    pPaletteEntry[index].peGreen = 0;
    pPaletteEntry[index].peBlue = 0;

    // The last 10 static entries:
    pPaletteEntry[index+246].peFlags = PC_EXPLICIT;
    pPaletteEntry[index+246].peRed = index+246;
    pPaletteEntry[index+246].peGreen = 0;
    pPaletteEntry[index+246].peBlue = 0;
}

// Now set up private entries. In this example, the first 16
// available entries are animated.
for (index = 10; index < 26; index ++)
{
    pPaletteEntry[index].peFlags = PC_NOCOLLAPSE|PC_RESERVED;
    pPaletteEntry[index].peRed = 255;
    pPaletteEntry[index].peGreen = 64;
    pPaletteEntry[index].peBlue = 32;
}

// Now set up the rest, the nonanimated entries.
for (; index < 246; index ++) // Index is set up by previous for loop
{
    pPaletteEntry[index].peFlags = PC_NOCOLLAPSE;
    pPaletteEntry[index].peRed = 25;
    pPaletteEntry[index].peGreen = 6;
    pPaletteEntry[index].peBlue = 63;
}

// All 256 entries are filled. Create the palette.
ddrval = lpDD->CreatePalette(DDPCAPS_8BIT, pPaletteEntry,
    &lpDDPal,NULL);


Setting Palette Entries in Windowed Mode

The rules that apply to the PALETTEENTRY structure used with the IDirectDraw4::CreatePalette method also apply to the IDirectDrawPalette::SetEntries method. Typically, you maintain your own array of PALETTEENTRY structures, so you do not need to rebuild it. When necessary, you can modify the array, and then call IDirectDrawPalette::SetEntries when it is time to update the palette.

In most circumstances, you should not attempt to set any of the Windows static entries when in nonexclusive (windowed) mode or you will get unpredictable results. The only exception is when you reset the 256 entries.

For palette animation, you typically change only a small subset of entries in your PALETTEENTRY array. You submit only those entries to IDirectDrawPalette::SetEntries. If you are resetting such a small subset, you must reset only those entries marked with the PC_NOCOLLAPSE and PC_RESERVED flags. Attempting to animate other entries can have unpredictable results.

The following example illustrates palette animation in nonexclusive mode:

LPDIRECTDRAW        lpDD;        // Already initialized
PALETTEENTRY pPaletteEntry[256]; // Already initialized
LPDIRECTDRAWPALETTE lpDDPal;     // Already initialized
int                 index;
HRESULT             ddrval;
PALETTEENTRY        temp;

// Animate some entries. Cycle the first 16 available entries.
// They were already animated.
temp = pPaletteEntry[10];
for (index = 10; index < 25; index ++)
{
    pPaletteEntry[index] = pPaletteEntry[index+1];
}
pPaletteEntry[25] = temp;

// Set the values. Do not pass a pointer to the entire palette entry
// structure, but only to the changed entries.
ddrval = lpDDPal->SetEntries(
    0,                      // Flags must be zero
    10,                     // First entry
    16,                     // Number of entries
    & (pPaletteEntry[10])); // Where to get the data


Video-Ports

DirectDraw video-port extensions are a low-level programming interface, not intended for mainstream multimedia programmers. The target customer is the video-streaming software industry, which creates products like DirectShow™. Developers who want to include video playback in their software can make use of video-port extensions. However, for most software, a high-level programming interface like the one provided by DirectShow is recommended for greater ease of use.

This section contains information about DirectDrawVideoPort objects. The following topics are discussed:

  • What Are Video Ports?
  • Video-Port Technology Overview
  • About DirectDraw Video-Port Extensions
  • Video Frames and Fields
  • HREF, VREF, and Connections
  • Vertical Blanking Interval Data
  • Auto-Flipping
  • Solutions to Common Video Artifacts
  • Solving Problems Caused by Half-Lines
  • Exploiting Hardware Features


What Are Video Ports?

A DirectDrawVideoPort object represents the video-port hardware found on some display adapters. Generally, a video-port object controls how the video-port hardware applies a video signal it receives from a video decoder directly to the frame buffer.

More than one channel of video can be controlled by creating as many DirectDrawVideoPort objects as is required. Because each channel can be separately enumerated and configured, the video hardware for each channel does not need to be identical.

For more information, see Video-Port Technology Overview.


Video-Port Technology Overview

A video port is hardware on a display device that enables direct access to a surface within the frame buffer, bypassing the CPU and PCI bus. Direct frame buffer access makes it possible to efficiently play live or recorded video without creating noticeable load on the CPU. Once in a surface, an image can be displayed on the screen as an overlay, used as a Direct3D texture, or accessed by the CPU for capture or other processing. The following paragraphs provide general information about the components that make up the technology and how they work.

Data Flow

In a machine equipped with a video port, data in a video stream can flow directly from a video source through a video decoder and the video port to the frame buffer. These components often exist together on a display adapter, but can be on separate hardware components that are physically connected to one another. An example of this data flow is provided in the following illustration.

Video source

In the scope of video-port technology, a video source is strictly a hardware video input device, such as a Zoom Video port, MPEG codec, or other hardware source. These sources broadcast signals in a variety of formats, including NTSC, PAL, and SECAM through a physical connection to a video decoder.

Video Decoder

A video decoder is also a hardware component. The video decoder's job is to decipher the information provided by the video source and send it to the video port in an agreed upon connection format. The decoder possesses a physical connection to the video port, and exposes its services through a stream class minidriver. The decoder is responsible for sending video data and clock and sync information to the video port.

Video port

Like the other components in the data flow path, the video port is a piece of hardware. The video port exists on the display adapter's VGA chip and has direct access to the frame buffer. It receives information sent from the decoder, processes it, and places it in the frame buffer to be displayed. During processing, the video port can manipulate image data to provide scaling, shrinking, color control, or cropping services.

Frame Buffer

The frame buffer accepts video data as provided by the video port. Once received, applications can programmatically manipulate the image data, blit it to other locations, or show it on the display using an overlay (the most common use).


About DirectDraw Video-Port Extensions

DirectDraw has been extended to include the DirectDrawVideoPort object, which takes advantage of video-port technology and provides its services through the IDDVideoPortContainer and IDirectDrawVideoPort interfaces.

DirectDrawVideoPort objects do not control the video decoder, because it provides services of its own, nor does DirectDraw control the video source; it is beyond the scope of the video port. Rather, a DirectDrawVideoPort object represents the video port itself. It monitors the incoming signal and passes image data to the frame buffer, using parameters set though its interface methods to modify the image, perform flipping, or carry out other services.

The IDDVideoPortContainer interface, which you can retrieve by calling the IDirectDraw4::QueryInterface method, provides methods to query the hardware for its capabilities and create video-port objects. You create a video-port object by calling the IDDVideoPortContainer::CreateVideoPort method. Video-port objects expose their functionality through the IDirectDrawVideoPort interface, enabling you to manipulate the video-port hardware itself. Using these interfaces, you can examine the video-port's capabilities, assign an overlay surface to receive image data, start and stop video playback, and set hardware parameters to manipulate image data for cropping, color control, scaling, or shrinking effects.

DirectDraw video-port extensions provide for multiple video ports on the same machine by allowing you to create multiple DirectDrawVideoPort objects. There is no requirement that multiple video ports on a machine be identical—each port is separately enumerated and configured separately, regardless of any hardware differences that might exist.

In keeping with the general philosophy of DirectX, this technology gives programmers low-level access to hardware features while insulating them from specific hardware implementation details. It is not a high-level API.


Video Frames and Fields

Video can be interlaced or non-interlaced. When a video signal is interlaced, each video frame is made of two fields of image data. Each field is a collection of every other scan line in an image, starting with the first or second scan line. The first field, referred to as the odd field (or field 1), contains the data for the first scan line and skips every other scan line to the end of the image. Similarly, the even field (or field 2), carries every other scan line starting with the second. The "even-ness" or "odd-ness" of a field is referred to as its field polarity.

When video is not interlaced, each field contains all of a frame's scan lines. Typically, video signals are sent at a rate of 30 frames per second; in the case of interleaved video, this means the rate is 60 fields per second.

The fields that make up a frame do not always reflect the same moment in time. For example, if the frames are separated by 1/30 of a second then the two fields of a frame may be separated by 1/60 of a second. Because a television displays each field individually, no two fields are simultaneously visible, and the difference between fields adds to the illusion of movement.


HREF, VREF, and Connections

When a monitor or other display device is displaying an image, it typically scans down the screen, creating an image from left to right, top to bottom. (Sometimes, the device makes two passes down the screen to create a single image; this type of display is called an interlaced display.) The video stream contains signals that instruct the display device when a new line or new screen is to be drawn.

The terms HREF and VREF, also known as hsync and vsync, are the signals within the video stream that tell a display device what to do and when to do it. The HREF signals that a new line is to be drawn and the VREF signals a new screen.

For instance, imagine you're working with a video signal intended for the world's smallest monitor. The monitor only has 4 scan lines. (This is not at all realistic, of course, but it's simple.) On an oscilloscope, the HREF and VREF signals would look somewhat like the following illustration.

In the preceding illustration, both HREF and VREF signals are "active high," meaning that they are considered active when in a heightened state (when the waves go up). There is no standard for these signals. In some cases, places where the waves go down ("low" states) might signal an active HREF or VREF, or sometimes one will be active high and the other active low. Although the preceding illustration is only an imaginary example, note that there are lots of HREF signals for each VREF. This is because for each new screen, there are several scan lines. Of course, in a real video signal for a real broadcast, you would see hundreds of HREFs for a single VREF.

HREF signals, VREF signals, and video data are carried across physical data lines from the decoder to the video port. In many cases, a number of lines are reserved for video data, and others are dedicated to carrying HREF and VREF signals. However, there is no standard for how these data lines are used.

A connection is a protocol that a video port or decoder uses to define how it uses these data lines. Video ports and video decoders will support a variety of connections. DirectDraw video-port extensions use globally-unique identifiers (GUIDs) to identify each type of connection. You can query for the connections that the video port supports by calling the IDDVideoPortContainer::GetVideoPortConnectInfo method. You create a DirectDrawVideoPort object that supports a given connection by calling the IDDVideoPortContainer::CreateVideoPort method.

Keep in mind that the video decoder is outside the scope of DirectDraw video-port extensions, and exposes its supported connections through an interface of its own. By enumerating the connections that the video-port supports and comparing the results with the connections supported by the decoder, you can negotiate a common connection (or "language") that both components understand.


Vertical Blanking Interval Data

In broadcast video, a small period of time elapses between video frames, during which a display device refreshes its display for the next frame. This period of time is called the Vertical Blanking Interval (VBI). Instead of sitting idle during the VBI, broadcast video encodes data in the first twenty-one scan lines of a video frame and sends these lines during the VBI. This data is often used for closed captioning or time-stamping, but can be used for other purposes.

DirectDraw video-port extensions enable you to divert data contained with the VBI to a surface, bypass scaling of VBI data, and automatically flip between VBI surfaces in a flipping chain. Once data is in a surface, you can directly access the surface's memory as needed.

For more information, see Auto-Flipping.


Auto-Flipping

To avoid tearing images when refreshing the screen between frames, DirectDrawVideoPort objects can automatically flip their target overlay surfaces in response to VREF signals. To use this service, the target surface you set to the video-port object with the IDirectDrawVideoPort::SetTargetSurface method must be the first surface in a flipping chain of overlay surfaces. Then, to begin playing the video sequence, call the IDirectDrawVideoPort::StartVideo method, specifying the DDVP_AUTOFLIP flag in the dwVPFlags member of the associated DDVIDEOPORTINFO structure. The video-port object will flip to the next surface in the flipping chain for each VREF signal it receives. If the video port is interleaving fields, it will flip once for every two VREF signals it receives.

If you are using auto-flipping and want to direct VBI data to separate auto-flipped surfaces, you must have the same number of VBI surfaces as you do standard video surfaces.


Solutions to Common Video Artifacts

Several problems are inherent in displaying broadcast video on display devices other than televisions. This section briefly discusses some common problems, then describes how DirectDraw video-port extensions tries to solve them.

NTSC Interlaced Display and Interleaved Memory

An NTSC signal broadcasts video at an approximate rate of 30 frames, or 60 fields, per second. Like a frame, a field in an NTSC signal is independent of the other field in a frame and can contain different image data. For more information on this behavior, see Video Frames and Fields.

The problems caused by the independence of fields within a frame become apparent when two fields are interleaved for display. In video with a lot of movement, the two fields of a single frame will contain images that don't match each other, resulting in motion artifacts.

One way that developers have tried to work around this behavior is by discarding one of the fields. This solution causes a loss in image quality by roughly one-half, but provides acceptable results for some purposes. Another method frequently used is to display fields individually, stretching each vertically by a factor of two when it is displayed. This provides better image quality, but because fields are offset by one pixel in the y-direction, the result is an animation that "jitters" up and down as it plays.

DirectDraw video-port extensions can employ two, more advanced, techniques for improving image quality, known as "Bob" and "Weave." Both are supported by the DirectDraw overlay surfaces that are used with video-port extensions.

The first algorithm, Bob, is very similar to the method of displaying each field in a frame individually. However, for each field, the overlay's source rectangle is adjusted to accommodate for any jittering effects. Effectively, the source rectangle bounces up and down in time with the fields, negating the jittering on the screen. The following illustration depicts this process.

The Weave algorithm provides the best image quality for material that originates from film by exploiting a common technique used in the video industry for converting motion pictures to television. Unlike Bob, a video-port object does not Weave by itself; you must combine the default overlay behavior of displaying both fields simultaneously with kernel mode video transport (provided with Windows 2000 and Windows 98) to implement the algorithm.

Here is a synopsis of the algorithm, provided for completeness. Motion pictures capture video at a rate of 24 frames per second. When converting a motion picture for television, technicians use a technique called 3:2 pulldown to convert the frame rate to the 30 frames per second required for television broadcasts. This technique involves inserting a redundant field for every four true fields in the video stream to come up with the required number of fields.

When you weave, you are reversing this process. You detect when 3:2 pulldown is being used, removing any redundant fields to restore the original motion-picture frames. The fields that make up the restored frames can then be interleaved in memory without risk of motion artifacts. Occasionally, the pattern of redundant frames will change due to edits within the original film or reel breaks. You must monitor when these changes occur and update the behavior to adjust for the new pattern.

By default, an overlay surface displays both fields simultaneously. This works well if you're implementing the Weave algorithm, but prevents the video port from using the Bob algorithm. You can programmatically change how the overlay treats video data by calling the IDirectDrawSurface4::UpdateOverlay method. The flags you include in the dwFlags parameter determine the overlay's behavior: if you include the DDOVER_BOB flag, the video port will use the Bob algorithm; if you don't, it displays both fields. Note that by simply displaying both fields simultaneously, the resulting video will show motion artifacts.


Solving Problems Caused by Half-Lines

Some video decoders output a half line of meaningless data at the beginning of the even field. If this extra line is written to the frame buffer, the resulting image will appear garbled. In some cases, the video-port hardware is capable of sensing and discarding this data before writing it to the frame buffer.

You can determine if a video port is capable of discarding this data when retrieving connection information with the IDDVideoPortContainer::GetVideoPortConnectInfo method. If the video port cannot discard half-lines, the DDVPCONNECT_HALFLINE flag will be specified in the dwFlags member of the associated DDVIDEOPORTCONNECT structure for each supported connection.

If the video port is unable to discard half-lines, you have two options: you can discard one of the fields, or you can work around the hardware's limitations by making some adjustments in how you create the video-port object and display images with the target overlay surface

Here's how to work around the problem. When creating the video-port object by calling the IDDVideoPortContainer::CreateVideoPort method, include the DDVPCONNECT_INVERTPOLARITY flag in the dwFlags member of the associated DDVIDEOPORTCONNECT structure. This causes the video port to invert the polarity of the fields in the video stream, treating even fields like odd fields and vice versa. Once reversed, the half-line preceding even fields will be written to the frame buffer as the first scan line of each frame. To remove the unwanted data, adjust the source rectangle of the overlay surface used to display the image down one pixel by calling the IDirectDrawVideoPort::StartVideo method with the necessary coordinates. Note that this technique requires that you allocate one extra line in the surface containing the even field.


Exploiting Hardware Features

Video-port hardware often supports special features for adjusting color, shrinking or zooming images, handling VBI data, or skipping fields. The HAL provides information about these features by using flags in the DDVIDEOPORTCAPS structure. You retrieve the capabilities of a machine's video-port hardware by calling the IDDVideoPortContainer::EnumVideoPorts method.

To exploit these features for playback, you use the IDirectDrawVideoPort::StartVideo method, which uses a DDVIDEOPORTINFO structure to request that hardware features be used to modify image data before placing it in the frame buffer or for display. By setting values and flags in this structure, you can specify the source rectangle used with the overlay surface, indicate cropping regions, request hardware scaling, and set pixel formats.

DirectDrawVideoPort objects do not emulate video-port hardware services.


Getting the Flip and Blit Status

When the IDirectDrawSurface4::Flip method is called, the primary surface and back buffer are exchanged. However, the exchange may not occur immediately. For example, if a previous flip has not finished, or if it did not succeed, this method returns DDERR_WASSTILLDRAWING. In the samples included with the SDK, the IDirectDrawSurface4::Flip call continues to loop until it returns DD_OK. Also, a IDirectDrawSurface4::Flip call does not complete immediately. It schedules a flip for the next time a vertical blank occurs on the system.

An application that waits until the DDERR_WASSTILLDRAWING value is not returned is very inefficient. Instead, you could create a function in your application that calls the IDirectDrawSurface4::GetFlipStatus method on the back buffer to determine if the previous flip has finished.

If the previous flip has not finished and the call returns DDERR_WASSTILLDRAWING, your application can use the time to perform another task before it checks the status again. Otherwise, you can perform the next flip. The following example demonstrates this concept:

while(lpDDSBack->GetFlipStatus(DDGFS_ISFLIPDONE) ==
    DDERR_WASSTILLDRAWING);

    // Waiting for the previous flip to finish. The application can
    // perform another task here.

ddrval = lpDDSPrimary->Flip(NULL, 0);

You can use the IDirectDrawSurface4::GetBltStatus method in much the same way to determine whether a blit has finished. Because IDirectDrawSurface4::GetFlipStatus and IDirectDrawSurface4::GetBltStatus return immediately, you can use them periodically in your application with little loss in speed.


Determining the Capabilities of the Display Hardware

DirectDraw uses software emulation to perform the DirectDraw functions not supported by the user's hardware. To accelerate performance of your DirectDraw applications, you should determine the capabilities of the user's display hardware after you have created a DirectDraw object, then structure your program to take advantage of these capabilities when possible.

You can determine these capabilities by using the IDirectDraw4::GetCaps method. Not all hardware features are supported in emulation. If you want to use a feature only supported by some hardware, you must also be prepared to supply some alternative for systems with hardware that lacks that feature.


Storing Bitmaps in Display Memory

Blitting from display memory to display memory is usually much more efficient than blitting from system memory to display memory. As a result, you should store as many of the sprites your application uses as possible in display memory.

Most display adapter hardware contains enough extra memory to store more than the primary surface and the back buffer. Call the IDirectDraw4::GetAvailableVidMem method to determine the amount of total and available memory for storing bitmaps in the display adapter's memory. After the call, the lpdwTotal parameter contains the total amount of display memory, minus the primary surface and any private caches held by driver, and lpdwFree contains the amount of display memory currently free that can be allocated for a surface that matches the capabilities specified by the structure at lpDDSCaps2.


Triple Buffering

In some cases, that is, when the display adapter has enough memory, it may be possible to speed up the process of displaying your application by using triple buffering. Triple buffering uses one primary surface and two back buffers. The following example shows how to initialize a triple-buffering scheme:

// The lpDDSPrimary and lpDDSBack variables are globally
// declared, uninitialized LPDIRECTDRAWSURFACE4 variables.
//
// The lpDD variable is a pointer to an IDirectDraw4 interface

DDSURFACEDESC2 ddsd;
ZeroMemory (&ddsd, sizeof(ddsd));

// Create the primary surface with two back buffers.
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE |
    DDSCAPS_FLIP | DDSCAPS_COMPLEX;
ddsd.dwBackBufferCount = 2;
ddrval = lpDD->CreateSurface(&ddsd, &lpDDSPrimary, NULL);

// If we successfully created the flipping chain,
// retrieve pointers to the surfaces we need for
// flipping and blitting.
if(ddrval == DD_OK)
{
    // Get the surface directly attached to the primary (the back buffer).
    ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER;
    ddrval = lpDDSPrimary->GetAttachedSurface(&ddsd.ddsCaps,
        &lpDDSBack);
    if(ddrval != DD_OK) ;
        // Display an error message here.
}

You do not need to keep track of all surfaces in a triple buffered flipping chain. The only surfaces you must keep pointers to are the primary surface and the back-buffer surface. You need a pointer to the primary surface in order to flip the surfaces in the flipping chain, and you need a pointer to the back buffer for blitting. For more information, see Flipping Surfaces.

Triple buffering allows your application to continue blitting to the back buffer even if a flip has not completed and the back buffer's blit has already finished. Performing a flip is not a synchronous event; one flip can take longer than another. Therefore, if your application uses only one back buffer, it may spend some time idling while waiting for the IDirectDrawSurface4::Flip method to return with DD_OK.


DirectDraw Applications and Window Styles

If your application uses DirectDraw in windowed mode, you can create windows with any window style. However, full-screen exclusive mode applications cannot be created with the WS_EX_TOOLWINDOW style without risk of unpredictable behavior. The WS_EX_TOOLWINDOW style prevents a window from being the top most window, which is required for a DirectDraw full-screen, exclusive mode application.

Full-screen exclusive mode applications should use the WS_EX_TOPMOST extended window style and the WS_VISIBLE window style to display properly. These styles keep the application at the front of the window z-order and prevent GDI from drawing on the primary surface.

The following example shows one way to safely prepare a window to be used in a full-screen, exclusive mode application.

////////////////////////////////////////////////////////
// Register the window class, display the window, and init
// all DirectX and graphic objects.
////////////////////////////////////////////////////////
BOOL WINAPI InitApp(INT nWinMode)
{
    WNDCLASSEX wcex;

    wcex.cbSize           =    sizeof(WNDCLASSEX);
    wcex.hInstance        =    g_hinst;
    wcex.lpszClassName    =    g_szWinName;
    wcex.lpfnWndProc      =    WndProc;
    wcex.style            =    CS_VREDRAW|CS_HREDRAW|CS_DBLCLKS;
    wcex.hIcon            =    LoadIcon (NULL, IDI_APPLICATION);
    wcex.hIconSm          =    LoadIcon (NULL, IDI_WINLOGO);
    wcex.hCursor          =    LoadCursor (NULL, IDC_ARROW);
    wcex.lpszMenuName     =    MAKEINTRESOURCE(IDR_APPMENU);
    wcex.cbClsExtra       =    0 ;
    wcex.cbWndExtra       =    0 ;
    wcex.hbrBackground    =    GetStockObject (NULL_BRUSH);

    RegisterClassEx(&wcex);

    g_hwndMain = CreateWindowEx(
                        WS_EX_TOPMOST,
                        g_szWinName,
                        g_szWinCaption,
                        WS_VISIBLE|WS_POPUP,
                        0,0,CX_SCREEN,CY_SCREEN,
                        NULL,
                        NULL,
                        g_hinst,
                        NULL);

    if(!g_hwndMain)
        return(FALSE);

    SetFocus(g_hwndMain);
    ShowWindow(g_hwndMain, nWinMode);
    UpdateWindow(g_hwndMain);

    return TRUE;
}


Matching True RGB Colors to the Frame Buffer's Color Space

Applications often need to find out how a true RGB color (RGB 888) will be mapped into a frame buffer's color space when the display device is not in RGB 888 mode. For example, imagine you're working on an application that will run in 16- and 24-bit RGB display modes. You know that when the art was created, a color was reserved for use as a transparent blitting color key; for the sake of argument, it is a 24-bit color such as RGB(128,64,255). Because your application will also run in a 16-bit RGB mode, you need a way to find out how this 24-bit color key maps into the color space that the frame buffer uses when it's running in a 16-bit RGB mode.

Although DirectDraw does not perform color matching services for you, there are ways to calculate how your color key will be mapped in the frame buffer. These methods can be pretty complicated. For most purposes, you can use the GDI built-in color matching services, combined with the DirectDraw direct frame buffer access, to determine how a color value maps into a different color space. In fact, the Ddutil.cpp source file included in the DirectX examples of the Platform SDK includes a sample function called DDColorMatch that performs this task. The DDColorMatch sample function performs the following main tasks:

  1. Retrieves the color value of a pixel in a surface at 0,0.
  2. Calls the Win32 SetPixel function, using a COLORREF structure that describes your 24-bit RGB color.
  3. Uses DirectDraw to lock the surface, getting a pointer to the frame buffer memory.
  4. Retrieves the actual color value from the frame buffer (set by GDI in Step 2) and unlocks the surface
  5. Resets the pixel at 0,0 to its original color using SetPixel.

The process used by the DDColorMatch sample function is not fast; it isn't intended to be. However, it provides a reliable way to determine how a color will be mapped across different RGB color spaces. For more information, see the source code for DDColorMatch in the Ddutil.cpp source file.

Note Because the SetPixel GDI function only accepts a COLORREF structure on input, this technique only works for matching RGB 888 colors to the frame buffer's pixel format. If your application needs to match colors of another pixel format, you should translate them to RGB 888 before using this technique or query the primary surface for its pixel format and match colors manually.


Displaying a Window in Full-Screen Mode

In full-screen mode, DirectDraw has exclusive control over the display. As a result, dialog boxes and other windows created through GDI are not normally visible. However, by using special techniques you can incorporate a Windows dialog box, HTML Help, or any other kind of window in your application.

The FSWindow Sample illustrates how a dialog box can be displayed and updated in a full-screen application, and how mouse clicks and keystrokes work just as if the dialog box were being displayed by GDI.

In FSWindow, the dialog box is created and "shown" as an ordinary dialog window:

hWndDlg = CreateDialog(g_hInstance,
        MAKEINTRESOURCE(IDD_DIALOG_SAMPLE),
        hWnd, (DLGPROC) SampleDlgProc);
ShowWindow(hWndDlg, SW_SHOWNORMAL);

Of course, at this point the dialog box is shown only on the hidden GDI surface. It does not appear on the primary surface, which is controlled by DirectDraw.

If the hardware capabilities include DDCAPS2_CANRENDERWINDOWED (see DDCAPS), displaying and updating the dialog box is easy. The application simply calls the IDirectDraw4::FlipToGDISurface method, which makes the GDI surface the primary surface. From now on, all updates to the dialog box will be displayed automatically, because GDI is now rendering directly to the front buffer. The application continues rendering to the back buffer, and on each pass through the rendering loop the contents of the back buffer are blitted to the front buffer by DirectDraw. The dialog box is not overwritten because the front buffer is clipped to the application window, and the dialog box is obscuring part of that window.

The following code, from the FSWindow_Init function, creates the clipper, associates it with the application window, and brings the GDI surface to the front:

if (ddObject->CreateClipper(0, &ddClipper, NULL) == DD_OK)
    ddClipper->SetHWnd(0, hwndAppWindow);
ddObject->FlipToGDISurface();

Then, in the FSWindow_Update function, the following code blits the rendered contents of the back buffer to the clipping region:

ddFrontBuffer->SetClipper(ddClipper);
ddFrontBuffer->Blt(NULL, ddBackBuffer, NULL, DDBLT_WAIT, NULL);

Note that because the GDI surface is the primary surface, Windows continues displaying the mouse cursor. (This would not be the case, however, if the application were using DirectInput with the mouse device at the exclusive cooperative level.)

For hardware that does not have the DDCAPS2_CANRENDERWINDOWED capability, the process of displaying and updating a window in full-screen mode is somewhat more complicated. In this case, the application is responsible for obtaining the image of the window created by GDI and blitting it to the back buffer after the full-screen rendering has been done. The entire back buffer is then flipped to the front in the usual way.

The FSWindow sample provides two different methods for accessing the display memory of the window, depending on whether the content is static or dynamic. The method for static content is faster because it involves blitting from a memory device context rather than a screen device context. This method should be used for windows that do not change, such as informational dialog boxes. (Remember, though, that unless you manually update the bitmap in response to events, even basic animations such as a button press will not be visible to the user.)

If the content is static, FSWindow calls the CreateBMPFromWindow function when the window is initialized. This function creates a bitmap and blits the contents of the window into it. The bitmap handle is stored in the global variable hwndFSWindowBMP. Whenever the primary surface is about to be updated, this bitmap is blitted to the back buffer, as follows:

if (FSWindow_IsStatic)
{
    hdcMemory = CreateCompatibleDC(NULL);
    SelectObject(hdcMemory, hwndFSWindowBMP);
    BitBlt(hdcBackBuffer, x, y, cx, cy, hdcMemory, 0, 0, SRCCOPY);
    DeleteDC(hdcMemory);
}

If, on the other hand, the content of the window is dynamic, the following code is executed. It blits the image directly from the GDI surface (represented by the hdcScreen device context) to the back buffer.

BitBlt(hdcBackBuffer, x, y, cx, cy, hdcScreen, x, y, SRCCOPY);

The coordinates represent the position and dimensions of the window on the GDI surface, as retrieved through a call to GetWindowRect.

When the FSWindow application is running on hardware that does not have the DDCAPS2_CANRENDERWINDOWED capability, it does not use the GDI surface, so Windows cannot display the mouse cursor. The application takes over this task by obtaining information about the cursor and displaying it on the back buffer just before the flip.


DirectDraw Tutorials

This section contains a series of tutorials, each of which provides step-by-step instructions for implementing a simple DirectDraw application. These tutorials use many of the DirectDraw sample files that are provided with this SDK. These samples demonstrate how to set up DirectDraw, and how to use the DirectDraw methods to perform common tasks:

  • Tutorial 1: The Basics of DirectDraw
  • Tutorial 2: Loading Bitmaps on the Back Buffer
  • Tutorial 3: Blitting from an Off-Screen Surface
  • Tutorial 4: Color Keys and Bitmap Animation
  • Tutorial 5: Dynamically Modifying Palettes
  • Tutorial 6: Using Overlay Surfaces

Some samples in these tutorials use older versions IDirectDraw and IDirectDrawSurface interfaces. If you want to update these examples so they use the DirectX 5.0 interfaces query for the new versions of the interfaces before using them. In addition, you must change the appropriate parameters of any methods that have been updated for new versions of the interfaces.

Note The sample files in these tutorials are written in C++. If you are using a C compiler, you must make the appropriate changes to the files for them to successfully compile. At the very least, you need to add the vtable and this pointers to the interface methods.


Tutorial 1: The Basics of DirectDraw

To use DirectDraw, you first create an instance of the DirectDraw object, which represents the display adapter on the computer. You then use the interface methods to manipulate the object. In addition, you need to create one or more instances of a DirectDrawSurface object to be able to display your application on a graphics surface.

To demonstrate this, the DDEx1 sample included with this SDK performs the following steps:

  • Step 1: Creating a DirectDraw Object
  • Step 2: Determining the Application's Behavior
  • Step 3: Changing the Display Mode
  • Step 4: Creating Flipping Surfaces
  • Step 5: Rendering to the Surfaces
  • Step 6: Writing to the Surface
  • Step 7: Flipping the Surfaces
  • Step 8: Deallocating the DirectDraw Objects

Note To use GUIDs successfully in your applications, you must either define INITGUID prior to all other include and define statements, or you must link to the Dxguid.lib library. You should define INITGUID in only one of your source modules.


Step 1: Creating a DirectDraw Object

To create an instance of a DirectDraw object, your application should use the DirectDrawCreate function as shown in the doInit sample function of the DDEx1 program. DirectDrawCreate contains three parameters. The first parameter takes a globally unique identifier (GUID) that represents the display device. The GUID, in most cases, is set to NULL, which means DirectDraw uses the default display driver for the system. The second parameter contains the address of a pointer that identifies the location of the DirectDraw object if it is created. The third parameter is always set to NULL and is included for future expansion.

The following example shows how to create the DirectDraw object and how to determine if the creation was successful or not:

ddrval = DirectDrawCreate(NULL, &lpDD, NULL);
if(ddrval == DD_OK)
{
    // lpDD is a valid DirectDraw object.
}
else
{
    // The DirectDraw object could not be created.
}


Step 2: Determining the Application's Behavior

Before you can change the resolution of the display, you must at a minimum specify the DDSCL_EXCLUSIVE and DDSCL_FULLSCREEN flags in the dwFlags parameter of the IDirectDraw::SetCooperativeLevel method. This gives your application complete control over the display device, and no other application will be able to share it. In addition, the DDSCL_FULLSCREEN flag sets the application in exclusive (full-screen) mode. Your application covers the entire desktop, and only your application can write to the screen. The desktop is still available, however. (To see the desktop in an application running in exclusive mode, start DDEx1 and press ALT+ TAB.)

The following example demonstrates the use of the SetCooperativeLevel method:

HRESULT      ddrval;
LPDIRECTDRAW lpDD;     // Already created by DirectDrawCreate

ddrval = lpDD->SetCooperativeLevel(hwnd, DDSCL_EXCLUSIVE |
    DDSCL_FULLSCREEN);
if(ddrval == DD_OK)
{
    // Exclusive mode was successful.
}
else
{
    // Exclusive mode was not successful.
    // The application can still run, however.
}

If SetCooperativeLevel does not return DD_OK, you can still run your application. The application will not be in exclusive mode, however, and it might not be capable of the performance your application requires. In this case, you might want to display a message that allows the user to decide whether or not to continue.

If you are setting the full-screen, exclusive cooperative level, you must pass your application's window handle to SetCooperativeLevel to allow Windows to determine if your application terminates abnormally. For example, if a general protection (GP) fault occurs and GDI is flipped to the back buffer, the user will not be able to return to the Windows screen. To prevent this from occurring, DirectDraw provides a process running in the background that traps messages that are sent to that window. DirectDraw uses these messages to determine when the application terminates. This feature imposes some restrictions, however. You have to specify the window handle that is retrieving messages for your application—that is, if you create another window, you must ensure that you specify the window that is active. Otherwise, you might experience problems, including unpredictable behavior from GDI, or no response when you press ALT + TAB.


Step 3: Changing the Display Mode

After you have set the application's behavior, you can use the IDirectDraw::SetDisplayMode method to change the resolution of the display. The following example shows how to set the display mode to 640×480×8 bpp:

HRESULT      ddrval;
LPDIRECTDRAW lpDD;  // Already created

ddrval = lpDD->SetDisplayMode(640, 480, 8);
if(ddrval == DD_OK)
{
    // The display mode changed successfully.
}
else
{
    // The display mode cannot be changed.
    // The mode is either not supported or
    // another application has exclusive mode.
}

When you set the display mode, you should ensure that if the user's hardware cannot support higher resolutions, your application reverts to a standard mode that is supported by a majority of display adapters. For example, your application could be designed to run on all systems that support 640×480×8 as a standard backup resolution.

Note IDirectDraw::SetDisplayMode returns a DDERR_INVALIDMODE error value if the display adapter could not be set to the desired resolution. Therefore, you should use the IDirectDraw::EnumDisplayModes method to determine the capabilities of the user's display adapter before trying to set the display mode.


Step 4: Creating Flipping Surfaces

After you have set the display mode, you must create the surfaces on which to place your application. Because the DDEx1 example is using the IDirectDraw::SetCooperativeLevel method to set the mode to exclusive (full-screen) mode, you can create surfaces that flip between the surfaces. If you were using SetCooperativeLevel to set the mode to DDSCL_NORMAL, you could create only surfaces that blit between the surfaces. Creating flipping surfaces requires the following steps, also discussed in this topic:

  • Defining the surface requirements
  • Creating the surfaces


Defining the Surface Requirements

The first step in creating flipping surfaces is to define the surface requirements in a DDSURFACEDESC structure. The following example shows the structure definitions and flags needed to create a flipping surface.

// Create the primary surface with one back buffer.
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE |
    DDSCAPS_FLIP | DDSCAPS_COMPLEX;

ddsd.dwBackBufferCount = 1;

In this example, the dwSize member is set to the size of the DDSURFACEDESC structure. This is to prevent any DirectDraw method call you use from returning with an invalid member error. (The dwSize member was provided for future expansion of the DDSURFACEDESC structure.)

The dwFlags member determines which members in the DDSURFACEDESC structure will be filled with valid information. For the DDEx1 example, dwFlags is set to specify that you want to use the DDSCAPS structure (DDSD_CAPS) and that you want to create a back buffer (DDSD_BACKBUFFERCOUNT).

The dwCaps member in the example indicates the flags that will be used in the DDSCAPS structure. In this case, it specifies a primary surface (DDSCAPS_PRIMARYSURFACE), a flipping surface (DDSCAPS_FLIP), and a complex surface (DDSCAPS_COMPLEX).

Finally, the example specifies one back buffer. The back buffer is where the backgrounds and sprites will actually be written. The back buffer is then flipped to the primary surface. In the DDEx1 example, the number of back buffers is set to 1. You can, however, create as many back buffers as the amount of display memory allows. For more information on creating more than one back buffer, see Triple Buffering.

Surface memory can be either display memory or system memory. DirectDraw uses system memory if the application runs out of display memory (for example, if you specify more than one back buffer on a display adapter with only 1 MB of RAM). You can also specify whether to use only system memory or only display memory by setting the dwCaps member in the DDSCAPS structure to DDSCAPS_SYSTEMMEMORY or DDSCAPS_VIDEOMEMORY. (If you specify DDSCAPS_VIDEOMEMORY, but not enough memory is available to create the surface, IDirectDraw::CreateSurface returns with a DDERR_OUTOFVIDEOMEMORY error.)


Creating the Surfaces

After the DDSURFACEDESC structure is filled, you can use it and lpDD, the pointer to the DirectDraw object that was created by the DirectDrawCreate function, to call the IDirectDraw::CreateSurface method, as shown in the following example:

ddrval = lpDD->CreateSurface(&ddsd, &lpDDSPrimary, NULL);
if(ddrval == DD_OK)
{
    // lpDDSPrimary points to the new surface.
}
else
{
    // The surface was not created.
    return FALSE;
}

The lpDDSPrimary parameter will point to the primary surface returned by CreateSurface if the call succeeds.

After the pointer to the primary surface is available, you can use the IDirectDrawSurface3::GetAttachedSurface method to retrieve a pointer to the back buffer, as shown in the following example:

ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
ddrval = lpDDSPrimary->GetAttachedSurface(&ddcaps, &lpDDSBack);
if(ddrval == DD_OK)
{
    // lpDDSBack points to the back buffer.
}
else
{
    return FALSE;
}

By supplying the address of the surface's primary surface and by setting the capabilities value with the DDSCAPS_BACKBUFFER flag, the lpDDSBack parameter will point to the back buffer if the IDirectDrawSurface3::GetAttachedSurface call succeeds.


Step 5: Rendering to the Surfaces

After the primary surface and a back buffer have been created, the DDEx1 example renders some text on the primary surface and back buffer surface by using standard Windows GDI functions, as shown in the following example:

if (lpDDSPrimary->GetDC(&hdc) == DD_OK)
{
    SetBkColor(hdc, RGB(0, 0, 255));
    SetTextColor(hdc, RGB(255, 255, 0));
    TextOut(hdc, 0, 0, szFrontMsg, lstrlen(szFrontMsg));
    lpDDSPrimary->ReleaseDC(hdc);
}

if (lpDDSBack->GetDC(&hdc) == DD_OK)
{
    SetBkColor(hdc, RGB(0, 0, 255));
    SetTextColor(hdc, RGB(255, 255, 0));
    TextOut(hdc, 0, 0, szBackMsg, lstrlen(szBackMsg));
    lpDDSBack->ReleaseDC(hdc);
}

The example uses the IDirectDrawSurface3::GetDC method to retrieve the handle of the device context, and it internally locks the surface. If you are not going to use Windows functions that require a handle of a device context, you could use the IDirectDrawSurface3::Lock and IDirectDrawSurface3::Unlock methods to lock and unlock the back buffer.

Locking the surface memory (whether the whole surface or part of a surface) ensures that your application and the system blitter cannot obtain access to the surface memory at the same time. This prevents errors from occurring while your application is writing to surface memory. In addition, your application cannot page flip until the surface memory is unlocked.

After the surface is locked, the example uses standard Windows GDI functions: SetBkColor to set the background color, SetTextColor to select the color of the text to be placed on the background, and TextOut to print the text and background color on the surfaces.

After the text has been written to the buffer, the example uses the IDirectDrawSurface3::ReleaseDC method to unlock the surface and release the handle. Whenever your application finishes writing to the back buffer, you must call either IDirectDrawSurface3::ReleaseDC or IDirectDrawSurface3::Unlock, depending on your application. Your application cannot flip the surface until the surface is unlocked.

Typically, you write to a back buffer, which you then flip to the primary surface to be displayed. In the case of DDEx1, there is a significant delay before the first flip, so DDEx1 writes to the primary buffer in the initialization function to prevent a delay before displaying the surface. As you will see in a subsequent step of this tutorial, the DDEx1 example writes only to the back buffer during WM_TIMER. An initialization function or title page may be the only place where you might want to write to the primary surface.

Note After the surface is unlocked by using IDirectDrawSurface3::Unlock, the pointer to the surface memory is invalid. You must use IDirectDrawSurface3::Lock again to obtain a valid pointer to the surface memory.


Step 6: Writing to the Surface

The first half of the WM_TIMER message in DDEx1 is devoted to writing to the back buffer, as shown in the following example:

case WM_TIMER:
    // Flip surfaces.
    if(bActive)
    {
        if (lpDDSBack->GetDC(&hdc) == DD_OK)
        {
            SetBkColor(hdc, RGB(0, 0, 255));
            SetTextColor(hdc, RGB(255, 255, 0));
            if(phase)
            {
                TextOut(hdc, 0, 0, szFrontMsg, lstrlen(szFrontMsg));
                phase = 0;
            }
            else
            {
                TextOut(hdc, 0, 0, szBackMsg, lstrlen(szBackMsg));
                phase = 1;
            }
            lpDDSBack->ReleaseDC(hdc);
        }

The line of code that calls the IDirectDrawSurface3::GetDC method locks the back buffer in preparation for writing. The SetBkColor and SetTextColor functions set the colors of the background and text.

Next, the phase variable determines whether the primary buffer message or the back buffer message should be written. If phase equals 1, the primary surface message is written, and phase is set to 0. If phase equals 0, the back buffer message is written, and phase is set to 1. Note, however, that in both cases the messages are written to the back buffer.

After the message is written to the back buffer, the back buffer is unlocked by using the IDirectDrawSurface3::ReleaseDC method.


Step 7: Flipping the Surfaces

After the surface memory is unlocked, you can use the IDirectDrawSurface3::Flip method to flip the back buffer to the primary surface, as shown in the following example:

while(1)
{
    HRESULT ddrval;
    ddrval = lpDDSPrimary->Flip(NULL, 0);
    if(ddrval == DD_OK)
    {
        break;
    }
    if(ddrval == DDERR_SURFACELOST)
    {
        ddrval = lpDDSPrimary->Restore();
        if(ddrval != DD_OK)
        {
            break;
        }
    }
    if(ddrval != DDERR_WASSTILLDRAWING)
    {
        break;
    }
}

In the example, lpDDSPrimary parameter designates the primary surface and its associated back buffer. When IDirectDrawSurface3::Flip is called, the front and back surfaces are exchanged (only the pointers to the surfaces are changed; no data is actually moved). If the flip is successful and returns DD_OK, the application breaks from the while loop.

If the flip returns with a DDERR_SURFACELOST value, an attempt is made to restore the surface by using the IDirectDrawSurface3::Restore method. If the restore is successful, the application loops back to the IDirectDrawSurface3::Flip call and tries again. If the restore is unsuccessful, the application breaks from the while loop, and returns with an error.

Note When you call IDirectDrawSurface3::Flip, the flip does not complete immediately. Rather, a flip is scheduled for the next time a vertical blank occurs on the system. If, for example, the previous flip has not occurred, IDirectDrawSurface3::Flip returns DDERR_WASSTILLDRAWING. In the example, the IDirectDrawSurface3::Flip call continues to loop until it returns DD_OK.


Step 8: Deallocating the DirectDraw Objects

When you press the F12 key, the DDEx1 application processes the WM_DESTROY message before exiting the application. This message calls the finiObjects sample function, which contains all of the IUnknown::Release calls, as shown in the following example:

static void finiObjects(void)
{
    if(lpDD != NULL)
    {
        if(lpDDSPrimary != NULL)
        {
            lpDDSPrimary->Release();
            lpDDSPrimary = NULL;
        }
        lpDD->Release();
        lpDD = NULL;
    }
} // finiObjects

The application checks if the pointers to the DirectDraw object (lpDD) and the DirectDrawSurface object (lpDDSPrimary) are not equal to NULL. Then DDEx1 calls the IDirectDrawSurface3::Release method to decrease the reference count of the DirectDrawSurface object by 1. Because this brings the reference count to 0, the DirectDrawSurface object is deallocated. The DirectDrawSurface pointer is then destroyed by setting its value to NULL. Next, the application calls IDirectDraw::Release to decrease the reference count of the DirectDraw object to 0, deallocating the DirectDraw object. This pointer is then also destroyed by setting its value to NULL.


Tutorial 2: Loading Bitmaps on the Back Buffer

The sample discussed in this tutorial (DDEx2) expands on the DDEx1 sample that was discussed in Tutorial 1. DDEx2 includes functionality to load a bitmap file on the back buffer. This new functionality is demonstrated in the following steps:

  • Step 1: Creating the Palette
  • Step 2: Setting the Palette
  • Step 3: Loading a Bitmap on the Back Buffer
  • Step 4: Flipping the Surfaces

As in DDEx1, doInit is the initialization function for the DDEx2 application. Although the code for the DirectDraw initialization does not look quite the same in DDEx2 as it did in DDEx1, it is essentially the same, except for the following section:

lpDDPal = DDLoadPalette(lpDD, szBackground);

if (lpDDPal == NULL)
    goto error;

ddrval = lpDDSPrimary->SetPalette(lpDDPal);

if(ddrval != DD_OK)
    goto error;

// Load a bitmap into the back buffer.
ddrval = DDReLoadBitmap(lpDDSBack, szBackground);

if(ddrval != DD_OK)
    goto error;


Step 1: Creating the Palette

The DDEx2 sample first loads the palette into a structure by using the following code:

lpDDPal = DDLoadPalette(lpDD, szBackground);

if (lpDDPal == NULL)
    goto error;

The sample function DDLoadPalette is part of the common DirectDraw functions found in the Ddutil.cpp file located in the \Dxsdk\Sdk\Samples\Misc directory. Most of the DirectDraw sample files in this SDK use this file. Essentially, it contains the functions for loading bitmaps and palettes from either files or resources. To avoid having to repeat code in the example files, these functions were placed in a file that could be reused. Make sure you include Ddutil.cpp in the list of files to be compiled with the rest of the DDExn samples.

For DDEx2, the DDLoadPalette sample function creates a DirectDrawPalette object from the Back.bmp file. The DDLoadPalette sample function determines if a file or resource for creating a palette exists. If one does not, it creates a default palette. For DDEx2, it extracts the palette information from the bitmap file and stores it in a structure pointed to by ape.

DDEx2 then creates the DirectDrawPalette object, as shown in the following example:

pdd->CreatePalette(DDPCAPS_8BIT, ape, &ddpal, NULL);
return ddpal;

When the IDirectDraw2::CreatePalette method returns, the ddpal parameter points to the DirectDrawPalette object, which is then returned from the DDLoadPalette call.

The ape parameter is a pointer to a structure that can contain either 2, 4, 16, or 256 entries, organized linearly. The number of entries depends on the dwFlags parameter in the CreatePalette method. In this case, the dwFlags parameter is set to DDPCAPS_8BIT, which indicates that there are 256 entries in this structure. Each entry contains 4 bytes (a red channel, a green channel, a blue channel, and a flags byte).


Step 2: Setting the Palette

After you create the palette, you pass the pointer to the DirectDrawPalette object (ddpal) to the primary surface by calling the IDirectDrawSurface3::SetPalette method, as shown in the following example:

ddrval = lpDDSPrimary->SetPalette(lpDDPal);

if(ddrval != DD_OK)
    // SetPalette failed.

After you have called IDirectDrawSurface3::SetPalette, the DirectDrawPalette object is associated with the DirectDrawSurface object. Any time you need to change the palette, you simply create a new palette and set the palette again. (Although this tutorial uses these steps, there are other ways of changing the palette, as will be shown in later examples.)


Step 3: Loading a Bitmap on the Back Buffer

After the DirectDrawPalette object is associated with the DirectDrawSurface object, DDEx2 loads the Back.bmp bitmap on the back buffer by using the following code:

// Load a bitmap into the back buffer.
ddrval = DDReLoadBitmap(lpDDSBack, szBackground);

if(ddrval != DD_OK)
    // Load failed.

DDReLoadBitmap is another sample function found in Ddutil.cpp. It loads a bitmap from a file or resource into an already existing DirectDraw surface. (You could also use DDLoadBitmap to create a surface and load the bitmap into that surface. For more information, see Tutorial 5: Dynamically Modifying Palettes.) For DDEx2, it loads the Back.bmp file pointed to by szBackground onto the back buffer pointed to by lpDDSBack. The DDReLoadBitmap function calls the DDCopyBitmap function to copy the file onto the back buffer and stretch it to the proper size.

The DDCopyBitmap function copies the bitmap into memory, and it uses the GetObject function to retrieve the size of the bitmap. It then uses the following code to retrieve the size of the back buffer onto which it will place the bitmap:

// Get the size of the surface.
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_HEIGHT | DDSD_WIDTH;
pdds->GetSurfaceDesc(&ddsd);

The ddsd value is a pointer to the DDSURFACEDESC structure. This structure stores the current description of the DirectDraw surface. In this case, the DDSURFACEDESC members describe the height and width of the surface, which are indicated by DDSD_HEIGHT and DDSD_WIDTH. The call to the IDirectDrawSurface3::GetSurfaceDesc method then loads the structure with the proper values. For DDEx2, the values will be 480 for the height and 640 for the width.

The DDCopyBitmap sample function locks the surface and copies the bitmap to the back buffer, stretching or compressing it as applicable by using the StretchBlt function, as shown in the following example:

if ((hr = pdds->GetDC(&hdc)) == DD_OK)
{
    StretchBlt(hdc, 0, 0, ddsd.dwWidth, ddsd.dwHeight, hdcImage, x, y,
        dx, dy, SRCCOPY);
    pdds->ReleaseDC(hdc);
}


Step 4: Flipping the Surfaces

Flipping surfaces in the DDEx2 sample is essentially the same process as that in the DDEx1 tutorial (see Tutorial 1: The Basics of DirectDraw) except that if the surface is lost (DDERR_SURFACELOST), the bitmap must be reloaded on the back buffer by using the DDReLoadBitmap function after the surface is restored.


Tutorial 3: Blitting from an Off-Screen Surface

The sample in Tutorial 2 (DDEx2) takes a bitmap and puts it in the back buffer, and then it flips between the back buffer and the primary buffer. This is not a very realistic approach to displaying bitmaps. The sample in this tutorial (DDEx3) expands on the capabilities of DDEx2 by including two off-screen buffers in which the two bitmaps—one for the even screen and one for the odd screen—are stored. It uses the IDirectDrawSurface3::BltFast method to copy the contents of an off-screen surface to the back buffer, and then it flips the buffers and copies the next off-screen surface to the back buffer.

The new functionality demonstrated in DDEx3 is shown in the following steps:

  • Step 1: Creating the Off-Screen Surfaces
  • Step 2: Loading the Bitmaps to the Off-Screen Surfaces
  • Step 3: Blitting the Off-Screen Surfaces to the Back Buffer


Step 1: Creating the Off-Screen Surfaces

The following code is added to the doInit sample function in DDEx3 to create the two off-screen buffers:

// Create an offscreen bitmap.
ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
ddsd.dwHeight = 480;
ddsd.dwWidth = 640;
ddrval = lpDD->CreateSurface(&ddsd, &lpDDSOne, NULL);
if(ddrval != DD_OK)
{
    return initFail(hwnd);
}

// Create another offscreen bitmap.
ddrval = lpDD->CreateSurface(&ddsd, &lpDDSTwo, NULL);
if(ddrval != DD_OK)
{
    return initFail(hwnd);
}

The dwFlags member specifies that the application will use the DDSCAPS structure, and it will set the height and width of the buffer. The surface will be an off-screen plain buffer, as indicated by the DDSCAPS_OFFSCREEN flag set in the DDSCAPS structure. The height and the width are set as 480 and 640, respectively, in the DDSURFACEDESC structure. The surface is then created by using the IDirectDraw::CreateSurface method.

Because both of the off-screen plain buffers are the same size, the only requirement for creating the second buffer is to call IDirectDraw::CreateSurface again with a different pointer name.

You can also specifically request that the off-screen buffer be placed in system memory or display memory by setting either the DDSCAPS_SYSTEMMEMORY or DDSCAPS_VIDEOMEMORY capability in the DDSCAPS structure. By saving the bitmaps in display memory, you can increase the speed of the transfers between the off-screen surfaces and the back buffer. This will become more important when using bitmap animation. However, if you specify DDSCAPS_VIDEOMEMORY for the off-screen buffer and not enough display memory is available to hold the entire bitmap, a DDERR_OUTOFVIDEOMEMORY error value will be returned when you attempt to create the surface.


Step 2: Loading the Bitmaps to the Off-Screen Surfaces

After the two off-screen surfaces are created, DDEx3 uses the InitSurfaces sample function to load the bitmaps from the Frntback.bmp file onto the surfaces. The InitSurfaces function uses the DDCopyBitmap sample function located in Ddutil.cpp to load both of the bitmaps, as shown in the following example:

// Load the bitmap resource.
hbm = (HBITMAP)LoadImage(GetModuleHandle(NULL), szBitmap,
    IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION);

if (hbm == NULL)
    return FALSE;

DDCopyBitmap(lpDDSOne, hbm, 0, 0,   640, 480);
DDCopyBitmap(lpDDSTwo, hbm, 0, 480, 640, 480);
DeleteObject(hbm);

return TRUE;

If you look at the Frntback.bmp file in Microsoft® Paint or another drawing application, you can see that the bitmap consists of two screens, one on top of the other. The DDCopyBitmap function breaks the bitmap in two at the point where the screens meet. In addition, it loads the first bitmap into the first off-screen surface (lpDDSOne) and the second bitmap into the second off-screen surface (lpDDSTwo).


Step 3: Blitting the Off-Screen Surfaces to the Back Buffer

The WM_TIMER message contains the code for writing to surfaces and flipping surfaces. In the case of DDEx3, it contains the following code to select the proper off-screen surface and to blit it to the back buffer:

rcRect.left = 0;
rcRect.top = 0;
rcRect.right = 640;
rcRect.bottom = 480;
if(phase)
{
    pdds = lpDDSTwo;
    phase = 0;
}
else
{
    pdds = lpDDSOne;
    phase = 1;
}
while(1)
{
    ddrval = lpDDSBack->BltFast(0, 0, pdds, &rcRect, FALSE);
    if(ddrval == DD_OK)
    {
        break;
    }
}

The phase variable determines which off-screen surface will be blitted to the back buffer. The IDirectDrawSurface3::BltFast method is then called to blit the selected off-screen surface onto the back buffer, starting at position (0, 0), the upper-left corner. The rcRect parameter points to the RECT structure that defines the upper-left and lower-right corners of the off-screen surface that will be blitted from. The last parameter is set to FALSE (or 0), indicating that no specific transfer flags are used.

Depending on the requirements of your application, you could use either the IDirectDrawSurface3::Blt method or the IDirectDrawSurface::BltFast method to blit from the off-screen buffer. If you are performing a blit from an off-screen plain buffer that is in display memory, you should use IDirectDrawSurface3::BltFast. Although you will not gain speed on systems that use hardware blitter on their display adapters, the blit will take about 10 percent less time on systems that use hardware emulation to perform the blit. Because of this, you should use IDirectDrawSurface3::BltFast for all display operations that blit from display memory to display memory. If you are blitting from system memory or require special hardware flags, however, you have to use IDirectDrawSurface3::Blt.

After the off-screen surface is loaded in the back buffer, the back buffer and the primary surface are flipped in much the same way as shown in the previous tutorials.


Tutorial 4: Color Keys and Bitmap Animation

The sample in Tutorial 3 (DDEx3) shows one simple method of placing bitmaps into an off-screen buffer before they are blitted to the back buffer. The sample in this tutorial (DDEx4) uses the techniques described in the previous tutorials to load a background and a series of sprites into an off-screen surface. Then it uses the IDirectDrawSurface3::BltFast method to copy portions of the off-screen surface to the back buffer, thereby generating a simple bitmap animation.

The bitmap file that DDEx4 uses, All.bmp, contains the background and 60 iterations of a rotating red donut with a black background. The DDEx4 sample contains new functions that set the color key for the rotating donut sprites. Then, the sample copies the appropriate sprite to the back buffer from the off-screen surface.

The new functionality demonstrated in DDEx4 is shown in the following steps:

  • Step 1: Setting the Color Key
  • Step 2: Creating a Simple Animation


Step 1: Setting the Color Key

In addition to the other functions found in the doInit sample function of some of the other DirectDraw samples, the DDEx4 sample contains the code to set the color key for the sprites. Color keys are used for setting a color value that will be used for transparency. When the system contains a hardware blitter, all the pixels of a rectangle are blitted except the value that was set as the color key, thereby creating nonrectangular sprites on a surface. The following code shows how to set the color key in DDEx4:

// Set the color key for this bitmap (black).
DDSetColorKey(lpDDSOne, RGB(0,0,0));

return TRUE;

You can select the color key by setting the RGB values for the color you want in the call to the DDSetColorKey sample function. The RGB value for black is (0, 0, 0). The DDSetColorKey function calls the DDColorMatch function. (Both functions are in Ddutil.cpp.) The DDColorMatch function stores the current color value of the pixel at location (0, 0) on the bitmap located in the lpDDSOne surface. Then it takes the RGB values you supplied and sets the pixel at location (0, 0) to that color. Finally, it masks the value of the color with the number of bits per pixel that are available. After that is done, the original color is put back in location (0, 0), and the call returns to DDSetColorKey with the actual color key value. After it is returned, the color key value is placed in the dwColorSpaceLowValue member of the DDCOLORKEY structure. It is also copied to the dwColorSpaceHighValue member. The call to IDirectDrawSurface3::SetColorKey then sets the color key.

You may have noticed the reference to CLR_INVALID in DDSetColorKey and DDColorMatch. If you pass CLR_INVALID as the color key in the DDSetColorKey call in DDEx4, the pixel in the upper-left corner (0, 0) of the bitmap will be used as the color key. As the DDEx4 bitmap is delivered, that does not mean much because the color of the pixel at (0, 0) is a shade of gray. If, however, you would like to see how to use the pixel at (0, 0) as the color key for the DDEx4 sample, open the All.bmp bitmap file in a drawing application and then change the single pixel at (0, 0) to black. Be sure to save the change (it's hard to see). Then change the DDEx4 line that calls DDSetColorKey to the following:

DDSetColorKey(lpDDSOne, CLR_INVALID);

Recompile the DDEx4 sample, and ensure that the resource definition file is also recompiled so that the new bitmap is included. (To do this, you can simply add and then delete a space in the Ddex4.rc file.) The DDEx4 sample will then use the pixel at (0, 0), which is now set to black, as the color key.


Step 2: Creating a Simple Animation

The DDEx4 sample uses the updateFrame sample function to create a simple animation using the red donuts included in the All.bmp file. The animation consists of three red donuts positioned in a triangle and rotating at various speeds. This sample compares the Win32 GetTickCount function with the number of milliseconds since the last call to GetTickCount to determine whether to redraw any of the sprites. It subsequently uses the IDirectDrawSurface3::BltFast method first to blit the background from the off-screen surface (lpDDSOne) to the back buffer, and then to blit the sprites to the back buffer using the color key that you set earlier to determine which pixels are transparent. After the sprites are blitted to the back buffer, DDEx4 calls the IDirectDrawSurface3::Flip method to flip the back buffer and the primary surface.

Note that when you use IDirectDrawSurface3::BltFast to blit the background from the off-screen surface, the dwTrans parameter that specifies the type of transfer is set to DDBLTFAST_NOCOLORKEY. This indicates that a normal blit will occur with no transparency bits. Later, when the red donuts are blitted to the back buffer, the dwTrans parameter is set to DDBLTFAST_SRCCOLORKEY. This indicates that a blit will occur with the color key for transparency as it is defined, in this case, in the lpDDSOne buffer.

In this sample, the entire background is redrawn each time through the updateFrame function. One way of optimizing this sample would be to redraw only that portion of the background that changes while rotating the red donuts. Because the location and size of the rectangles that make up the donut sprites never change, you should be able to easily modify the DDEx4 sample with this optimization.


Tutorial 5: Dynamically Modifying Palettes

The sample described in this tutorial (DDEx5) is a modification of the sample described in Tutorial 4 (DDEx4) example. DDEx5 demonstrates how to dynamically change the palette entries while an application is running. The new functionality demonstrated in DDEx5 is shown in the following steps:

  • Step 1: Loading the Palette Entries
  • Step 2: Rotating the Palettes


Step 1: Loading the Palette Entries

The following code in DDEx5 loads the palette entries with the values in the lower half of the All.bmp file (the part of the bitmap that contains the red donuts):

// First, set all colors as unused.
for(i=0; i<256; i++)
{
    torusColors[i] = 0;
}

// Lock the surface and scan the lower part (the torus area),
// and keep track of all the indexes found.
ddsd.dwSize = sizeof(ddsd);
while (lpDDSOne->Lock(NULL, &ddsd, 0, NULL) == DDERR_WASSTILLDRAWING)
    ;

// Search through the torus frames and mark used colors.
for(y=480; y<480+384; y++)
{
    for(x=0; x<640; x++)
    {
        torusColors[((BYTE *)ddsd.lpSurface)[y*ddsd.lPitch+x]] = 1;
    }
}

lpDDSOne->Unlock(NULL);

The torusColors array is used as an indicator of the color index of the palette used in the lower half of the All.bmp file. Before it is used, all of the values in the torusColors array are reset to 0. The off-screen buffer is then locked in preparation for determining if a color index value is used.

The torusColors array is set to start at row 480 and column 0 of the bitmap. The color index value in the array is determined by the byte of data at the location in memory where the bitmap surface is located. This location is determined by the lpSurface member of the DDSURFACEDESC structure, which is pointing to the memory location corresponding to row 480 and column 0 of the bitmap (y × lPitch + x). The location of the specific color index value is then set to 1. The y-value (row) is multiplied by the lPitch value (found in the DDSURFACEDESC structure) to get the actual location of the pixel in linear memory.

The color index values that are set in torusColors will be used later to determine which colors in the palette are rotated. Because there are no common colors between the background and the red donuts, only those colors associated with the red donuts are rotated. If you want to check whether this is true or not, just remove the "*ddsd.lPitch" from the array and see what happens when you recompile and run the program. (Without multiplying y × lPitch, the red donuts are never reached and only the colors found in the background are indexed and later rotated.) For more information about width and pitch, see Width vs. Pitch.


Step 2: Rotating the Palettes

The updateFrame sample function in DDEx5 works in much the same way as it did in Tutorial 4 (DDEx4). It first blits the background into the back buffer, and then it blits the three donuts in the foreground. However, before it flips the surfaces, updateFrame changes the palette of the primary surface from the palette index that was created in the doInit function, as shown in the following code:

// Change the palette.
if(lpDDPal->GetEntries(0, 0, 256, pe) != DD_OK)
{
    return;
}

for(i=1; i<256; i++)
{
    if(!torusColors[i])
    {
       continue;
    }
    pe[i].peRed = (pe[i].peRed+2) % 256;
    pe[i].peGreen = (pe[i].peGreen+1) % 256;
    pe[i].peBlue = (pe[i].peBlue+3) % 256;
}

if(lpDDPal->SetEntries(0, 0, 256, pe) != DD_OK)
{
    return;
}

The IDirectDrawPalette::GetEntries method in the first line queries palette values from a DirectDrawPalette object. Because the palette entry values pointed to by pe should be valid, the method will return DD_OK and continue. The loop that follows checks torusColors to determine if the color index was set to 1 during its initialization. If so, the red, green, and blue values in the palette entry pointed to by pe are rotated.

After all of the marked palette entries are rotated, the IDirectDrawPalette::SetEntries method is called to change the entries in the DirectDrawPalette object. This change takes place immediately if you are working with a palette set to the primary surface.

With this done, the surfaces are subsequently flipped.


Tutorial 6: Using Overlay Surfaces

This tutorial shows you, step by step, how to use DirectDraw and hardware supported overlay surfaces in your applications. The tutorial is written around the Mosquito sample application included with the DirectX SDK samples. Mosquito is a simple application that uses a flipping chain of overlay surfaces to display an animated bitmap on the desktop without blitting to the primary surface. The sample adjusts the characteristics of the overlay surface as needed to accommodate for hardware limitations.

The Mosquito sample application performs the following steps (complex tasks are divided into smaller sub-steps):

  • Step 1: Creating a Primary Surface
  • Step 2: Testing for Hardware Overlay Support
  • Step 3: Creating an Overlay Surface
  • Step 4: Displaying the Overlay Surface
  • Step 5: Updating the Overlay Display Position
  • Step 6: Hiding the Overlay Surface


Step 1: Creating a Primary Surface

To prepare for using overlay surfaces, you must first initialize DirectDraw and create a primary surface over which the overlay surface will be displayed. Mosquito creates a primary surface with the following code:

    // Zero-out the structure and set the dwSize member.
    ZeroMemory(&ddsd, sizeof(ddsd));
    ddsd.dwSize = sizeof(ddsd);

    // Set flags and create a primary surface.
    ddsd.dwFlags = DDSD_CAPS;
    ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
    ddrval = g_lpdd->CreateSurface(&ddsd, &g_lpddsPrimary, NULL );

The preceding example begins by initializing the DDSURFACEDESC structure it will use. It then sets the flags appropriate to create a primary surface and creates it by calling the IDirectDraw2::CreateSurface method. For the call, the first parameter is a pointer to a DDSURFACEDESC structure that describes the surface to be created. The second parameter is a pointer to a variable that will receive an IDirectDrawSurface interface pointer if the call succeeds. The last parameter is set to NULL to indicate that no COM aggregation is taking place.


Step 2: Testing for Hardware Overlay Support

After initializing DirectDraw, you need to verify that the device supports overlay surfaces. Because DirectDraw doesn't emulate overlays, if the hardware device driver doesn't support them, you can't continue. You can test for overlay support by retrieving the device driver capabilities with the IDirectDraw2::GetCaps method. After the call, look for the presence of the DDCAPS_OVERLAY flag in the dwFlags member of the associated DDCAPS structure. If the flag is present, then the display hardware supports overlays; if not, you can't use overlay surfaces with that device.

The following example, taken from the Mosquito sample application, shows how to test for hardware overlay support:

BOOL AreOverlaysSupported()
{
    DDCAPS  capsDrv;
    HRESULT ddrval;

    // Get driver capabilities to determine Overlay support.
    ZeroMemory(&capsDrv, sizeof(capsDrv));
    capsDrv.dwSize = sizeof(capsDrv);

    ddrval = g_lpdd->GetCaps(&capsDrv, NULL);
    if (FAILED(ddrval))
        return FALSE;

    // Does the driver support overlays in the current mode?
    // (Currently the DirectDraw emulation layer does not support overlays.
    // Overlay related APIs will fail without hardware support).
    if (!(capsDrv.dwCaps & DDCAPS_OVERLAY))
        return FALSE;

    return TRUE;
}

The preceding example calls the IDirectDraw2::GetCaps method to retrieve device driver capabilities. The first parameter for the call is the address of a DDCAPS that will be filled with information describing the device driver's capabilities. Because the application doesn't need information about emulation capabilities, the second parameter is set to NULL.

After retrieving the driver capabilities, the example checks the dwCaps member for the presence of the DDCAPS_OVERLAY flag using a logical AND operation. If the flag isn't present, the example returns FALSE to indicate failure. Otherwise, the example returns TRUE to indicate that the device driver supports overlay surfaces.

In your code, this might be a good time for you to check the dwMaxVisibleOverlays and dwCurrentVisibleOverlays members in the DDCAPS structure to ensure that no other overlay surfaces are in use by other applications.


Step 3: Creating an Overlay Surface

Now that you know that the driver supports overlay surfaces, you can try to create one. Because there is no standard dictating how devices must support overlay surfaces, you can't count on being able to create overlays of any particular size or pixel format. Additionally, you can't expect to succeed in creating an overlay surface on the first try. Therefore, be prepared to attempt creation multiple times starting with the most desirable characteristics, falling back on less desirable (but possibly less hardware intensive) configurations until one works.

Note You can call the IDirectDraw2::GetFourCCCodes method to retrieve a list of FOURCC codes that describe non-RGB pixel formats that the driver will likely support for overlay surfaces. However, in you want to try using RGB overlay surfaces, it is recommended that you attempt to create surfaces in various common RGB formats, falling back on another format if you fail.

The Mosquito sample follows a "best case to worst case" philosophy when creating an overlay surface. Mosquito first tries to create a triple-buffered page flipping complex overlay surface. If the creation attempt fails, the sample tries the configuration with other common pixel formats. The following code fragment shows how this can be done:

    ZeroMemory(&ddsdOverlay, sizeof(ddsdOverlay));
    ddsdOverlay.dwSize = sizeof(ddsdOverlay);

    ddsdOverlay.dwFlags= DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH |
                         DDSD_BACKBUFFERCOUNT| DDSD_PIXELFORMAT;
    ddsdOverlay.ddsCaps.dwCaps = DDSCAPS_OVERLAY | DDSCAPS_FLIP |
                                 DDSCAPS_COMPLEX | DDSCAPS_VIDEOMEMORY;
    ddsdOverlay.dwWidth  =320;
    ddsdOverlay.dwHeight =240;
    ddsdOverlay.dwBackBufferCount=2;

    // Try to create an overlay surface using one of the pixel formats in our
    // global list.
    i=0;
    do{
    ddsdOverlay.ddpfPixelFormat=g_ddpfOverlayFormats[i];
       // Try to create the overlay surface
       ddrval = g_lpdd->CreateSurface(&ddsdOverlay, &g_lpddsOverlay, NULL);
    } while( FAILED(ddrval) && (++i < NUM_OVERLAY_FORMATS) );

The preceding example sets the flags and values within a DDSURFACEDESC structure to reflect a triple-buffered page flipping complex overlay surface. Then, the sample performs a loop during which it attempts to create the requested surface in a variety of common pixel formats, in order of most desirable to least desirable pixel formats. If the attempt succeeds, the loop ends. If all the attempts fail, it's likely that the display hardware doesn't have enough memory to support a triple-buffered scheme or that it doesn't support flipping overlay surfaces. In this case, the sample falls back on a less desirable configuration using a single non-flipping overlay surface, as shown in the following example:

    // If we failed to create a triple buffered complex overlay surface, try
    // again with a single non-flippable buffer.
    if(FAILED(ddrval))
    {
        ddsdOverlay.dwBackBufferCount=0;
        ddsdOverlay.ddsCaps.dwCaps=DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY;
        ddsdOverlay.dwFlags= DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH|DDSD_PIXELFORMAT;

        // Try to create the overlay surface
        ddrval = g_lpdd->CreateSurface(&ddsdOverlay, &g_lpddsOverlay, NULL);
        i=0;
        do{
            ddsdOverlay.ddpfPixelFormat=g_ddpfOverlayFormats[i];
            ddrval = g_lpdd->CreateSurface(&ddsdOverlay, &g_lpddsOverlay, NULL);
        } while( FAILED(ddrval) && (++i < NUM_OVERLAY_FORMATS) );

        // We couldn't create an overlay surface.  Exit, returning failure.
        if (FAILED(ddrval))
            return FALSE;
    }

The previous code resets the flags and values in the DDSURFACEDESC structure to reflect a single non-flipping overlay surface. Again, the example loops through pixel formats attempting to create the surfaces, stopping the loop if an attempt succeeded. If the attempts still didn't work, the sample returns FALSE to indicate failure.

After you've successfully created your overlay surface or surfaces, you can load bitmaps onto them in preparation for display.


Step 4: Displaying the Overlay Surface

After creating your overlay surface, you can display it. Often, display hardware imposes alignment restrictions on the position and pixel width of the rectangles you use to display the overlay. Additionally, you will often need to account for a minimum required stretch factor by adjusting the width of the destination rectangle in order to successfully display the overlay surface. The Mosquito sample performs the following tasks to prepare and display the overlay surface:

  • Step 4.1: Determining the Minimum Display Requirements
  • Step 4.2: Setting Up the Source and Destination Rectangles
  • Step 4.3: Displaying the Overlay Surface


Step 4.1: Determining the Minimum Display Requirements

Most display hardware imposes restrictions on displaying overlay surfaces. You must carefully meet these restrictions in order to successfully display an overlay surface. You can retrieve information about these restrictions by calling the IDirectDraw2::GetCaps method. The DDCAPS structure that the method fills contains information about overlay capabilities and their usage restrictions. Hardware restrictions vary, so always look at the flags included in the dwFlags member to determine which restrictions apply to you.

The Mosquito sample starts by retrieving the hardware capabilities, then takes action based upon the minimum stretch factor, as shown in the following code fragment:

    // Get driver capabilities
    ddrval = g_lpdd->GetCaps(&capsDrv, NULL);
    if (FAILED(ddrval))
        return FALSE;

    // Check the minimum stretch and set the local variable accordingly.
    if(capsDrv.dwCaps & DDCAPS_OVERLAYSTRETCH)
        uStretchFactor1000 = (capsDrv.dwMinOverlayStretch>1000) ? capsDrv.dwMinOverlayStretch : 1000;
    else
        uStretchFactor1000 = 1000;

The preceding code calls GetCaps to retrieve only the hardware capabilities. For this call, the first parameter is a pointer the DDCAPS structure that will be filled with the capability information for the device driver, and the second parameter is NULL to indicate that emulation information is not to be retrieved.

The example retains the minimum stretch factor in a temporary variable for use later. (Keep in mind that stretch factors are reported multiplied by 1000, so 1300 really means 1.3.) If the driver reports a value greater than 1000, it means that the driver requires that all destination rectangles must be stretched along the x-axis by a ratio of the reported value. For example, if the driver reports a stretch factor 1.3 and the source rectangle is 320 pixels wide, the destination rectangle must be at least 416 pixels wide. If the driver reports a stretch factor less than 1000, it means that the driver can display overlays smaller than the source rectangle, but can also stretch the overlay if desired.

Next, the sample examines values describing the driver's size alignment restrictions, as shown in the following example:

    // Grab any alignment restrictions and set the local variables acordingly.
    uSrcSizeAlign = (capsDrv.dwCaps & DDCAPS_ALIGNSIZESRC)?capsDrv.dwAlignSizeSrc:0;
    uDestSizeAlign= (capsDrv.dwCaps & DDCAPS_ALIGNSIZESRC)?capsDrv.dwAlignSizeDest:0;

The sample uses more temporary variables to hold the reported size alignment restrictions taken from the dwAlignSizeSrc and dwAlignSizeDest members. These values provide information about pixel width alignment restrictions and are needed when setting the dimensions of the source and destination rectangles to reflect these restrictions later. Source and destination rectangles must have a pixel width that is a multiple of the values in these members.

Last, the sample examines the value that describes the destination rectangle boundary alignment:

    // Set the "destination position alignment" global so we won't have to
    // keep calling GetCaps() every time we move the overlay surface.
    if (capsDrv.dwCaps & DDCAPS_ALIGNBOUNDARYDEST)
        g_dwOverlayXPositionAlignment = capsDrv.dwAlignBoundaryDest;
    else
        g_dwOverlayXPositionAlignment = 0;

The preceding code uses a global variable to hold the value for the destination rectangle's boundary alignment, as taken from the dwAlignBoundaryDest member. This value will be used when the program repositions the overlay later. (For details, see Step 5: Updating the Overlay Display Position) You must set the x-coordinate of the destination rectangle's top left corner to be aligned with this value, in pixels. That is, if the value specified is 4, you can only specify destination rectangles whose top-left corner has an x-coordinate at pixels 0, 4, 8, 12, and so on. The Mosquito application initially displays the overlay at 0,0, so alignment compliance is assumed and the sample doesn't need to retrieve the restriction information until after displaying the overlay the first time. Your implementation might vary, so you will probably need to check this information and adjust the destination rectangle before displaying the overlay.


Step 4.2: Setting Up the Source and Destination Rectangles

After retrieving the driver's overlay restrictions you should set the values for your source and destination rectangles accordingly, assuring that you will be able to successfully display the overlay. The following sample from the Mosquito sample application starts by setting the characteristics of the source rectangle:

    // Set initial values in the source RECT.
    rs.left=0; rs.top=0;
    rs.right = 320;
    rs.bottom = 240;

    // Apply size alignment restrictions, if necessary.
    if (capsDrv.dwCaps & DDCAPS_ALIGNSIZESRC && uSrcSizeAlign)
        rs.right -= rs.right % uSrcSizeAlign;

The preceding code sets initial values for the surface to include the dimensions of the entire surface. If the device driver requires size alignment for the source rectangle, the example adjusts the source rectangle to conform. The example adjusts the width of the source rectangle to be narrower than the original size because the width cannot be expanded without completely recreating the surface. However, your code could just as easily start with a smaller rectangle and widen the rectangle to meet driver restrictions.

After the dimensions of the source rectangle are set and conform with hardware restrictions, you need to set and adjust the dimensions of the destination rectangle. This process requires a little more work because the rectangle might need to be stretched first, then adjusted to meet size alignment restrictions. The following code performs the task of accounting for the minimum stretch factor:

    // Set up the destination RECT, starting with the source RECT values.
    // We use the source RECT dimensions instead of the surface dimensions in
    // case they differ.
    rd.left=0; rd.top=0;
    rd.right  = (rs.right*uStretchFactor1000+999)/1000;
    // (Adding 999 avoids integer truncation problems.)

    // (This isn't required by DDraw, but we'll stretch the
    //  height, too, to maintain aspect ratio).
    rd.bottom = rs.bottom*uStretchFactor1000/1000;

The preceding code sets the top left corner of the destination rectangle to the top left corner of the screen, then sets the width to account for the minimum stretch factor. While adjusting for the stretch factor, note that the example adds 999 to the product of the width and stretch factor. This is done to prevent integer truncation that could result in a rectangle that isn't as wide as the minimum stretch factor requires. For more information, see Minimum and Maximum Stretch Factors. Also, after the example stretches the width, it stretches the height. Stretching the height isn't required, but was done to preserve the bitmap's aspect ratio and avoid a distorted appearance.

After stretching the destination rectangle, the example continues by adjusting it to conform to size alignment restrictions as follows:

    // Adjust the destination RECT's width to comply with any imposed
    // alignment restrictions.
    if (capsDrv.dwCaps & DDCAPS_ALIGNSIZEDEST && uDestSizeAlign)
        rd.right = (int)((rd.right+uDestSizeAlign-1)/uDestSizeAlign)*uDestSizeAlign;

The example checks the capabilities flags to see if the driver imposes destination size alignment restrictions. If so, the destination rectangle's width is increased by enough pixels to meet alignment restrictions. Note that the rectangle is adjusted by expanding the width, not by decreasing it. This is done because decreasing the width could cause the destination rectangle to be smaller than is required by the minimum stretch factor, consequently causing attempts to display the overlay surface to fail.


Step 4.3: Displaying the Overlay Surface

After you've set up the source and destination rectangles, you can display the overlay for the first time. If you've prepared correctly, this will be simple. The Mosquito sample uses the following code to initially display the overlay:

    // Set the flags we'll send to UpdateOverlay
    dwUpdateFlags = DDOVER_SHOW | DDOVER_DDFX;

    // Does the overlay hardware support source color keying?
    // If so, we can hide the black background around the image.
    // This probably won't work with YUV formats
    if (capsDrv.dwCKeyCaps & DDCKEYCAPS_SRCOVERLAY)
        dwUpdateFlags |= DDOVER_KEYSRCOVERRIDE;

    // Create an overlay FX structure so we can specify a source color key.
    // This information is ignored if the DDOVER_SRCKEYOVERRIDE flag isn't set.
    ZeroMemory(&ovfx, sizeof(ovfx));
    ovfx.dwSize = sizeof(ovfx);

    ovfx.dckSrcColorkey.dwColorSpaceLowValue=0; // Specify black as the color key
    ovfx.dckSrcColorkey.dwColorSpaceHighValue=0;

    // Call UpdateOverlay() to displays the overlay on the screen.
    ddrval = g_lpddsOverlay->UpdateOverlay(&rs, g_lpddsPrimary, &rd, dwUpdateFlags, &ovfx);
    if(FAILED(ddrval))
        return FALSE;

The preceding example starts by setting the DDOVER_SHOW and DDOVER_DDFX flags in the dwUpdateFlags temporary variable, indicating that the overlay is to be displayed for the first time, and that the hardware should use the effects information included in an associated DDOVERLAYFX structure to do so. Next, the example checks a previously existing DDCAPS structure to determine if overlay source color keying is supported. If it is, the DDOVER_KEYSRCOVERRIDE is included in the dwUpdateFlags variable to take advantage of source color keying and the example sets color key values accordingly.

After preparation is complete, the example calls the IDirectDrawSurface3::UpdateOverlay method to display the overlay. For the call, the first and third parameters are the addresses of the adjusted source and destination rectangles. The second parameter is the address of the primary surface over which the overlay will be displayed. The fourth parameter consists of the flags placed in the previously prepared dwUpdateFlags variable, and the fifth parameter is the address of DDOVERLAYFX structure whose members were set to match those flags.

If the hardware only supports one overlay surface and that surface is in use, the UpdateOverlay method fails, returning DDERR_OUTOFCAPS. Additionally, if UpdateOverlay fails, you might try increasing the width of the destination rectangle to accommodate for the possibility that the hardware incorrectly reported a minimum stretch factor that was too small. However, this rarely occurs and Mosquito simply fails if UpdateOverlay doesn't succeed.


Step 5: Updating the Overlay Display Position

After displaying the overlay surface, you might not need to do anything else. However, some software might need to reposition the overlay surface. The Mosquito sample uses the IDirectDrawSurface3::SetOverlayPosition method to reposition the overlay, as shown in the following example:

    // Set x- and y-coordinates
    .
    .
    .
    // We need to check for any alignment restrictions on the x-position
    // and align it if necessary.
    if (g_dwOverlayXPositionAlignment)
        dwXAligned = g_nOverlayXPos - g_nOverlayXPos % g_dwOverlayXPositionAlignment;
    else
        dwXAligned = g_nOverlayXPos;

    // Set the overlay to its new position.
    ddrval = g_lpddsOverlay->SetOverlayPosition(dwXAligned, g_nOverlayYPos);
    if (ddrval == DDERR_SURFACELOST)
    {
        if (!RestoreAllSurfaces())
            return;
    }

The preceding example starts by aligning the rectangle to meet any destination rectangle boundary alignment restrictions that might exist. The global variable that it checks, g_dwOverlayXPositionAlignment, was set earlier to equal the value reported in the dwAlignBoundaryDest member of the DDCAPS structure when the application previously called the IDirectDraw2::GetCaps method. (For details, see Step 4.1: Determining the Minimum Display Requirements). If destination alignment restrictions exist, the example adjusts the new x-coordinate to be pixel-aligned accordingly. Failing to meet this requirement will cause the overlay surface not to be displayed.

After making any requisite adjustments to the new x-coordinate, the example calls IDirectDrawSurface3::SetOverlayPosition method to reposition the overlay. For the call, the first parameter is the aligned x-coordinate, and the second parameter is the new y-coordinate. These values represent the new location of the overlay's top-left corner. Width and height information are not accepted, nor are they needed because DirectDraw already knows the dimensions of the surface from the IDirectDrawSurface3::UpdateOverlay method made to initially display the overlay. If the call fails because one or more surfaces were lost, the example calls an application-defined function to restore them and reload their bitmaps.

Note Take care not to use coordinates too close to the bottom or right edge of the target surface. The IDirectDraw2::SetOverlayPosition method does not perform clipping for you; using coordinates that would potentially make the overlay run off the edge of the target surface will cause the method to fail, returning DDERR_INVALIDPOSITION.


Step 6: Hiding the Overlay Surface

When you do not need the overlay surface anymore, or if you simply want to remove it from view, you can hide the surface by calling the IDirectDrawSurface3::UpdateOverlay method with the appropriate flags. Mosquito hides the overlay in preparation for closing the application using the following code:

void DestroyOverlay()
{
    if (g_lpddsOverlay){
        // Use UpdateOverlay() with the DDOVER_HIDE flag to remove an overlay
        // from the display.
        g_lpddsOverlay->UpdateOverlay(NULL, g_lpddsPrimary, NULL, DDOVER_HIDE, NULL);
        g_lpddsOverlay->Release();
        g_lpddsOverlay=NULL;
    }
}

When the preceding example calls IDirectDrawSurface3::UpdateOverlay, it specifies NULL for the source and destination rectangles, because they are irrelevant when hiding the overlay. Similarly, the example uses NULL in the fifth parameter because overlay effects aren't being used. The second parameter is a pointer to the target surface. Lastly, the example uses the DDOVER_HIDE flag in the fourth parameter to indicate that the overlay will be removed from view.

After the example hides the overlay, the example releases its IDirectDrawSurface3 interface and invalidates its global variable by setting it to NULL. For the purposes of the Mosquito sample application, the overlay surface is no longer needed. If you still need the overlay surface for later, you could simply hide the overlay without releasing it, then redisplay it whenever you require.


DirectDraw Reference

This section contains reference information for the API elements that DirectDraw provides. Reference material is divided into the following categories:

  • Interfaces
  • Functions
  • Callback Functions
  • Structures
  • Return Values
  • Pixel Format Masks
  • Four Character Codes (FOURCC)


Interfaces

This section contains reference information about the interfaces used with the DirectDraw component. The following interfaces are covered:

  • IDDVideoPortContainer
  • IDirectDraw4
  • IDirectDrawClipper
  • IDirectDrawColorControl
  • IDirectDrawGammaControl
  • IDirectDrawPalette
  • IDirectDrawSurface4
  • IDirectDrawVideoPort


IDDVideoPortContainer

Applications use the methods of the IDDVideoPortContainer interface to create and manipulate DirectDrawVideoPort objects. You retrieve a pointer to this interface by calling the IUnknown::QueryInterface method of a DirectDraw object, specifying the IID_IDDVideoPortContainer reference identifier.

The methods of the IDDVideoPortContainer interface can be organized into the following groups:

Creating objects | CreateVideoPort
Video ports | EnumVideoPorts
 | QueryVideoPortStatus
Connections | GetVideoPortConnectInfo

The IDDVideoPortContainer interface, like all COM interfaces, inherits the IUnknown interface methods. The IUnknown interface supports the following three methods:

IUnknown | AddRef
 | QueryInterface
 | Release

You can use the LPDDVIDEOPORTCONTAINER data type to declare a variable that contains a pointer to an IDDVideoPortContainer interface. The Dvp.h header file declares the LPDDVIDEOPORTCONTAINER with the following code:

typedef struct IDDVideoPortContainer    FAR *LPDDVIDEOPORTCONTAINER;

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dvp.h.
Import Library: Use ddraw.lib.


IDDVideoPortContainer::CreateVideoPort

The IDDVideoPortContainer::CreateVideoPort method creates a DirectDrawVideoPort object.

HRESULT CreateVideoPort(
  DWORD dwFlags,
  LPDDVIDEOPORTDESC lpDDVideoPortDesc,
  LPDIRECTDRAWVIDEOPORT FAR *lplpDDVideoPort,
  IUnknown FAR *pUnkOuter
);

Parameters

dwFlags
Flags specifying video-port control options. This parameter can be one of the following flags, or NULL if control options are not needed:
DDVPCREATE_VBIONLY
The process only wants to control the VBI portion of the video stream.
DDVPCREATE_VIDEOONLY
The process only wants to control the non-VBI (video) portion of the video stream.
lpDDVideoPortDesc
Address of a DDVIDEOPORTDESC structure that describes the DirectDrawVideoPort object to be created.
lplpDDVideoPort
Address of a variable that will be filled with a pointer to the new DirectDrawVideoPort object's IDirectDrawVideoPort interface if the call succeeds.
pUnkOuter
Allows for future compatibility with COM aggregation features. Presently, however, this method will return an error if this parameter is anything but NULL.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_CURRENTLYNOTAVAIL
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_NOCOOPERATIVELEVELSET
DDERR_OUTOFCAPS
DDERR_OUTOFMEMORY

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dvp.h.
Import Library: Use ddraw.lib.


IDDVideoPortContainer::EnumVideoPorts

The IDDVideoPortContainer::EnumVideoPorts method enumerates all of the video ports that the hardware exposes that are compatible with a provided video port description.

HRESULT EnumVideoPorts(
  DWORD dwFlags,
  LPDDVIDEOPORTCAPS lpDDVideoPortCaps,
  LPVOID lpContext,
  LPENUMVIDEOCALLBACK lpEnumVideoCallback
);

Parameters

dwFlags
Reserved for future use. This parameter must be zero.
lpDDVideoPortCaps
Pointer to a DDVIDEOPORTCAPS structure that will be checked against the available video ports. If this parameter is NULL, all video ports will be enumerated.
lpContext
Address of a caller-defined structure that will be passed to each enumeration member.
lpEnumVideoCallback
Address of the EnumVideoCallback function that will be called each time a match is found.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dvp.h.
Import Library: Use ddraw.lib.


IDDVideoPortContainer::GetVideoPortConnectInfo

The IDDVideoPortContainer::GetVideoPortConnectInfo method retrieves the connection information supported by all video ports.

HRESULT GetVideoPortConnectInfo(
  DWORD dwPortId,
  LPDWORD lpNumEntries,
  LPDDVIDEOPORTCONNECT lpConnectInfo
);

Parameters

dwPortId
Identifier of the video port for which the connection information will be retrieved.
lpNumEntries
Address of a variable containing the number of entries that the array at lpConnectInfo can hold. If this number is less than the total number of connections, the method fills the array with as many entries as will fit, sets the value at lpNumEntries to indicate the total number of connections, and returns DDERR_MOREDATA.
lpConnectInfo
Address of an array of DDVIDEOPORTCONNECT structures that will be filled with the connection options supported by the specified video port. If this parameter is NULL, the method sets lpNumEntries to indicate the total number of connections that the video port supports, then returns DD_OK.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_MOREDATA

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dvp.h.
Import Library: Use ddraw.lib.


IDDVideoPortContainer::QueryVideoPortStatus

The IDDVideoPortContainer::QueryVideoPortStatus method retrieves the status of a DirectDrawVideoPort object.

HRESULT QueryVideoPortStatus(
  DWORD dwPortId,
  LPDDVIDEOPORTSTATUS lpVPStatus
);

Parameters

dwPortId
Identifier of the video port for which the status information will be retrieved.
lpVPStatus
Address of a DDVIDEOPORTSTATUS structure that will be filled with information about the status of the specified video port.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_CURRENTLYNOTAVAIL
DDERR_EXCEPTION
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_UNSUPPORTED

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dvp.h.
Import Library: Use ddraw.lib.


IDirectDraw4

Applications use the methods of the IDirectDraw4 interface to create DirectDraw objects and work with system-level variables. This section is a reference to the methods of this interface. For a conceptual overview, see The DirectDraw Object.

The methods of the IDirectDraw4 interface can be organized into the following groups:

Allocating memory | Compact
 | Initialize
Cooperative levels | SetCooperativeLevel
 | TestCooperativeLevel
Creating objects | CreateClipper
 | CreatePalette
 | CreateSurface
Device capabilities | GetCaps
Display modes | EnumDisplayModes
 | GetDisplayMode
 | GetMonitorFrequency
 | RestoreDisplayMode
 | SetDisplayMode
 | WaitForVerticalBlank
Display status | GetScanLine
 | GetVerticalBlankStatus
Miscellaneous | GetAvailableVidMem
 | GetDeviceIdentifier
 | GetFourCCCodes
Surface management | DuplicateSurface
 | EnumSurfaces
 | FlipToGDISurface
 | GetGDISurface
 | GetSurfaceFromDC
 | RestoreAllSurfaces

The IDirectDraw4 interface, like all COM interfaces, inherits the IUnknown interface methods. The IUnknown interface supports the following three methods:

IUnknown | AddRef
 | QueryInterface
 | Release

The IDirectDraw4 interface extends the features of previous versions of the interface by offering methods enabling more flexible surface management than previous versions. Note that all of the surface-related methods in the IDirectDraw4 interface accept slightly different parameters than their counterparts in the IDirectDraw2 interface. Wherever an IDirectDraw2 interface method might accept a DDSURFACEDESC structure and retrieve an IDirectDrawSurface3 interface, the methods in IDirectDraw4 accept a DDSURFACEDESC2 structure and retrieve an IDirectDrawSurface4 interface instead.

IDirectDraw4 introduces improved compliance with COM rules dictating the lifetimes of child objects. For more information, see Parent and Child Object Lifetimes.

You can use the LPDIRECTDRAW, LPDIRECTDRAW2, or LPDIRECTDRAW4 data types to declare a variable that contains a pointer to an IDirectDraw, IDirectDraw2, or IDirectDraw4 interface. The Ddraw.h header file declares these data types with the following code:

typedef struct IDirectDraw     FAR *LPDIRECTDRAW;
typedef struct IDirectDraw2    FAR *LPDIRECTDRAW2;
typedef struct IDirectDraw4    FAR *LPDIRECTDRAW4;

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.


IDirectDraw4::Compact

The IDirectDraw4::Compact method is not currently implemented.

HRESULT Compact();

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_NOEXCLUSIVEMODE
DDERR_SURFACEBUSY

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.


IDirectDraw4::CreateClipper

The IDirectDraw4::CreateClipper method creates a DirectDrawClipper object.

HRESULT CreateClipper(
  DWORD dwFlags,
  LPDIRECTDRAWCLIPPER FAR *lplpDDClipper,
  IUnknown FAR *pUnkOuter
);

Parameters

dwFlags
This parameter is currently not used and must be set to 0.
lplpDDClipper
Address of a variable that will be set to a valid IDirectDrawClipper interface pointer if the call succeeds.
pUnkOuter
Allows for future compatibility with COM aggregation features. Presently, however, this method will return an error if this parameter is anything but NULL.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_NOCOOPERATIVELEVELSET
DDERR_OUTOFMEMORY

Remarks

The DirectDrawClipper object can be attached to a DirectDrawSurface and used during IDirectDrawSurface4::Blt, IDirectDrawSurface4::BltBatch, and IDirectDrawSurface4::UpdateOverlay operations.

To create a DirectDrawClipper object that is not owned by a specific DirectDraw object, use the DirectDrawCreateClipper function.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.

See Also

IDirectDrawSurface4::GetClipper, IDirectDrawSurface4::SetClipper


IDirectDraw4::CreatePalette

The IDirectDraw4::CreatePalette method creates a DirectDrawPalette object for this DirectDraw object.

HRESULT CreatePalette(
  DWORD dwFlags,
  LPPALETTEENTRY lpDDColorArray,
  LPDIRECTDRAWPALETTE FAR *lplpDDPalette,
  IUnknown FAR *pUnkOuter
);

Parameters

dwFlags
One or more of the following flags:
DDPCAPS_1BIT
Indicates that the index is 1 bit. There are two entries in the color table.
DDPCAPS_2BIT
Indicates that the index is 2 bits. There are four entries in the color table.
DDPCAPS_4BIT
Indicates that the index is 4 bits. There are 16 entries in the color table.
DDPCAPS_8BIT
Indicates that the index is 8 bits. There are 256 entries in the color table.
DDPCAPS_8BITENTRIES
Indicates that the index refers to an 8-bit color index. This flag is valid only when used with the DDPCAPS_1BIT, DDPCAPS_2BIT, or DDPCAPS_4BIT flag, and when the target surface is in 8 bpp. Each color entry is 1 byte long and is an index to a destination surface's 8-bpp palette.
DDPCAPS_ALPHA
Indicates that the peFlags member of the associated PALETTEENTRY structure is to be interpreted as a single 8-bit alpha value (in addition to the peRed, peGreen, and peBlue members). A palette created with this flag can only be attached to a texture—a surface created with the DDSCAPS_TEXTURE capability flag.
DDPCAPS_ALLOW256
Indicates that this palette can have all 256 entries defined.
DDPCAPS_INITIALIZE
Initialize this palette with the colors in the color array passed at lpDDColorArray.
DDPCAPS_PRIMARYSURFACE
This palette is attached to the primary surface. Changing this palette's color table immediately affects the display unless DDPSETPAL_VSYNC is specified and supported.
DDPCAPS_PRIMARYSURFACELEFT
This palette is the one attached to the left eye primary surface. Changing this palette's color table immediately affects the left eye display unless DDPSETPAL_VSYNC is specified and supported.
DDPCAPS_VSYNC
This palette can have modifications to it synced with the monitors refresh rate.
lpDDColorArray
Address of an array of 2, 4, 16, or 256 PALETTEENTRY structures that will initialize this DirectDrawPalette object.
lplpDDPalette
Address of a variable that will be set to a valid IDirectDrawPalette interface pointer if the call succeeds.
pUnkOuter
Allows for future compatibility with COM aggregation features. Presently, however, this method will return an error if this parameter is anything but NULL.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_NOCOOPERATIVELEVELSET
DDERR_OUTOFMEMORY
DDERR_UNSUPPORTED

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.


IDirectDraw4::CreateSurface

The IDirectDraw4::CreateSurface method creates a DirectDrawSurface object for this DirectDraw object.

HRESULT CreateSurface(
  LPDDSURFACEDESC2 lpDDSurfaceDesc2,
  LPDIRECTDRAWSURFACE4 FAR *lplpDDSurface,
  IUnknown FAR *pUnkOuter
);

Parameters

lpDDSurfaceDesc2
Address of a DDSURFACEDESC2 structure that describes the requested surface. You should set any unused members of the DDSURFACEDESC2 structure to zero before calling this method. A DDSCAPS2 structure is a member of DDSURFACEDESC2.
lplpDDSurface
Address of a variable that will be set to a valid IDirectDrawSurface4 interface pointer if the call succeeds.
pUnkOuter
Allows for future compatibility with COM aggregation features. Presently, however, this method will return an error if this parameter is anything but NULL.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_INCOMPATIBLEPRIMARY
DDERR_INVALIDCAPS
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_INVALIDPIXELFORMAT
DDERR_NOALPHAHW
DDERR_NOCOOPERATIVELEVELSET
DDERR_NODIRECTDRAWHW
DDERR_NOEMULATION
DDERR_NOEXCLUSIVEMODE
DDERR_NOFLIPHW
DDERR_NOMIPMAPHW
DDERR_NOOVERLAYHW
DDERR_NOZBUFFERHW
DDERR_OUTOFMEMORY
DDERR_OUTOFVIDEOMEMORY
DDERR_PRIMARYSURFACEALREADYEXISTS
DDERR_UNSUPPORTEDMODE

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.


IDirectDraw4::DuplicateSurface

The IDirectDraw4::DuplicateSurface method duplicates a DirectDrawSurface object.

HRESULT DuplicateSurface(
  LPDIRECTDRAWSURFACE4 lpDDSurface,
  LPLPDIRECTDRAWSURFACE4 FAR *lplpDupDDSurface
);

Parameters

lpDDSurface
Address of the IDirectDrawSurface4 interface for the surface to be duplicated.
lplpDupDDSurface
Address of a variable that will be filled with an IDirectDrawSurface4 interface pointer for the newly duplicated DirectDrawSurface object.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_CANTDUPLICATE
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_OUTOFMEMORY
DDERR_SURFACELOST

Remarks

This method creates a new DirectDrawSurface object that points to the same surface memory as an existing DirectDrawSurface object. This duplicate can be used just like the original object. The surface memory is released after the last object referencing it is released. A primary surface, 3-D surface, or implicitly created surface cannot be duplicated.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.


IDirectDraw4::EnumDisplayModes

The IDirectDraw4::EnumDisplayModes method enumerates all of the display modes the hardware exposes through the DirectDraw object that are compatible with a provided surface description.

HRESULT EnumDisplayModes(
  DWORD dwFlags,
  LPDDSURFACEDESC2 lpDDSurfaceDesc2,
  LPVOID lpContext,
  LPDDENUMMODESCALLBACK2 lpEnumModesCallback
);

Parameters

dwFlags
DDEDM_REFRESHRATES
Enumerates modes with different refresh rates. IDirectDraw4::EnumDisplayModes guarantees that a particular mode will be enumerated only once. This flag specifies whether the refresh rate is taken into account when determining if a mode is unique.
DDEDM_STANDARDVGAMODES
Enumerates Mode 13 in addition to the 320x200x8 Mode X mode.
lpDDSurfaceDesc2
Address of a DDSURFACEDESC2 structure that will be checked against available modes. If the value of this parameter is NULL, all modes are enumerated.
lpContext
Address of an application-defined structure that will be passed to each enumeration member.
lpEnumModesCallback
Address of the EnumModesCallback2 function that the enumeration procedure will call every time a match is found.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS

Remarks

This method enumerates the dwRefreshRate member of the DDSURFACEDESC2 structure; the IDirectDraw::EnumDisplayModes method does not contain this capability. If you use the IDirectDraw4::SetDisplayMode method to set the refresh rate of a new mode, you must use IDirectDraw4::EnumDisplayModes to enumerate the dwRefreshRate member.

This method differs from its counterparts in former interfaces in that it accepts the address of an EnumModesCallback2 function as a parameter rather than an EnumModesCallback function.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.

See Also

IDirectDraw4::GetDisplayMode, IDirectDraw4::SetDisplayMode, IDirectDraw4::RestoreDisplayMode


IDirectDraw4::EnumSurfaces

The IDirectDraw4::EnumSurfaces method enumerates all of the existing or possible surfaces that meet the specified surface description.

HRESULT EnumSurfaces(
  DWORD dwFlags,
  LPDDSURFACEDESC2 lpDDSD2,
  LPVOID lpContext,
  LPDDENUMSURFACESCALLBACK2 lpEnumSurfacesCallback
);

Parameters

dwFlags
A combination of one search type flag and one matching flag. The search type flag determines how the method searches for matching surfaces; you can search for surfaces that can be created using the description in the lpDDSD2 parameter or you can search for existing surfaces that already match that description. The matching flag determines whether the method enumerates all surfaces, only those that match, or only those that don't match the description in the lpDDSD2 parameter.
Search type flags
DDENUMSURFACES_CANBECREATED
Enumerates the first surface that can be created and meets the search criterion. This flag can only be used with the DDENUMSURFACES_MATCH flag.
DDENUMSURFACES_DOESEXIST
Enumerates the already existing surfaces that meet the search criterion.
Matching flags
DDENUMSURFACES_ALL
Enumerates all of the surfaces that meet the search criterion. This flag can only be used with the DDENUMSURFACES_DOESEXIST search type flag.
DDENUMSURFACES_MATCH
Searches for any surface that matches the surface description.
DDENUMSURFACES_NOMATCH
Searches for any surface that does not match the surface description.
lpDDSD2
Address of a DDSURFACEDESC2 structure that defines the surface of interest. This parameter can be NULL if dwFlags includes the DDENUMSURFACES_ALL flag.
lpContext
Address of an application-defined structure that will be passed to each enumeration member.
lpEnumSurfacesCallback
Address of the EnumSurfacesCallback2 function the enumeration procedure will call every time a match is found.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS

Remarks

If the DDENUMSURFACES_CANBECREATED flag is set, this method attempts to temporarily create a surface that meets the search criterion.

When using the DDENUMSURFACES_DOESEXIST flag, note that an enumerated surface's reference count is incremented—if you are not going to use the surface, be sure to use IDirectDrawSurface4::Release to release it after each enumeration. If you will be using the surface, release it when it is no longer needed.

This method differs from its counterparts in previous interface versions in that it accepts a pointer to an EnumSurfacesCallback2 function, rather than an EnumSurfacesCallback function.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.

See Also

Enumerating Surfaces


IDirectDraw4::FlipToGDISurface

The IDirectDraw4::FlipToGDISurface method makes the surface that GDI writes to the primary surface.

HRESULT FlipToGDISurface();

Parameters

None.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_NOTFOUND

Remarks

This method can be called at the end of a page-flipping application to ensure that the display memory that GDI is writing to is visible to the user.

The method can also be used to make the GDI surface the primary surface, so that normal windows such as dialog boxes can be displayed in full-screen mode. The hardware must have the DDCAPS2_CANRENDERWINDOWED capability. For more information, see Displaying a Window in Full-Screen Mode

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.

See Also

IDirectDraw4::GetGDISurface


IDirectDraw4::GetAvailableVidMem

The IDirectDraw4::GetAvailableVidMem method retrieves the total amount of display memory available and the amount of display memory currently free for a given type of surface.

HRESULT GetAvailableVidMem(
  LPDDSCAPS2 lpDDSCaps2,
  LPDWORD    lpdwTotal,
  LPDWORD    lpdwFree
);

Parameters

lpDDSCaps2
Address of a DDSCAPS2 structure that indicates the hardware capabilities of the proposed surface.
lpdwTotal
Address of a variable that will be filled with the total amount of display memory available, in bytes. The value retrieved reflects the total video memory, less the video memory required for the primary surface and any private caches the display driver reserves.
lpdwFree
Address of a variable that will be filled with the amount of display memory currently free that can be allocated for a surface that matches the capabilities specified by the structure at lpDDSCaps2.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_INVALIDCAPS
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_NODIRECTDRAWHW

If NULL is passed to either lpdwTotal or lpdwFree, the value for that parameter is not returned.

Remarks

The following C++ example demonstrates using IDirectDraw4::GetAvailableVidMem to determine both the total and free display memory available for texture-map surfaces:

// For this example, the lpDD variable is a valid
// pointer to an IDirectDraw interface.
LPDIRECTDRAW4 lpDD4;
DDSCAPS2      ddsCaps2;
DWORD         dwTotal;
DWORD         dwFree;
HRESULT       hr;

hr = lpDD->QueryInterface(IID_IDirectDraw4, &lpDD4);
if (FAILED(hr))
    return hr;

// Initialize the structure.
ZeroMemory(&ddsCaps2, sizeof(ddsCaps2));

ddsCaps2.dwCaps = DDSCAPS_TEXTURE;
hr = lpDD4->GetAvailableVidMem(&ddsCaps2, &dwTotal, &dwFree);
if (FAILED(hr))
    return hr;

This method provides only a snapshot of the current display-memory state. The amount of free display memory is subject to change as surfaces are created and released. Therefore, you should use the free memory value only as an approximation. In addition, a particular display adapter card may make no distinction between two different memory types. For example, the adapter might use the same portion of display memory to store z-buffers and textures. So, allocating one type of surface (for example, a z-buffer) can affect the amount of display memory available for another type of surface (for example, textures). Therefore, it is best to first allocate an application's fixed resources (such as front and back buffers , and z-buffers) before determining how much memory is available for dynamic use (such as texture mapping).

This method was not implemented in the IDirectDraw interface.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.


IDirectDraw4::GetCaps

The IDirectDraw4::GetCaps method fills in the capabilities of the device driver for the hardware and the hardware-emulation layer (HEL).

HRESULT GetCaps(
  LPDDCAPS lpDDDriverCaps,
  LPDDCAPS lpDDHELCaps
);

Parameters

lpDDDriverCaps
Address of a DDCAPS structure that will be filled with the capabilities of the hardware, as reported by the device driver. Set this parameter to NULL if device driver capabilities are not to be retrieved.
lpDDHELCaps
Address of a DDCAPS structure that will be filled with the capabilities of the HEL. Set this parameter to NULL if HEL capabilities are not to be retrieved.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS

You can only set one of the two parameters to NULL to exclude it. If you set both to NULL the method will fail, returning DDERR_INVALIDPARAMS.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.


IDirectDraw4::GetDeviceIdentifier

The IDirectDraw4::GetDeviceIdentifier method obtains information about the driver. This method can be used, with caution, to recognize specific hardware installations in order to implement workarounds for poor driver/chipset behavior.

HRESULT GetDeviceIdentifier(
  LPDDDEVICEIDENTIFIER lpdddi,
  DWORD dwFlags
);

Parameters

lpdddi
Address of a DDDEVICEIDENTIFIER structure to receive information about the driver.
dwFlags
Flags specifying options. The following flag is defined:
DDGDI_GETHOSTIDENTIFIER
Causes the method to return information about the host (typically 2-D) adapter in a system equipped with a stacked secondary 3-D adapter. Such an adapter appears to the application as if it were part of the host adapter, but is typically located on a separate card. When the dwFlags parameter is zero, the stacked secondary's information is returned, because this most accurately reflects the qualities of the DirectDraw object involved.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be DDERR_INVALIDPARAMS.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.


IDirectDraw4::GetDisplayMode

The IDirectDraw4::GetDisplayMode method retrieves the current display mode.

HRESULT GetDisplayMode(
  LPDDSURFACEDESC2 lpDDSurfaceDesc2
);

Parameters

lpDDSurfaceDesc2
Address of a DDSURFACEDESC2 structure that will be filled with a description of the surface.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_UNSUPPORTEDMODE

Remarks

An application should not save the information returned by this method to restore the display mode on clean-up. The application should use the IDirectDraw4::RestoreDisplayMode method to restore the mode on clean-up, thereby avoiding mode-setting conflicts that could arise in a multiprocess environment.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.

See Also

IDirectDraw4::SetDisplayMode, IDirectDraw4::RestoreDisplayMode, IDirectDraw4::EnumDisplayModes


IDirectDraw4::GetFourCCCodes

The IDirectDraw4::GetFourCCCodes method retrieves the FOURCC codes supported by the DirectDraw object. This method can also retrieve the number of codes supported.

HRESULT GetFourCCCodes(
  LPDWORD lpNumCodes,
  LPDWORD lpCodes
);

Parameters

lpNumCodes
Address of a variable that contains the number of entries that the array pointed to by lpCodes can hold. If the number of entries is too small to accommodate all the codes, lpNumCodes is set to the required number and the array pointed to by lpCodes is filled with all that fits.
lpCodes
Address of an array of variables that will be filled with FOURCC codes supported by this DirectDraw object. If you specify NULL, lpNumCodes is set to the number of supported FOURCC codes and the method will return.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.


IDirectDraw4::GetGDISurface

The IDirectDraw4::GetGDISurface method retrieves the DirectDrawSurface object that currently represents the surface memory that GDI is treating as the primary surface.

HRESULT GetGDISurface(
  LPDIRECTDRAWSURFACE4 FAR *lplpGDIDDSSurface4
);

Parameters

lplpGDIDDSSurface4
Address of a variable that will be filled with a pointer to the IDirectDrawSurface4 interface for the surface that currently controls GDI's primary surface memory.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_NOTFOUND

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.

See Also

IDirectDraw4::FlipToGDISurface


IDirectDraw4::GetMonitorFrequency

The IDirectDraw4::GetMonitorFrequency method retrieves the frequency of the monitor being driven by the DirectDraw object.

HRESULT GetMonitorFrequency(
  LPDWORD lpdwFrequency
);

Parameters

lpdwFrequency
Address of the variable that will be filled with the monitor frequency, reported in Hz.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_UNSUPPORTED

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.


IDirectDraw4::GetScanLine

The IDirectDraw4::GetScanLine method retrieves the scan line that is currently being drawn on the monitor.

HRESULT GetScanLine(
  LPDWORD lpdwScanLine
);

Parameters

lpdwScanLine
Address of the variable that will contain the scan line the display is currently drawing.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_UNSUPPORTED
DDERR_VERTICALBLANKINPROGRESS

Remarks

Scan lines are reported as zero-based integers. The returned scan line value is between 0 and n, where scan line 0 is the first visible scan line on the screen and n is the last visible scan line, plus any scan lines that occur during the vertical blank period. So, in a case where an application is running at 640×480, and there are 12 scan lines during vblank, the values returned by this method will range from 0 to 491.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.

See Also

IDirectDraw4::GetVerticalBlankStatus, IDirectDraw4::WaitForVerticalBlank


IDirectDraw4::GetSurfaceFromDC

The IDirectDraw4::GetSurfaceFromDC method retrieves the IDirectDrawSurface4 interface for a surface based on its GDI device context handle.

HRESULT GetSurfaceFromDC(
  HDC hdc,
  LPDIRECTDRAWSURFACE4 * lpDDS4
);

Parameters

hdc
Handle to a display device context.
lpDDS4
Address of a variable that will be filled with a valid IDirectDrawSurface4 interface pointer if the call succeeds.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_GENERIC
DDERR_INVALIDPARAMS
DDERR_OUTOFMEMORY
DDERR_NOTFOUND

Remarks

This method will succeed only for device context handles that identify surfaces already associated with the DirectDraw object.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.

See Also

Surfaces and Device Contexts


IDirectDraw4::GetVerticalBlankStatus

The IDirectDraw4::GetVerticalBlankStatus method retrieves the status of the vertical blank.

HRESULT GetVerticalBlankStatus(
  LPBOOL lpbIsInVB
);

Parameters

lpbIsInVB
Address of the variable that will be filled with the status of the vertical blank. This parameter is TRUE if a vertical blank is occurring, and FALSE otherwise.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS

Remarks

To synchronize with the vertical blank, use the IDirectDraw4::WaitForVerticalBlank method.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.

See Also

IDirectDraw4::GetScanLine, IDirectDraw4::WaitForVerticalBlank


IDirectDraw4::Initialize

The IDirectDraw4::Initialize method initializes a DirectDraw object that was created by using the CoCreateInstance COM function.

HRESULT Initialize(
  GUID FAR *lpGUID
);

Parameters

lpGUID
Address of the globally unique identifier (GUID) used as the interface identifier.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_ALREADYINITIALIZED
DDERR_DIRECTDRAWALREADYCREATED
DDERR_GENERIC
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_NODIRECTDRAWHW
DDERR_NODIRECTDRAWSUPPORT
DDERR_OUTOFMEMORY

This method is provided for compliance with the Component Object Model (COM) protocol. If the DirectDrawCreate function was used to create a DirectDraw object, this method returns DDERR_ALREADYINITIALIZED. If IDirectDraw4::Initialize is not called when using CoCreateInstance to create a DirectDraw object, any method that is called afterward returns DDERR_NOTINITIALIZED.

Remarks

For more information about using IDirectDraw4::Initialize with CoCreateInstance, see Creating DirectDraw Objects by Using CoCreateInstance.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.


IDirectDraw4::RestoreAllSurfaces

The IDirectDraw4::RestoreAllSurfaces method restores all the surfaces created for the DirectDraw object, in the order they were created.

HRESULT RestoreAllSurfaces();

Parameters

None.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS

Remarks

This method is provided for convenience. Effectively, this method calls the IDirectDrawSurface4::Restore method for each surface created by this DirectDraw object.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.

See Also

IDirectDrawSurface4::Restore, Losing and Restoring Surfaces


IDirectDraw4::RestoreDisplayMode

The IDirectDraw4::RestoreDisplayMode method resets the mode of the display device hardware for the primary surface to what it was before the IDirectDraw4::SetDisplayMode method was called. Exclusive-level access is required to use this method.

HRESULT RestoreDisplayMode();

Parameters

None.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_GENERIC
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_LOCKEDSURFACES
DDERR_NOEXCLUSIVEMODE

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.

See Also

IDirectDraw4::SetDisplayMode, IDirectDraw4::EnumDisplayModes, IDirectDraw4::SetCooperativeLevel


IDirectDraw4::SetCooperativeLevel

The IDirectDraw4::SetCooperativeLevel method determines the top-level behavior of the application.

HRESULT SetCooperativeLevel(
  HWND hWnd,
  DWORD dwFlags
);

Parameters

hWnd
Window handle used for the application. Set to the calling application's top-level window handle (not a handle for any child windows created by the top-level window). This parameter can be NULL when the DDSCL_NORMAL flag is specified in the dwFlags parameter.
dwFlags
One or more of the following flags:
DDSCL_ALLOWMODEX
Allows the use of Mode X display modes. This flag can only be used if the DDSCL_EXCLUSIVE and DDSCL_FULLSCREEN flags are present.
DDSCL_ALLOWREBOOT
Allows CTRL+ALT+DEL to function while in exclusive (full-screen) mode.
DDSCL_CREATEDEVICEWINDOW
This flag is supported in Windows 98 and Windows 2000 only. Indicates that DirectDraw is to create and manage a default device window for this DirectDraw object. For more information, see Focus and Device Windows.
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, see DirectDraw Cooperative Levels and FPU Precision.
DDSCL_FULLSCREEN
Indicates that the exclusive-mode owner will be responsible for the entire primary surface. GDI can be ignored. This flag must be used with the DDSCL_EXCLUSIVE flag.
DDSCL_MULTITHREADED
Requests multithread-safe DirectDraw behavior. This causes Direct3D to take the global critical section more frequently.
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.
DDSCL_SETDEVICEWINDOW
This flag is supported in Windows 98 and Windows 2000 only. Indicates that the hWnd parameter is the window handle of the device window for this DirectDraw object. This flag cannot be used with the DDSCL_SETFOCUSWINDOW flag.
DDSCL_SETFOCUSWINDOW
This flag is supported in Windows 98 and Windows 2000 only. Indicates that the hWnd parameter is the window handle of the focus window for this DirectDraw object. This flag cannot be used with the DDSCL_SETDEVICEWINDOW flag.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_EXCLUSIVEMODEALREADYSET
DDERR_HWNDALREADYSET
DDERR_HWNDSUBCLASSED
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_OUTOFMEMORY

Remarks

This method must be called by the same thread that created the application window.

An application must set either the DDSCL_EXCLUSIVE or DDSCL_NORMAL flag.

The DDSCL_EXCLUSIVE flag must be set to call functions that can have drastic performance consequences for other applications. For more information, see Cooperative Levels.

Interaction between this method and the IDirectDraw4::SetDisplayMode method differs from their IDirectDraw counterparts. For more information, see Restoring Display Modes.

Developers using Microsoft Foundation Classes (MFC) should keep in mind that the window handle passed to this method should identify the application's top-level window, not a derived child window. To retrieve your MFC application's top level window handle, you could use the following code:

    HWND hwndTop = AfxGetMainWnd()->GetSafeHwnd();

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.

See Also

IDirectDraw4::SetDisplayMode, IDirectDraw4::Compact, IDirectDraw4::EnumDisplayModes, Mode X and Mode 13 Display Modes, Focus and Device Windows


IDirectDraw4::SetDisplayMode

The IDirectDraw4::SetDisplayMode method sets the mode of the display-device hardware.

HRESULT SetDisplayMode(
  DWORD dwWidth,
  DWORD dwHeight,
  DWORD dwBPP,
  DWORD dwRefreshRate,
  DWORD dwFlags
);

Parameters

dwWidth and dwHeight
Width and height of the new mode.
dwBPP
Bits per pixel (bpp) of the new mode.
dwRefreshRate
Refresh rate of the new mode. Set this value to 0 to request the default refresh rate for the driver.
dwFlags
Flags describing additional options. Currently, the only valid flag is DDSDM_STANDARDVGAMODE, which causes the method to set Mode 13 instead of Mode X 320x200x8 mode. If you are setting another resolution, bit depth, or a Mode X mode, do not use this flag and set the parameter to 0.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_GENERIC
DDERR_INVALIDMODE
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_LOCKEDSURFACES
DDERR_NOEXCLUSIVEMODE
DDERR_SURFACEBUSY
DDERR_UNSUPPORTED
DDERR_UNSUPPORTEDMODE
DDERR_WASSTILLDRAWING

Remarks

This method must be called by the same thread that created the application window.

If another application changes the display mode, the primary surface will be lost and will return DDERR_SURFACELOST until it is recreated to match the new display mode.

As part of the IDirectDraw interface, this method did not include the dwRefreshRate and dwFlags parameters.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.

See Also

IDirectDraw4::RestoreDisplayMode, IDirectDraw4::GetDisplayMode, IDirectDraw4::EnumDisplayModes, IDirectDraw4::SetCooperativeLevel, Setting Display Modes, Restoring Display Modes


IDirectDraw4::TestCooperativeLevel

The IDirectDraw4::TestCooperativeLevel method reports the current cooperative-level status of the DirectDraw device for a windowed or full-screen application.

HRESULT TestCooperativeLevel(void);

Parameters

None.

Return Values

If the method succeeds, the return value is DD_OK, indicating that the calling application can continue executing.

If the method fails, the return value may be one of the following error values (see remarks):

DDERR_INVALIDOBJECT
DDERR_EXCLUSIVEMODEALREADYSET
DDERR_NOEXCLUSIVEMODE
DDERR_WRONGMODE

Remarks

This method is particularly useful to applications that use the WM_ACTIVATEAPP and WM_DISPLAYCHANGE system messages as a notification to restore surfaces or re-create DirectDraw objects. The DD_OK return value always indicates that the application can continue execution, but the failure codes are interpreted differently depending on the cooperative-level that the application uses. For more information, see Testing Cooperative Levels.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.


IDirectDraw4::WaitForVerticalBlank

The IDirectDraw4::WaitForVerticalBlank method helps the application synchronize itself with the vertical-blank interval.

HRESULT WaitForVerticalBlank(
  DWORD dwFlags,
  HANDLE hEvent
);

Parameters

dwFlags
Determines how long to wait for the vertical blank.
DDWAITVB_BLOCKBEGIN
Returns when the vertical-blank interval begins.
DDWAITVB_BLOCKBEGINEVENT
Triggers an event when the vertical blank begins. This value is not currently supported.
DDWAITVB_BLOCKEND
Returns when the vertical-blank interval ends and the display begins.
hEvent
Handle of the event to be triggered when the vertical blank begins. This parameter is not currently used.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_UNSUPPORTED
DDERR_WASSTILLDRAWING

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.

See Also

IDirectDraw4::GetVerticalBlankStatus, IDirectDraw4::GetScanLine


IDirectDrawClipper

Applications use the methods of the IDirectDrawClipper interface to manage clip lists. This section is a reference to the methods of this interface. For a conceptual overview, see Clippers.

The methods of the IDirectDrawClipper interface can be organized into the following groups:

Allocating memory | Initialize
Clip list | GetClipList
 | IsClipListChanged
 | SetClipList
 | SetHWnd
Handles | GetHWnd

The IDirectDrawClipper interface, like all COM interfaces, inherits the IUnknown interface methods. The IUnknown interface supports the following three methods:

IUnknown | AddRef
 | QueryInterface
 | Release

You can use the LPDIRECTDRAWCLIPPER data type to declare a variable that contains a pointer to an IDirectDrawClipper interface. The Ddraw.h header file declares these data types with the following code:

typedef struct IDirectDrawClipper    FAR *LPDIRECTDRAWCLIPPER;

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.


IDirectDrawClipper::GetClipList

The IDirectDrawClipper::GetClipList method retrieves a copy of the clip list associated with a DirectDrawClipper object. A subset of the clip list can be selected by passing a rectangle that clips the clip list.

HRESULT GetClipList(
  LPRECT lpRect,
  LPRGNDATA lpClipList,
  LPDWORD lpdwSize
);

Parameters

lpRect
Address of a rectangle that will be used to clip the clip list. This parameter can be NULL to retrieve the entire clip list.
lpClipList
Address of an RGNDATA structure that will contain the resulting copy of the clip list. If this parameter is NULL, the method fills the variable at lpdwSize to the number of bytes necessary to hold the entire clip list.
lpdwSize
Size of the resulting clip list. When retrieving the clip list, this parameter is the size of the buffer at lpClipList. When lpClipList is NULL, the variable at lpdwSize receives the required size of the buffer, in bytes.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_GENERIC
DDERR_INVALIDCLIPLIST
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_NOCLIPLIST
DDERR_REGIONTOOSMALL

Remarks

The RGNDATA structure used with this method has the following syntax:

typedef struct _RGNDATA {
    RGNDATAHEADER rdh;
    char          Buffer[1];
} RGNDATA;

The rdh member of the RGNDATA structure is an RGNDATAHEADER structure that has the following syntax:

typedef struct _RGNDATAHEADER {
    DWORD dwSize;
    DWORD iType;
    DWORD nCount;
    DWORD nRgnSize;
    RECT  rcBound;
} RGNDATAHEADER;

For more information about these structures, see the documentation in the Platform SDK.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.

See Also

IDirectDrawClipper::SetClipList


IDirectDrawClipper::GetHWnd

The IDirectDrawClipper::GetHWnd method retrieves the window handle previously associated with this DirectDrawClipper object by the IDirectDrawClipper::SetHWnd method.

HRESULT GetHWnd(
  HWND FAR *lphWnd
);

Parameters

lphWnd
Address of the window handle previously associated with this DirectDrawClipper object by the IDirectDrawClipper::SetHWnd method.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.

See Also

IDirectDrawClipper::SetHWnd


IDirectDrawClipper::Initialize

The IDirectDrawClipper::Initialize method initializes a DirectDrawClipper object that was created by using the CoCreateInstance COM function.

HRESULT Initialize(
  LPDIRECTDRAW lpDD,
  DWORD dwFlags
);

Parameters

lpDD
Address of the DirectDraw structure that represents the DirectDraw object. If this parameter is set to NULL, an independent DirectDrawClipper object is created (the equivalent of using the DirectDrawCreateClipper function).
dwFlags
This parameter is currently not used and must be set to 0.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_ALREADYINITIALIZED
DDERR_INVALIDPARAMS

This method is provided for compliance with the Component Object Model (COM) protocol. If DirectDrawCreateClipper or the IDirectDraw4::CreateClipper method was used to create the DirectDrawClipper object, this method returns DDERR_ALREADYINITIALIZED.

Remarks

For more information about using IDirectDrawClipper::Initialize with CoCreateInstance, see Creating DirectDrawClipper Objects with CoCreateInstance.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.

See Also

IUnknown::AddRef, IUnknown::QueryInterface, IUnknown::Release, IDirectDraw4::CreateClipper


IDirectDrawClipper::IsClipListChanged

The IDirectDrawClipper::IsClipListChanged method monitors the status of the clip list if a window handle is associated with a DirectDrawClipper object.

HRESULT IsClipListChanged(
  BOOL FAR *lpbChanged
);

Parameters

lpbChanged
Address of a variable that is set to TRUE if the clip list has changed.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.


IDirectDrawClipper::SetClipList

The IDirectDrawClipper::SetClipList method sets or deletes the clip list used by the IDirectDrawSurface4::Blt, IDirectDrawSurface4::BltBatch, and IDirectDrawSurface4::UpdateOverlay methods on surfaces to which the parent DirectDrawClipper object is attached.

HRESULT SetClipList(
  LPRGNDATA lpClipList,
  DWORD dwFlags
);

Parameters

lpClipList
Either an address to a valid RGNDATA structure or NULL. If there is an existing clip list associated with the DirectDrawClipper object and this value is NULL, the clip list will be deleted.
dwFlags
This parameter is currently not used and must be set to 0.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_CLIPPERISUSINGHWND
DDERR_INVALIDCLIPLIST
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_OUTOFMEMORY

Remarks

The clip list cannot be set if a window handle is already associated with the DirectDrawClipper object. Note that the BltFast method cannot clip.

The RGNDATA structure used with this method has the following syntax:

typedef struct _RGNDATA {
    RGNDATAHEADER rdh;
    char          Buffer[1];
} RGNDATA;

The rdh member of the RGNDATA structure is an RGNDATAHEADER structure that has the following syntax:

typedef struct _RGNDATAHEADER {
    DWORD dwSize;
    DWORD iType;
    DWORD nCount;
    DWORD nRgnSize;
    RECT  rcBound;
} RGNDATAHEADER;

For more information about these structures, see the documentation in the Platform Software Development Kit.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.

See Also

IDirectDrawClipper::GetClipList, IDirectDrawSurface4::Blt, IDirectDrawSurface4::BltFast, IDirectDrawSurface4::BltBatch, IDirectDrawSurface4::UpdateOverlay


IDirectDrawClipper::SetHWnd

The IDirectDrawClipper::SetHWnd method sets the window handle that the clipper object uses to obtain clipping information.

HRESULT SetHWnd(
  DWORD dwFlags,
  HWND hWnd
);

Parameters

dwFlags
This parameter is currently not used and must be set to 0.
hWnd
Window handle that obtains the clipping information.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_INVALIDCLIPLIST
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_OUTOFMEMORY

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.

See Also

IDirectDrawClipper::GetHWnd


IDirectDrawColorControl

The IDirectDrawColorControl interface allows you to get and set color controls:

Color controls | GetColorControls
 | SetColorControls

The IDirectDrawColorControl interface, like all COM interfaces, inherits the IUnknown interface methods. The IUnknown interface supports the following three methods:

IUnknown | AddRef
 | QueryInterface
 | Release

You can use the LPDIRECTDRAWCOLORCONTROL data type to declare a variable that contains a pointer to an IDirectDrawColorControl interface. The Ddraw.h header file declares these data types with the following code:

typedef struct IDirectDrawColorControl    FAR *LPDIRECTDRAWCOLORCONTROL;

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.


IDirectDrawColorControl::GetColorControls

The IDirectDrawColorControl::GetColorControls method returns the current color control settings associated with the specified overlay or primary surface. The dwFlags member of the DDCOLORCONTROL structure indicates which of the color control options are supported.

HRESULT GetColorControls(
  LPDDCOLORCONTROL lpColorControl
);

Parameters

lpColorControl
Address of the DDCOLORCONTROL structure that will receive the current control settings of the specified surface.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_UNSUPPORTED

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.

See Also

IDirectDrawColorControl::SetColorControls, Using Color Controls, Gamma and Color Controls


IDirectDrawColorControl::SetColorControls

The IDirectDrawColorControl::SetColorControls method sets the color control settings associated with the specified overlay or primary surface.

HRESULT SetColorControls(
  LPDDCOLORCONTROL lpColorControl
);

Parameters

lpColorControl
Address of the DDCOLORCONTROL structure containing the new values to be applied to the specified surface.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_UNSUPPORTED

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.

See Also

IDirectDrawColorControl::GetColorControls, Using Color Controls, Gamma and Color Controls


IDirectDrawGammaControl

Applications use the methods of the IDirectDrawGammaControl interface to adjust the red, green, and blue gamma ramp levels of the primary surface. This section is a reference to the methods of this interface. This interface is supported by DirectDrawSurface objects; you can retrieve a pointer to this interface by calling the IUnknown::QueryInterface method of a DirectDrawSurface object, specifying the IID_IDirectDrawGammaControl reference identifier.

For a conceptual overview, see Gamma and Color Controls.

Gamma ramps | GetGammaRamp
 | SetGammaRamp

The IDirectDrawGammaControl interface, like all COM interfaces, inherits the IUnknown interface methods. The IUnknown interface supports the following three methods:

IUnknown | AddRef
 | QueryInterface
 | Release

You can use the LPDIRECTDRAWGAMMACONTROL data type to declare a variable that contains a pointer to an IDirectDrawGammaControl interface. The Ddraw.h header file declares the data type with the following code:

typedef struct IDirectDrawGammaControl    FAR *LPDIRECTDRAWGAMMACONTROL;

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.


IDirectDrawGammaControl::GetGammaRamp

The IDirectDrawGammaControl::GetGammaRamp method retrieves the red, green, and blue gamma ramps for the primary surface.

HRESULT GetGammaRamp(
  DWORD  dwFlags,
  LPGAMMARAMP lpRampData
);

Parameters

dwFlags
Not currently used; set to 0.
lpRampData
Address of a DDGAMMARAMP structure that will be filled with the current red, green, and blue gamma ramps. Each array maps color values in the frame buffer to the color values that will be passed to the DAC (Digital-to-Analog Converter).

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_EXCEPTION
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.

See Also

IDirectDrawGammaControl::SetGammaRamp, Gamma and Color Controls


IDirectDrawGammaControl::SetGammaRamp

The IDirectDrawGammaControl::SetGammaRamp method retrieves the red, green, and blue gamma ramps for the primary surface.

HRESULT SetGammaRamp(
  DWORD  dwFlags,
  LPGAMMARAMP lpRampData
);

Parameters

dwFlags
Flag indicating if gamma calibration is desired. Set this parameter DDSGR_CALIBRATE to request that the calibrator adjust the gamma ramp according to the physical properties of the display, making the result identical on all systems. If calibration is not needed, set this parameter to 0.
lpRampData
Address of a DDGAMMARAMP structure that contains the new red, green, and blue gamma ramp entries. Each array maps color values in the frame buffer to the color values that will be passed to the DAC (Digital-to-Analog Converter).

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_EXCEPTION
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_OUTOFMEMORY

Remarks

Not all systems support gamma calibration. To determine if gamma calibration is supported, call IDirectDraw4::GetCaps, and examine the dwCaps2 member of the associated DDCAPS structure after the method returns. If the DDCAPS2_CANCALIBRATEGAMMA capability flag is present, then gamma calibration is supported.

Calibrating gamma ramps incurs some processing overhead, and should not be used frequently.

Including the DDSGR_CALIBRATE flag in the dwFlags parameter when running on systems that do not support gamma calibration will not cause this method to fail. The method succeeds, setting new gamma ramp values without calibration.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.

See Also

IDirectDrawGammaControl::GetGammaRamp, Gamma and Color Controls


IDirectDrawPalette

Applications use the methods of the IDirectDrawPalette interface to create DirectDrawPalette objects and work with system-level variables. This section is a reference to the methods of this interface. For a conceptual overview, see Palettes.

The methods of the IDirectDrawPalette interface can be organized into the following groups:

Allocating memory | Initialize
Palette capabilities | GetCaps
Palette entries | GetEntries
 | SetEntries

The IDirectDrawPalette interface, like all COM interfaces, inherits the IUnknown interface methods. The IUnknown interface supports the following three methods:

IUnknown | AddRef
 | QueryInterface
 | Release

You can use the LPDIRECTDRAWPALETTE data type to declare a variable that contains a pointer to an IDirectDrawPalette interface. The Ddraw.h header file declares the data type with the following code:

typedef struct IDirectDrawPalette    FAR *LPDIRECTDRAWPALETTE;

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.


IDirectDrawPalette::GetCaps

The IDirectDrawPalette::GetCaps method retrieves the capabilities of this palette object.

HRESULT GetCaps(
  LPDWORD lpdwCaps
);

Parameters

lpdwCaps
Flag from the dwPalCaps member of the DDCAPS structure that defines palette capabilities:
DDPCAPS_1BIT
DDPCAPS_2BIT
DDPCAPS_4BIT
DDPCAPS_8BIT
DDPCAPS_8BITENTRIES
DDPCAPS_ALPHA
DDPCAPS_ALLOW256
DDPCAPS_PRIMARYSURFACE
DDPCAPS_PRIMARYSURFACELEFT
DDPCAPS_VSYNC

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.


IDirectDrawPalette::GetEntries

The IDirectDrawPalette::GetEntries method queries palette values from a DirectDrawPalette object.

HRESULT GetEntries(
  DWORD dwFlags,
  DWORD dwBase,
  DWORD dwNumEntries,
  LPPALETTEENTRY lpEntries
);

Parameters

dwFlags
This parameter is currently not used and must be set to 0.
dwBase
Start of the entries that should be retrieved sequentially.
dwNumEntries
Number of palette entries that can fit in the address specified in lpEntries. The colors of each palette entry are returned in sequence, from the value of the dwStartingEntry parameter through the value of the dwCount parameter minus 1. (These parameters are set by IDirectDrawPalette::SetEntries.)
lpEntries
Address of the palette entries. The palette entries are 1 byte each if the DDPCAPS_8BITENTRIES flag is set and 4 bytes otherwise. Each field is a color description.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_NOTPALETTIZED

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.

See Also

IDirectDrawPalette::SetEntries


IDirectDrawPalette::Initialize

The IDirectDrawPalette::Initialize method initializes the DirectDrawPalette object.

HRESULT Initialize(
  LPDIRECTDRAW lpDD,
  DWORD dwFlags,
  LPPALETTEENTRY lpDDColorTable
);

Parameters

lpDD
Address of the DirectDraw structure that represents the DirectDraw object.
dwFlags and lpDDColorTable
These parameters are currently not used and must be set to 0.

Return Values

This method returns DDERR_ALREADYINITIALIZED.

This method is provided for compliance with the Component Object Model (COM) protocol. Because the DirectDrawPalette object is initialized when it is created, this method always returns DDERR_ALREADYINITIALIZED.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.

See Also

IUnknown::AddRef, IUnknown::QueryInterface, IUnknown::Release


IDirectDrawPalette::SetEntries

The IDirectDrawPalette::SetEntries method changes entries in a DirectDrawPalette object immediately.

HRESULT SetEntries(
  DWORD dwFlags,
  DWORD dwStartingEntry,
  DWORD dwCount,
  LPPALETTEENTRY lpEntries
);

Parameters

dwFlags
This parameter is currently not used and must be set to 0.
dwStartingEntry
First entry to be set.
dwCount
Number of palette entries to be changed.
lpEntries
Address of the palette entries. The palette entries are 1 byte each if the DDPCAPS_8BITENTRIES flag is set and 4 bytes otherwise. Each field is a color description.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_NOPALETTEATTACHED
DDERR_NOTPALETTIZED
DDERR_UNSUPPORTED

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.

See Also

IDirectDrawPalette::GetEntries, IDirectDrawSurface4::SetPalette


IDirectDrawSurface4

Applications use the methods of the IDirectDrawSurface4 interface to create DirectDrawSurface objects and work with system-level variables. This section is a reference to the methods of this interface. For a conceptual overview, see Surfaces.

The methods of the IDirectDrawSurface4 interface can be organized into the following groups:

Allocating memory | Initialize
 | IsLost
 | Restore
Attaching surfaces | AddAttachedSurface
 | DeleteAttachedSurface
 | EnumAttachedSurfaces
 | GetAttachedSurface
Blitting | Blt
 | BltBatch
 | BltFast
 | GetBltStatus
Color keying | GetColorKey
 | SetColorKey
Device contexts | GetDC
 | ReleaseDC
Flipping | Flip
 | GetFlipStatus
Locking surfaces | Lock
 | PageLock
 | PageUnlock
 | Unlock
Miscellaneous | GetDDInterface
Overlays | AddOverlayDirtyRect
 | EnumOverlayZOrders
 | GetOverlayPosition
 | SetOverlayPosition
 | UpdateOverlay
 | UpdateOverlayDisplay
 | UpdateOverlayZOrder
Private surface data | FreePrivateData
 | GetPrivateData
 | SetPrivateData
Surface capabilities | GetCaps
Surface clipper | GetClipper
 | SetClipper
Surface characteristics | ChangeUniquenessValue
 | GetPixelFormat
 | GetSurfaceDesc
 | GetUniquenessValue
 | SetSurfaceDesc
Surface palettes | GetPalette
 | SetPalette

The IDirectDrawSurface4 interface, like all COM interfaces, inherits the IUnknown interface methods. The IUnknown interface supports the following three methods:

IUnknown | AddRef
 | QueryInterface
 | Release

The IDirectDrawSurface4 interface extends the features of previous versions of the interface by offering methods that offer better surface management and ease of use. Note that many methods in this interface accept slightly different parameters than their counterparts in former versions of the interface. Wherever an IDirectDrawSurface3 interface method might accept a DDSURFACEDESC structure or an IDirectDrawSurface3 interface, the methods in IDirectDrawSurface4 accept a DDSURFACEDESC2 structure or an IDirectDrawSurface4 interface instead.

You can use the LPDIRECTDRAWSURFACE, LPDIRECTDRAWSURFACE2, LPDIRECTDRAWSURFACE3, or LPDIRECTDRAWSURFACE4 data types to declare variables that point to various DirectDrawSurface object interfaces. The Ddraw.h header file declares these data types with the following code:

typedef struct IDirectDrawSurface     FAR *LPDIRECTDRAWSURFACE;
typedef struct IDirectDrawSurface2    FAR *LPDIRECTDRAWSURFACE2;
typedef struct IDirectDrawSurface3    FAR *LPDIRECTDRAWSURFACE3;
typedef struct IDirectDrawSurface4    FAR *LPDIRECTDRAWSURFACE4;

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.


IDirectDrawSurface4::AddAttachedSurface

The IDirectDrawSurface4::AddAttachedSurface method attaches the specified surface to this surface.

HRESULT AddAttachedSurface(
  LPDIRECTDRAWSURFACE4 lpDDSAttachedSurface
);

Parameters

lpDDSAttachedSurface
Address of an IDirectDrawSurface4 interface for the surface to be attached.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_CANNOTATTACHSURFACE
DDERR_GENERIC
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_SURFACEALREADYATTACHED
DDERR_SURFACELOST
DDERR_WASSTILLDRAWING

Remarks

This method increments the reference count of the surface being attached. You can explicitly unattach the surface and decrement its reference count by using the IDirectDrawSurface4::DeleteAttachedSurface method. Unlike complex surfaces that you create with a single call to IDirectDraw4::CreateSurface, surfaces attached with this method are not automatically released. It is the application's responsibility to release such surfaces.

Possible attachments include z-buffers, alpha channels, and back buffers. Some attachments automatically break other attachments. For example, the 3-D z-buffer can be attached only to one back buffer at a time. Attachment is not bidirectional, and a surface cannot be attached to itself. Emulated surfaces (in system memory) cannot be attached to nonemulated surfaces. Unless one surface is a texture map, the two attached surfaces must be the same size. A flipping surface cannot be attached to another flipping surface of the same type; however, attaching two surfaces of different types is allowed. For example, a flipping z-buffer can be attached to a regular flipping surface. If a nonflipping surface is attached to another nonflipping surface of the same type, the two surfaces will become a flipping chain. If a nonflipping surface is attached to a flipping surface, it becomes part of the existing flipping chain. Additional surfaces can be added to this chain, and each call of the IDirectDrawSurface4::Flip method will advance one step through the surfaces.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.

See Also

IDirectDrawSurface4::DeleteAttachedSurface, IDirectDrawSurface4::EnumAttachedSurfaces


IDirectDrawSurface4::AddOverlayDirtyRect

The IDirectDrawSurface4::AddOverlayDirtyRect method is not currently implemented.

HRESULT AddOverlayDirtyRect(
  LPRECT lpRect
);

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.

See Also

IDirectDrawSurface4::UpdateOverlayDisplay


IDirectDrawSurface4::Blt

The IDirectDrawSurface4::Blt method performs a bit block transfer. This method does not support z-buffering or alpha blending (see alpha channel) during blit operations.

HRESULT Blt(
  LPRECT lpDestRect,
  LPDIRECTDRAWSURFACE4 lpDDSrcSurface,
  LPRECT lpSrcRect,
  DWORD dwFlags,
  LPDDBLTFX lpDDBltFx
);

Parameters

lpDestRect
Address of a RECT structure that defines the upper-left and lower-right points of the rectangle to blit to on the destination surface. If this parameter is NULL, the entire destination surface will be used.
lpDDSrcSurface
Address of an IDirectDrawSurface4 interface for the DirectDrawSurface object that is the source of the blit.
lpSrcRect
Address of a RECT structure that defines the upper-left and lower-right points of the rectangle to blit from on the source surface. If this parameter is NULL, the entire source surface will be used.
dwFlags
A combination of flags that determine the valid members of the associated DDBLTFX structure, specify color key information, or that request special behavior from the method. The following flags are defined.
Validation flags
DDBLT_COLORFILL
Uses the dwFillColor member of the DDBLTFX structure as the RGB color that fills the destination rectangle on the destination surface.
DDBLT_DDFX
Uses the dwDDFX member of the DDBLTFX structure to specify the effects to use for this blit.
DDBLT_DDROPS
Uses the dwDDROP member of the DDBLTFX structure to specify the raster operations (ROPS) that are not part of the Win32 API.
DDBLT_DEPTHFILL
Uses the dwFillDepth member of the DDBLTFX structure as the depth value with which to fill the destination rectangle on the destination z-buffer surface.
DDBLT_KEYDESTOVERRIDE
Uses the ddckDestColorkey member of the DDBLTFX structure as the color key for the destination surface.
DDBLT_KEYSRCOVERRIDE
Uses the ddckSrcColorkey member of the DDBLTFX structure as the color key for the source surface.
DDBLT_ROP
Uses the dwROP member of the DDBLTFX structure for the ROP for this blit. These ROPs are the same as those defined in the Win32 API.
DDBLT_ROTATIONANGLE
Uses the dwRotationAngle member of the DDBLTFX structure as the rotation angle (specified in 1/100th of a degree) for the surface.
Color key flags
DDBLT_KEYDEST
Uses the color key associated with the destination surface.
DDBLT_KEYSRC
Uses the color key associated with the source surface.
Behavior flags
DDBLT_ASYNC
Performs this blit asynchronously through the FIFO in the order received. If no room is available in the FIFO hardware, the call fails.
DDBLT_WAIT
Postpones the DDERR_WASSTILLDRAWING return value if the blitter is busy, and returns as soon as the blit can be set up or another error occurs.
Obsolete and unsupported flags
All "DDBLT_ALPHA" flag values.
Not currently implemented.
All "DDBLT_ZBUFFER" flag values
This method does not currently support z-aware blit operations. None of the flags beginning with "DDBLT_ZBUFFER" are supported in this release of DirectX 6.0.
lpDDBltFx
Address of the DDBLTFX structure.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_GENERIC
DDERR_INVALIDCLIPLIST
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_INVALIDRECT
DDERR_NOALPHAHW
DDERR_NOBLTHW
DDERR_NOCLIPLIST
DDERR_NODDROPSHW
DDERR_NOMIRRORHW
DDERR_NORASTEROPHW
DDERR_NOROTATIONHW
DDERR_NOSTRETCHHW
DDERR_NOZBUFFERHW
DDERR_SURFACEBUSY
DDERR_SURFACELOST
DDERR_UNSUPPORTED
DDERR_WASSTILLDRAWING

Remarks

This method is capable of synchronous or asynchronous blits (the default behavior), either display memory to display memory, display memory to system memory, system memory to display memory, or system memory to system memory. The blits can be performed by using source color keys, and destination color keys. Arbitrary stretching or shrinking will be performed if the source and destination rectangles are not the same size.

Typically, IDirectDrawSurface4::Blt returns immediately with an error if the blitter is busy and the blit could not be set up. Specify the DDBLT_WAIT flag to request a synchronous blit. When you include the DDBLT_WAIT flag, the method waits until the blit can be set up or another error occurs before it returns.

Note that RECT structures are defined so that the right and bottom members are exclusive—therefore, right minus left equals the width of the rectangle, not one less than the width.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.


IDirectDrawSurface4::BltBatch

The IDirectDrawSurface4::BltBatch method is not currently implemented.

HRESULT BltBatch(
  LPDDBLTBATCH lpDDBltBatch,
  DWORD dwCount,
  DWORD dwFlags
);

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.


IDirectDrawSurface4::BltFast

The IDirectDrawSurface4::BltFast method performs a source copy blit or transparent blit by using a source color key or destination color key.

HRESULT BltFast(
  DWORD dwX,
  DWORD dwY,
  LPDIRECTDRAWSURFACE4 lpDDSrcSurface,
  LPRECT lpSrcRect,
  DWORD dwTrans
);

Parameters

dwX and dwY
The x- and y-coordinates to blit to on the destination surface.
lpDDSrcSurface
Address of an IDirectDrawSurface4 interface for the DirectDrawSurface object that is the source of the blit.
lpSrcRect
Address of a RECT structure that defines the upper-left and lower-right points of the rectangle to blit from on the source surface.
dwTrans
Type of transfer.
DDBLTFAST_DESTCOLORKEY
Specifies a transparent blit that uses the destination's color key.
DDBLTFAST_NOCOLORKEY
Specifies a normal copy blit with no transparency.
DDBLTFAST_SRCCOLORKEY
Specifies a transparent blit that uses the source's color key.
DDBLTFAST_WAIT
Postpones the DDERR_WASSTILLDRAWING message if the blitter is busy, and returns as soon as the blit can be set up or another error occurs.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_EXCEPTION
DDERR_GENERIC
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_INVALIDRECT
DDERR_NOBLTHW
DDERR_SURFACEBUSY
DDERR_SURFACELOST
DDERR_UNSUPPORTED
DDERR_WASSTILLDRAWING

Remarks

This method always attempts an asynchronous blit if it is supported by the hardware.

This method works only on display memory surfaces and cannot clip when blitting. If you use this method on a surface with an attached clipper, the call will fail and the method will return DDERR_UNSUPPORTED.

The software implementation of IDirectDrawSurface4::BltFast is 10 percent faster than the IDirectDrawSurface4::Blt method. However, there is no speed difference between the two if display hardware is being used.

Typically, IDirectDrawSurface4::BltFast returns immediately with an error if the blitter is busy and the blit cannot be set up. You can use the DDBLTFAST_WAIT flag, however, if you want this method to not return until either the blit can be set up or another error occurs.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.


IDirectDrawSurface4::ChangeUniquenessValue

The IDirectDrawSurface4::ChangeUniquenessValue method manually updates the uniqueness value for this surface.

HRESULT ChangeUniquenessValue();

Parameters

None.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_EXCEPTION
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS

Remarks

DirectDraw automatically updates uniqueness values whenever the contents of a surface change.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.

See Also

IDirectDrawSurface4::GetUniquenessValue, Surface Uniqueness Values


IDirectDrawSurface4::DeleteAttachedSurface

The IDirectDrawSurface4::DeleteAttachedSurface method detaches two attached surfaces.

HRESULT DeleteAttachedSurface(
  DWORD dwFlags,
  LPDIRECTDRAWSURFACE4 lpDDSAttachedSurface
);

Parameters

dwFlags
This parameter is currently not used and must be set to 0.
lpDDSAttachedSurface
Address of the IDirectDrawSurface4 interface for the DirectDrawSurface object to be detached. If this parameter is NULL, all attached surfaces are detached.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_CANNOTDETACHSURFACE
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_SURFACELOST
DDERR_SURFACENOTATTACHED

Remarks

This method decrements the reference count of the surface being detached. If the reference count of the surface being detached reaches zero, it is lost and removed from memory.

Implicit attachments, those formed by DirectDraw rather than the IDirectDrawSurface4::AddAttachedSurface method, cannot be detached. Detaching surfaces from a flipping chain can alter other surfaces in the chain. If a front buffer is detached from a flipping chain, the next surface in the chain becomes the front buffer, and the following surface becomes the back buffer. If a back buffer is detached from a chain, the following surface becomes a back buffer. If a plain surface is detached from a chain, the chain simply becomes shorter. If a flipping chain has only two surfaces and they are detached, the chain is destroyed and both surfaces return to their previous designations.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.

See Also

IDirectDrawSurface4::Flip


IDirectDrawSurface4::EnumAttachedSurfaces

The IDirectDrawSurface4::EnumAttachedSurfaces method enumerates all the surfaces attached to a given surface.

HRESULT EnumAttachedSurfaces(
  LPVOID lpContext,
  LPDDENUMSURFACESCALLBACK2 lpEnumSurfacesCallback
);

Parameters

lpContext
Address of the application-defined structure that is passed to the enumeration member every time it is called.
lpEnumSurfacesCallback
Address of the EnumSurfacesCallback2 function that will be called for each surface that is attached to this surface.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_SURFACELOST

Remarks

This method enumerates only those surfaces that are directly attached to this surface. For example, in a flipping chain of three or more surfaces, only one surface will be enumerated, because each surface is attached only to the next surface in the flipping chain. In such a configuration, you can call EnumAttachedSurfaces on each successive surface to walk the entire flipping chain.

This method differs from its counterparts in previous interface versions in that it accepts a pointer to an EnumSurfacesCallback2 function, rather than an EnumSurfacesCallback function.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.


IDirectDrawSurface4::EnumOverlayZOrders

The IDirectDrawSurface4::EnumOverlayZOrders method enumerates the overlay surfaces on the specified destination. The overlays can be enumerated in front-to-back or back-to-front order.

HRESULT EnumOverlayZOrders(
  DWORD dwFlags,
  LPVOID lpContext,
  LPDDENUMSURFACESCALLBACK2 lpfnCallback
);

Parameters

dwFlags
One of the following flags:
DDENUMOVERLAYZ_BACKTOFRONT
Enumerates overlays back to front.
DDENUMOVERLAYZ_FRONTTOBACK
Enumerates overlays front to back.
lpContext
Address of the user-defined context that will be passed to the callback function for each overlay surface.
lpfnCallback
Address of the EnumSurfacesCallback2 callback function that will be called for each surface being overlaid on this surface.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS

Remarks

This method differs from its counterparts in previous interface versions in that it accepts a pointer to an EnumSurfacesCallback2 function, rather than an EnumSurfacesCallback function.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.


IDirectDrawSurface4::Flip

The IDirectDrawSurface4::Flip method makes the surface memory associated with the DDSCAPS_BACKBUFFER surface become associated with the front-buffer surface.

HRESULT Flip(
  LPDIRECTDRAWSURFACE4 lpDDSurfaceTargetOverride,
  DWORD dwFlags
);

Parameters

lpDDSurfaceTargetOverride
Address of the IDirectDrawSurface4 interface for an arbitrary surface in the flipping chain. The default for this parameter is NULL, in which case DirectDraw cycles through the buffers in the order they are attached to each other. If this parameter is not NULL, DirectDraw flips to the specified surface instead of the next surface in the flipping chain. The method fails if the specified surface is not a member of the flipping chain.
dwFlags
Flags specifying flip options.
DDFLIP_EVEN
For use only when displaying video in an overlay surface. The new surface contains data from the even field of a video signal. This flag cannot be used with the DDFLIP_ODD flag.
DDFLIP_INTERVAL2
DDFLIP_INTERVAL3
DDFLIP_INTERVAL4
These flags indicate how many vertical retraces to wait between each flip. The default is 1. DirectDraw will return DERR_WASSTILLDRAWING for each surface involved in the flip until the specified number of vertical retraces has occurred. If DDFLIP_INTERVAL2 is set, DirectDraw will flip on every second vertical sync; if DDFLIP_INTERVAL3, on every third sync; and if DDFLIP_INTERVAL4, on every fourth sync.

These flags are effective only if DDCAPS2_FLIPINTERVAL is set in the DDCAPS structure returned for the device.

DDFLIP_NOVSYNC
Causes DirectDraw to perform the physical flip as close as possible to the next scan line. Subsequent operations involving the two flipped surfaces will not check to see if the physical flip has finished—that is, they will not return DDERR_WASSTILLDRAWING for that reason (but may for other reasons). This allows an application to perform flips at a higher frequency than the monitor refresh rate, but may introduce visible artifacts.

If DDCAPS2_FLIPNOVSYNC is not set in the DDCAPS structure returned for the device, DDFLIP_NOVSYNC has no effect.

DDFLIP_ODD
For use only when displaying video in an overlay surface. The new surface contains data from the odd field of a video signal. This flag cannot be used with the DDFLIP_EVEN flag.
DDFLIP_WAIT
Typically, if the flip cannot be set up because the state of the display hardware is not appropriate, the DDERR_WASSTILLDRAWING error returns immediately and no flip occurs. Setting this flag causes the method to continue trying to flip if it receives the DDERR_WASSTILLDRAWING error from the HAL. The method does not return until the flipping operation has been successfully set up, or another error, such as DDERR_SURFACEBUSY, is returned.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_GENERIC
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_NOFLIPHW
DDERR_NOTFLIPPABLE
DDERR_SURFACEBUSY
DDERR_SURFACELOST
DDERR_UNSUPPORTED
DDERR_WASSTILLDRAWING

Remarks

This method can be called only for a surface that has the DDSCAPS_FLIP and DDSCAPS_FRONTBUFFER capabilities. The display memory previously associated with the front buffer is associated with the back buffer.

The lpDDSurfaceTargetOverride parameter is used in rare cases when the back buffer is not the buffer that should become the front buffer. Typically this parameter is NULL.

The IDirectDrawSurface4::Flip method will always be synchronized with the vertical blank. If the surface has been assigned to a video port, this method updates the visible overlay surface and the video port's target surface.

For more information, see Flipping Surfaces.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.

See Also

IDirectDrawSurface4::GetFlipStatus


IDirectDrawSurface4::FreePrivateData

The IDirectDrawSurface4::FreePrivateData method frees the specified private data associated with this surface.

HRESULT FreePrivateData(
  REFGUID guidTag,
);

Parameters

guidTag
Reference to (C++) or address of (C) the globally unique identifier that identifies the private data to be freed.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_NOTFOUND

Remarks

DirectDraw calls this method automatically when a surface is released.

If the private data was set by using the DDSPD_IUNKNOWNPOINTER flag, this method calls the IUnknown::Release method on the associated interface.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.

See Also

IDirectDrawSurface4::GetPrivateData, IDirectDrawSurface4::SetPrivateData


IDirectDrawSurface4::GetAttachedSurface

The IDirectDrawSurface4::GetAttachedSurface method obtains the attached surface that has the specified capabilities and increments the reference count of the retrieved interface.

HRESULT GetAttachedSurface(
  LPDDSCAPS2 lpDDSCaps,
  LPDIRECTDRAWSURFACE4 FAR *lplpDDAttachedSurface
);

Parameters

lpDDSCaps
Address of a DDSCAPS2 structure that contains the hardware capabilities of the surface.
lplpDDAttachedSurface
Address of a variable that will contain a pointer to the retrieved surface's IDirectDrawSurface4 interface. The retrieved surface is the one that matches the description according to the lpDDSCaps parameter.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_NOTFOUND
DDERR_SURFACELOST

Remarks

Attachments are used to connect multiple DirectDrawSurface objects into complex structures, like the ones needed to support 3-D page flipping with z-buffers. This method fails if more than one surface is attached that matches the capabilities requested. In this case, the application must use the IDirectDrawSurface4::EnumAttachedSurfaces method to obtain the attached surfaces.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.


IDirectDrawSurface4::GetBltStatus

The IDirectDrawSurface4::GetBltStatus method obtains the blitter status.

HRESULT GetBltStatus(
  DWORD dwFlags
);

Parameters

dwFlags
One of the following flags:
DDGBS_CANBLT
Inquires whether a blit involving this surface can occur immediately, and returns DD_OK if the blit can be completed.
DDGBS_ISBLTDONE
Inquires whether the blit is done, and returns DD_OK if the last blit on this surface has completed.

Return Values

If the method succeeds, that means a blitter is present, the return value is DD_OK.

If the method fails, the return value is DDERR_WASSTILLDRAWING if the blitter is busy, DDERR_NOBLTHW if there is no blitter, or one of the following error values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_NOBLTHW
DDERR_SURFACEBUSY
DDERR_SURFACELOST
DDERR_UNSUPPORTED
DDERR_WASSTILLDRAWING

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.


IDirectDrawSurface4::GetCaps

The IDirectDrawSurface4::GetCaps method retrieves the capabilities of the surface. These capabilities are not necessarily related to the capabilities of the display device.

HRESULT GetCaps(
  LPDDSCAPS2 lpDDSCaps
);

Parameters

lpDDSCaps
Address of a DDSCAPS2 structure that will be filled with the hardware capabilities of the surface.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS

Remarks

This method differs from its counterpart in the IDirectDrawSurface3 interface in that it accepts a pointer to a DDSCAPS2 structure rather than the legacy DDSCAPS structure.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.


IDirectDrawSurface4::GetClipper

The IDirectDrawSurface4::GetClipper method retrieves the DirectDrawClipper object associated with this surface and increments the reference count of the returned clipper.

HRESULT GetClipper(
  LPDIRECTDRAWCLIPPER FAR *lplpDDClipper
);

Parameters

lplpDDClipper
Address of a pointer to the DirectDrawClipper object associated with the surface.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_NOCLIPPERATTACHED

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.

See Also

IDirectDrawSurface4::SetClipper


IDirectDrawSurface4::GetColorKey

The IDirectDrawSurface4::GetColorKey method retrieves the color key value for the DirectDrawSurface object.

HRESULT GetColorKey(
  DWORD dwFlags,
  LPDDCOLORKEY lpDDColorKey
);

Parameters

dwFlags
Determines which color key is requested.
DDCKEY_DESTBLT
Set if the structure specifies a color key or color space to be used as a destination color key for blit operations.
DDCKEY_DESTOVERLAY
Set if the structure specifies a color key or color space to be used as a destination color key for overlay operations.
DDCKEY_SRCBLT
Set if the structure specifies a color key or color space to be used as a source color key for blit operations.
DDCKEY_SRCOVERLAY
Set if the structure specifies a color key or color space to be used as a source color key for overlay operations.
lpDDColorKey
Address of the DDCOLORKEY structure that will be filled with the current values for the specified color key of the DirectDrawSurface object.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_NOCOLORKEY
DDERR_NOCOLORKEYHW
DDERR_SURFACELOST
DDERR_UNSUPPORTED

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.

See Also

IDirectDrawSurface4::SetColorKey


IDirectDrawSurface4::GetDC

The IDirectDrawSurface4::GetDC method creates a GDI-compatible handle of a device context for the surface.

HRESULT GetDC(
  HDC FAR *lphDC
);

Parameters

lphDC
Address for the returned handle to a device context.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_DCALREADYCREATED
DDERR_GENERIC
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_INVALIDSURFACETYPE
DDERR_SURFACELOST
DDERR_UNSUPPORTED
DDERR_WASSTILLDRAWING

Remarks

This method uses an internal version of the IDirectDrawSurface4::Lock method to lock the surface. The surface remains locked until the IDirectDrawSurface4::ReleaseDC method is called.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.

See Also

IDirectDrawSurface4::Lock


IDirectDrawSurface4::GetDDInterface

The IDirectDrawSurface4::GetDDInterface method retrieves an interface to the DirectDraw object that was used to create the surface.

HRESULT GetDDInterface(
  LPVOID FAR *lplpDD
);

Parameters

lplpDD
Address of a variable that will be filled with a valid interface pointer if the call succeeds. Cast this pointer to an IUnknown interface pointer, then query for the desired DirectDraw interface.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS

Remarks

This method was not implemented in the IDirectDraw interface.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.


IDirectDrawSurface4::GetFlipStatus

The IDirectDrawSurface4::GetFlipStatus method indicates whether the surface has finished its flipping process.

HRESULT GetFlipStatus(
  DWORD dwFlags
);

Parameters

dwFlags
One of the following flags:
DDGFS_CANFLIP
Inquires whether this surface can be flipped immediately and returns DD_OK if the flip can be completed.
DDGFS_ISFLIPDONE
Inquires whether the flip has finished and returns DD_OK if the last flip on this surface has completed.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value is DDERR_WASSTILLDRAWING if the surface has not finished its flipping process, or one of the following error values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_INVALIDSURFACETYPE
DDERR_SURFACEBUSY
DDERR_SURFACELOST
DDERR_UNSUPPORTED

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.

See Also

IDirectDrawSurface4::Flip


IDirectDrawSurface4::GetOverlayPosition

Given a visible, active overlay surface (DDSCAPS_OVERLAY flag set), the IDirectDrawSurface4::GetOverlayPosition method returns the display coordinates of the surface.

HRESULT GetOverlayPosition(
  LPLONG lplX,
  LPLONG lplY
);

Parameters

lplX and lplY
Addresses of the x- and y-display coordinates.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_GENERIC
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_INVALIDPOSITION
DDERR_NOOVERLAYDEST
DDERR_NOTAOVERLAYSURFACE
DDERR_OVERLAYNOTVISIBLE
DDERR_SURFACELOST

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.

See Also

IDirectDrawSurface4::SetOverlayPosition, IDirectDrawSurface4::UpdateOverlay


IDirectDrawSurface4::GetPalette

The IDirectDrawSurface4::GetPalette method retrieves the DirectDrawPalette object associated with this surface and increments the reference count of the returned palette.

HRESULT GetPalette(
  LPDIRECTDRAWPALETTE FAR *lplpDDPalette
);

Parameters

lplpDDPalette
Address of a variable that will be filled with a pointer to the palette object's IDirectDrawPalette interface.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_GENERIC
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_NOEXCLUSIVEMODE
DDERR_NOPALETTEATTACHED
DDERR_SURFACELOST
DDERR_UNSUPPORTED

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.

See Also

IDirectDrawSurface4::SetPalette


IDirectDrawSurface4::GetPixelFormat

The IDirectDrawSurface4::GetPixelFormat method retrieves the color and pixel format of the surface.

HRESULT GetPixelFormat(
  LPDDPIXELFORMAT lpDDPixelFormat
);

Parameters

lpDDPixelFormat
Address of the DDPIXELFORMAT structure that will be filled with a detailed description of the current pixel and color space format of the surface.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_INVALIDSURFACETYPE

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.


IDirectDrawSurface4::GetPrivateData

The IDirectDrawSurface4::GetPrivateData method copies the private data associated with the surface to a provided buffer.

HRESULT GetPrivateData(
  REFGUID guidTag,
  LPVOID  lpBuffer,
  LPDWORD lpcbBufferSize
);

Parameters

guidTag
Reference to (C++) or address of (C) the globally unique identifier that identifies the private data to be retrieved.
lpBuffer
Address of a previously allocated buffer that will be filled with the requested private data if the call succeeds. The application calling this method is responsible for allocating and releasing this buffer.
lpcbBufferSize
Size of the buffer at lpBuffer, in bytes. If this value is less than the actual size of the private data (such as zero), the method sets this parameter to the required buffer size, and the method returns DDERR_MOREDATA.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_EXPIRED
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_MOREDATA
DDERR_NOTFOUND
DDERR_OUTOFMEMORY

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.

See Also

IDirectDrawSurface4::SetPrivateData, IDirectDrawSurface4::FreePrivateData


IDirectDrawSurface4::GetSurfaceDesc

The IDirectDrawSurface4::GetSurfaceDesc method retrieves a description of the surface in its current condition.

HRESULT GetSurfaceDesc(
  LPDDSURFACEDESC2 lpDDSurfaceDesc
);

Parameters

lpDDSurfaceDesc
Address of a DDSURFACEDESC2 structure that will be filled with the current description of this surface. You need only initialize this structure's dwSize member to the size, in bytes, of the structure prior to the call; no other preparation is required.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.

See Also

DDSURFACEDESC, DDSURFACEDESC2


IDirectDrawSurface4::GetUniquenessValue

The IDirectDrawSurface4::GetUniquenessValue method retrieves the current uniqueness value for this surface.

HRESULT GetUniquenessValue(
  LPDWORD lpValue,
);

Parameters

lpValue
Address of a variable that will be filled with the surface's current uniqueness value, if the call succeeds.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS

Remarks

The only defined uniqueness value is 0, to indicate that the surface is likely to be changing beyond DirectDraw's control. Other uniqueness values are only significant if they differ from a previously cached uniqueness value. If the current value is different than a cached value, then the contents of the surface have changed.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.

See Also

IDirectDrawSurface4::ChangeUniquenessValue, Surface Uniqueness Values


IDirectDrawSurface4::Initialize

The IDirectDrawSurface4::Initialize method initializes a DirectDrawSurface object.

HRESULT Initialize(
  LPDIRECTDRAW lpDD,
  LPDDSURFACEDESC2 lpDDSurfaceDesc
);

Parameters

lpDD
Address of the DirectDraw structure that represents the DirectDraw object.
lpDDSurfaceDesc
Address of a DDSURFACEDESC2 structure that will be filled with the relevant details about the surface.

Return Values

The method returns DDERR_ALREADYINITIALIZED.

Remarks

This method is provided for compliance with the Component Object Model (COM) protocol. Because the DirectDrawSurface object is initialized when it is created, this method always returns DDERR_ALREADYINITIALIZED.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.

See Also

IUnknown::AddRef, IUnknown::QueryInterface, IUnknown::Release


IDirectDrawSurface4::IsLost

The IDirectDrawSurface4::IsLost method determines if the surface memory associated with a DirectDrawSurface object has been freed.

HRESULT IsLost();

Parameters

None.

Return Values

If the method succeeds, the return value is DD_OK because the memory has not been freed.

If the method fails, the return value may be one of the following error values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_SURFACELOST

You can use this method to determine when you need to reallocate surface memory. When a DirectDrawSurface object loses its surface memory, most methods return DDERR_SURFACELOST and perform no other action.

Remarks

Surfaces can lose their memory when the mode of the display card is changed, or when an application receives exclusive access to the display card and frees all of the surface memory currently allocated on the display card.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.

See Also

IDirectDrawSurface4::Restore, Losing and Restoring Surfaces


IDirectDrawSurface4::Lock

The IDirectDrawSurface4::Lock method obtains a pointer to the surface memory.

HRESULT Lock(
  LPRECT lpDestRect,
  LPDDSURFACEDESC2 lpDDSurfaceDesc,
  DWORD dwFlags,
  HANDLE hEvent
);

Parameters

lpDestRect
Address of a RECT structure that identifies the region of surface that is being locked. If NULL, the entire surface will be locked.
lpDDSurfaceDesc
Address of a DDSURFACEDESC2 structure that will be filled with the relevant details about the surface.
dwFlags
DDLOCK_EVENT
This flag is not currently implemented.
DDLOCK_NOSYSLOCK
Do not take the Win16Mutex (also known as Win16Lock). This flag is ignored when locking the primary surface.
DDLOCK_READONLY
Indicates that the surface being locked will only be read.
DDLOCK_SURFACEMEMORYPTR
Indicates that a valid memory pointer to the top of the specified rectangle 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.
hEvent
This parameter is not used and must be set to NULL.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_OUTOFMEMORY
DDERR_SURFACEBUSY
DDERR_SURFACELOST
DDERR_WASSTILLDRAWING

Remarks

For more information on using this method, see Accessing Surface Memory Directly.

After retrieving a surface memory pointer, you can access the surface memory until a corresponding IDirectDrawSurface4::Unlock method is called. When the surface is unlocked, the pointer to the surface memory is invalid.

Do not call DirectDraw blit functions to blit from a locked region of a surface. If you do, the blit returns either DDERR_SURFACEBUSY or DDERR_LOCKEDSURFACES. Additionally, GDI blit functions will silently fail when used on a locked video memory surface.

Unless you include the DDLOCK_NOSYSLOCK flag, this method causes DirectDraw to hold the Win16Mutex (also known as Win16Lock) until you call the IDirectDrawSurface4::Unlock method. GUI debuggers cannot operate while the Win16Mutex is held.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.

See Also

IDirectDrawSurface4::Unlock, IDirectDrawSurface4::GetDC, IDirectDrawSurface4::ReleaseDC


IDirectDrawSurface4::PageLock

The IDirectDrawSurface4::PageLock method prevents a system-memory surface from being paged out while a blit operation using direct memory access (DMA) transfers to or from system memory is in progress.

HRESULT PageLock(
  DWORD dwFlags
);

Parameters

dwFlags
This parameter is currently not used and must be set to 0.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_CANTPAGELOCK
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_SURFACELOST

Remarks

You must call this method to make use of DMA support. If you do not, the blit occurs using software emulation. For more information, see Using DMA.

The performance of the operating system could be negatively affected if too much memory is locked.

A lock count is maintained for each surface and is incremented each time IDirectDrawSurface4::PageLock is called for that surface. The count is decremented when IDirectDrawSurface4::PageUnlock is called. When the count reaches 0, the memory is unlocked and can then be paged by the operating system.

This method works only on system-memory surfaces; it will not page lock a display-memory surface or an emulated primary surface. If an application calls this method on a display memory surface, the method will do nothing except return DD_OK.

This method was not implemented in the IDirectDraw interface.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.

See Also

IDirectDrawSurface4::PageUnlock


IDirectDrawSurface4::PageUnlock

The IDirectDrawSurface4::PageUnlock method unlocks a system-memory surface, allowing it to be paged out.

HRESULT PageUnlock(
  DWORD dwFlags
);

Parameters

dwFlags
This parameter is currently not used and must be set to 0.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_CANTPAGEUNLOCK
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_NOTPAGELOCKED
DDERR_SURFACELOST

Remarks

A lock count is maintained for each surface and is incremented each time IDirectDrawSurface4::PageLock is called for that surface. The count is decremented when IDirectDrawSurface4::PageUnlock is called. When the count reaches 0, the memory is unlocked and can then be paged by the operating system.

This method works only on system-memory surfaces; it will not page unlock a display-memory surface or an emulated primary surface. If an application calls this method on a display-memory surface, this method will do nothing except return DD_OK.

This method was not implemented in the IDirectDraw interface.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.

See Also

IDirectDrawSurface4::PageLock


IDirectDrawSurface4::ReleaseDC

The IDirectDrawSurface4::ReleaseDC method releases the handle of a device context previously obtained by using the IDirectDrawSurface4::GetDC method.

HRESULT ReleaseDC(
  HDC hDC
);

Parameters

hDC
Handle to a device context previously obtained by IDirectDrawSurface4::GetDC.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_GENERIC
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_SURFACELOST
DDERR_UNSUPPORTED

Remarks

This method also unlocks the surface previously locked when the IDirectDrawSurface4::GetDC method was called.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.

See Also

IDirectDrawSurface4::GetDC


IDirectDrawSurface4::Restore

The IDirectDrawSurface4::Restore method restores a surface that has been lost. This occurs when the surface memory associated with the DirectDrawSurface object has been freed.

HRESULT Restore();

Parameters

None.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_GENERIC
DDERR_IMPLICITLYCREATED
DDERR_INCOMPATIBLEPRIMARY
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_NOEXCLUSIVEMODE
DDERR_OUTOFMEMORY
DDERR_UNSUPPORTED
DDERR_WRONGMODE

Remarks

This method restores the memory allocated for a surface, but doesn't reload any bitmaps that may have existed in the surface before it was lost. For more information, see Losing and Restoring Surfaces.

Surfaces can be lost because the mode of the display card was changed or because an application received exclusive access to the display card and freed all of the surface memory currently allocated on the card. When a DirectDrawSurface object loses its surface memory, many methods will return DDERR_SURFACELOST and perform no other function. The IDirectDrawSurface4::Restore method will reallocate surface memory and reattach it to the DirectDrawSurface object.

A single call to this method will restore a DirectDrawSurface object's associated implicit surfaces (back buffers, and so on). An attempt to restore an implicitly created surface will result in an error. IDirectDrawSurface4::Restore will not work across explicit attachments created by using the IDirectDrawSurface4::AddAttachedSurface method—each of these surfaces must be restored individually.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.

See Also

IDirectDrawSurface4::IsLost


IDirectDrawSurface4::SetClipper

The IDirectDrawSurface4::SetClipper method attaches a clipper object to or deletes one from a surface.

HRESULT SetClipper(
  LPDIRECTDRAWCLIPPER lpDDClipper
);

Parameters

lpDDClipper
Address of the IDirectDrawClipper interface for the DirectDrawClipper object that will be attached to the DirectDrawSurface object. If this parameter is NULL, the current DirectDrawClipper object will be detached.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_INVALIDSURFACETYPE
DDERR_NOCLIPPERATTACHED

Remarks

When setting a clipper to a surface for the first time, this method increments the clipper's reference count; subsequent calls to do not affect the clipper's reference count. If you pass NULL as the lpDDClipper parameter, the clipper is removed from the surface, and the clipper's reference count is decremented. If you do not delete the clipper, the surface will automatically release its reference to the clipper when the surface itself is released. According to COM rules, your application is responsible for releasing any references it holds to the clipper when the object is no longer needed.

This method is primarily used by surfaces that are being overlaid on or blitted to the primary surface. However, it can be used on any surface. After a DirectDrawClipper object has been attached and a clip list is associated with it, the DirectDrawClipper object will be used for the IDirectDrawSurface4::Blt, IDirectDrawSurface4::BltBatch, and IDirectDrawSurface4::UpdateOverlay operations involving the parent DirectDrawSurface object. This method can also detach a DirectDrawSurface object's current DirectDrawClipper object.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.

See Also

IDirectDrawSurface4::GetClipper


IDirectDrawSurface4::SetColorKey

The IDirectDrawSurface4::SetColorKey method sets the color key value for the DirectDrawSurface object if the hardware supports color keys on a per surface basis.

HRESULT SetColorKey(
  DWORD dwFlags,
  LPDDCOLORKEY lpDDColorKey
);

Parameters

dwFlags
Determines which color key is requested.
DDCKEY_COLORSPACE
Set if the structure contains a color space. Not set if the structure contains a single color key.
DDCKEY_DESTBLT
Set if the structure specifies a color key or color space to be used as a destination color key for blit operations.
DDCKEY_DESTOVERLAY
Set if the structure specifies a color key or color space to be used as a destination color key for overlay operations.
DDCKEY_SRCBLT
Set if the structure specifies a color key or color space to be used as a source color key for blit operations.
DDCKEY_SRCOVERLAY
Set if the structure specifies a color key or color space to be used as a source color key for overlay operations.
lpDDColorKey
Address of the DDCOLORKEY structure that contains the new color key values for the DirectDrawSurface object. This value can be NULL to remove a previously set color key.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_GENERIC
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_INVALIDSURFACETYPE
DDERR_NOOVERLAYHW
DDERR_NOTAOVERLAYSURFACE
DDERR_SURFACELOST
DDERR_UNSUPPORTED
DDERR_WASSTILLDRAWING

Remarks

For transparent blits and overlays, you should set destination color on the destination surface and source color on the source surface.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.

See Also

IDirectDrawSurface4::GetColorKey


IDirectDrawSurface4::SetOverlayPosition

The IDirectDrawSurface4::SetOverlayPosition method changes the display coordinates of an overlay surface.

HRESULT SetOverlayPosition(
  LONG lX,
  LONG lY
);

Parameters

lX and lY
New x- and y-display coordinates.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_GENERIC
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_INVALIDPOSITION
DDERR_NOOVERLAYDEST
DDERR_NOTAOVERLAYSURFACE
DDERR_OVERLAYNOTVISIBLE
DDERR_SURFACELOST
DDERR_UNSUPPORTED

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.

See Also

IDirectDrawSurface4::GetOverlayPosition, IDirectDrawSurface4::UpdateOverlay


IDirectDrawSurface4::SetPalette

The IDirectDrawSurface4::SetPalette method attaches a palette object to (or detaches one from) a surface. The surface uses this palette for all subsequent operations. The palette change takes place immediately, without regard to refresh timing.

HRESULT SetPalette(
  LPDIRECTDRAWPALETTE lpDDPalette
);

Parameters

lpDDPalette
Address of the IDirectDrawPalette interface for the palette object to be used with this surface. If this parameter is NULL, the current palette will be detached.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_GENERIC
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_INVALIDPIXELFORMAT
DDERR_INVALIDSURFACETYPE
DDERR_NOEXCLUSIVEMODE
DDERR_NOPALETTEATTACHED
DDERR_NOPALETTEHW
DDERR_NOT8BITCOLOR
DDERR_SURFACELOST
DDERR_UNSUPPORTED

Remarks

When setting a palette to a surface for the first time, this method increments the palette's reference count; subsequent calls to do not affect the palette's reference count. If you pass NULL as the lpDDPalette parameter, the palette is removed from the surface, and the palette's reference count is decremented. If you do not delete the palette, the surface will automatically release its reference to the palette when the surface itself is released. According to COM rules, your application is responsible for releasing any references it holds to the palette when the object is no longer needed.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.

See Also

IDirectDrawSurface4::GetPalette, IDirectDraw4::CreatePalette


IDirectDrawSurface4::SetPrivateData

The IDirectDrawSurface4::SetPrivateData method associates data with the surface that is intended for use by the application, not by DirectDraw. Data is passed by value, and multiple sets of data can be associated with a single surface.

HRESULT SetPrivateData(
  REFGUID guidTag,
  LPVOID  lpData,
  DWORD   cbSize,
  DWORD   dwFlags
);

Parameters

guidTag
Reference to (C++) or address of (C) the globally unique identifier that identifies the private data to be set.
lpData
Address of a buffer that contains the data to be associated with the surface.
cbSize
Size of the buffer at lpData, in bytes.
dwFlags
Flags describing the type of data being passed, or requesting that the data be invalidated when the surface changes. The following flags are defined:
(none)
If no flags are specified, DirectDraw allocates memory to hold the data within the buffer, and copies the data into the new buffer. The buffer allocated by DirectDraw will automatically be freed as appropriate.
DDSPD_IUNKNOWNPOINTER
The data at lpData is a pointer to an IUnknown interface. DirectDraw automatically calls the IUnknown::AddRef method of this interface. When this data is no longer needed, DirectDraw automatically calls the IUnknown::Release method of this interface.
DDSPD_VOLATILE
The buffer at lpData is only valid while the surface remains unchanged from its current state. If the surface's contents change, subsequent calls to the IDirectDrawSurface4::GetPrivateData method will return DDERR_EXPIRED.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_OUTOFMEMORY

Remarks

DirectDraw does not manage the memory at lpData. If this buffer was dynamically allocated, it is the caller's responsibility to free the memory.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.

See Also

IDirectDrawSurface4::GetPrivateData, IDirectDrawSurface4::FreePrivateData


IDirectDrawSurface4::SetSurfaceDesc

The IDirectDrawSurface4::SetSurfaceDesc method sets the characteristics of an existing surface.

HRESULT SetSurfaceDesc(
  LPDDSURFACEDESC2 lpddsd2,
  DWORD dwFlags
);

Parameters

lpddsd2
Address of a DDSURFACEDESC2 structure that contains the new surface characteristics.
dwFlags
This parameter is currently not used and must be set to 0.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_INVALIDPARAMS
DDERR_INVALIDOBJECT
DDERR_SURFACELOST
DDERR_SURFACEBUSY
DDERR_INVALIDSURFACETYPE
DDERR_INVALIDPIXELFORMAT
DDERR_INVALIDCAPS
DDERR_UNSUPPORTED
DDERR_GENERIC

Remarks

Currently, this method can only be used to set the surface data and pixel format used by an explicit system memory surface. This is useful as it allows a surface to use data from a previously allocated buffer without copying. The new surface memory is allocated by the client application and, as such, the client application must also deallocate it. For more information about how this method is used, see Updating Surface Characteristics.

Using this method incorrectly will cause unpredictable behavior. The DirectDrawSurface object will not deallocate surface memory that it didn't allocate. Therefore, when the surface memory is no longer needed, it is your responsibility to deallocate it. However, when this method is called, DirectDraw frees the original surface memory that it implicitly allocated when creating the surface.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.


IDirectDrawSurface4::Unlock

The IDirectDrawSurface4::Unlock method notifies DirectDraw that the direct surface manipulations are complete.

HRESULT Unlock(
  LPRECT lpRect
);

Parameters

lpRect
Address of the RECT structure that was used to lock the surface in the corresponding call to the IDirectDrawSurface4::Lock method. This parameter can be NULL only if the entire surface was locked by passing NULL in the lpDestRect parameter of the corresponding call to the IDirectDrawSurface4::Lock method.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_GENERIC
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_INVALIDRECT
DDERR_NOTLOCKED
DDERR_SURFACELOST

Remarks

Because it is possible to call IDirectDrawSurface4::Lock multiple times for the same surface with different destination rectangles, the pointer in lpRect links the calls to the IDirectDrawSurface4::Lock and IDirectDrawSurface4::Unlock methods.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.

See Also

IDirectDrawSurface4::Lock


IDirectDrawSurface4::UpdateOverlay

The IDirectDrawSurface4::UpdateOverlay method repositions or modifies the visual attributes of an overlay surface. These surfaces must have the DDSCAPS_OVERLAY flag set.

HRESULT UpdateOverlay(
  LPRECT lpSrcRect,
  LPDIRECTDRAWSURFACE4 lpDDDestSurface,
  LPRECT lpDestRect,
  DWORD dwFlags,
  LPDDOVERLAYFX lpDDOverlayFx
);

Parameters

lpSrcRect
Address of a RECT structure that defines the x, y, width, and height of the region on the source surface being used as the overlay. This parameter can be NULL when hiding an overlay or to indicate that the entire overlay surface is to be used and that the overlay surface conforms to any boundary and size alignment restrictions imposed by the device driver.
lpDDDestSurface
Address of the IDirectDrawSurface4 interface for the surface that is being overlaid.
lpDestRect
Address of a RECT structure that defines the x, y, width, and height of the region on the destination surface that the overlay should be moved to. This parameter can be NULL when hiding the overlay.
dwFlags
DDOVER_ADDDIRTYRECT
Adds a dirty rectangle to an emulated overlay surface.
DDOVER_ALPHADEST
Uses either the alpha information in pixel format or the alpha channel surface attached to the destination surface as the alpha channel for this overlay.
DDOVER_ALPHADESTCONSTOVERRIDE
Uses the dwAlphaDestConst member of the DDOVERLAYFX structure as the destination alpha channel for this overlay.
DDOVER_ALPHADESTNEG
Indicates that the destination surface becomes more transparent as the alpha value increases (0 is opaque).
DDOVER_ALPHADESTSURFACEOVERRIDE
Uses the lpDDSAlphaDest member of the DDOVERLAYFX structure as the alpha channel destination for this overlay.
DDOVER_ALPHAEDGEBLEND
Uses the dwAlphaEdgeBlend member of the DDOVERLAYFX structure as the alpha channel for the edges of the image that border the color key colors.
DDOVER_ALPHASRC
Uses either the alpha information in pixel format or the alpha channel surface attached to the source surface as the source alpha channel for this overlay.
DDOVER_ALPHASRCCONSTOVERRIDE
Uses the dwAlphaSrcConst member of the DDOVERLAYFX structure as the source alpha channel for this overlay.
DDOVER_ALPHASRCNEG
Indicates that the source surface becomes more transparent as the alpha value increases (0 is opaque).
DDOVER_ALPHASRCSURFACEOVERRIDE
Uses the lpDDSAlphaSrc member of the DDOVERLAYFX structure as the alpha channel source for this overlay.
DDOVER_AUTOFLIP
Automatically flip to the next surface in the flip chain each time a video port VSYNC occurs.
DDOVER_BOB
Display each field individually of the interlaced video stream without causing any artifacts.
DDOVER_BOBHARDWARE
Indicates that bob operations will be performed using hardware rather than software or emulated. This flag must be used with the DDOVER_BOB flag.
DDOVER_DDFX
Uses the overlay FX flags in the lpDDOverlayFx parameter to define special overlay effects.
DDOVER_HIDE
Turns off this overlay.
DDOVER_KEYDEST
Uses the color key associated with the destination surface.
DDOVER_KEYDESTOVERRIDE
Uses the dckDestColorkey member of the DDOVERLAYFX structure as the color key for the destination surface.
DDOVER_KEYSRC
Uses the color key associated with the source surface.
DDOVER_KEYSRCOVERRIDE
Uses the dckSrcColorkey member of the DDOVERLAYFX structure as the color key for the source surface.
DDOVER_OVERRIDEBOBWEAVE
Indicates that bob/weave decisions should not be overridden by other interfaces.
DDOVER_INTERLEAVED
Indicates that the surface memory is composed of interleaved fields.
DDOVER_SHOW
Turns on this overlay.
lpDDOverlayFx
Address of a DDOVERLAYFX structure that describes the effects to be used. This parameter can be NULL if the DDOVER_DDFX flag is not specified.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_DEVICEDOESNTOWNSURFACE
DDERR_GENERIC
DDERR_HEIGHTALIGN
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_INVALIDRECT
DDERR_INVALIDSURFACETYPE
DDERR_NOSTRETCHHW
DDERR_NOTAOVERLAYSURFACE
DDERR_OUTOFCAPS
DDERR_SURFACELOST
DDERR_UNSUPPORTED
DDERR_XALIGN

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.


IDirectDrawSurface4::UpdateOverlayDisplay

The IDirectDrawSurface4::UpdateOverlayDisplay method is not currently implemented.

HRESULT UpdateOverlayDisplay(
  DWORD dwFlags
);

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.

See Also

IDirectDrawSurface4::AddOverlayDirtyRect


IDirectDrawSurface4::UpdateOverlayZOrder

The IDirectDrawSurface4::UpdateOverlayZOrder method sets the z-order of an overlay.

HRESULT UpdateOverlayZOrder(
  DWORD dwFlags,
  LPDIRECTDRAWSURFACE4 lpDDSReference
);

Parameters

dwFlags
One of the following flags:
DDOVERZ_INSERTINBACKOF
Inserts this overlay in the overlay chain behind the reference overlay.
DDOVERZ_INSERTINFRONTOF
Inserts this overlay in the overlay chain in front of the reference overlay.
DDOVERZ_MOVEBACKWARD
Moves this overlay one position backward in the overlay chain.
DDOVERZ_MOVEFORWARD
Moves this overlay one position forward in the overlay chain.
DDOVERZ_SENDTOBACK
Moves this overlay to the back of the overlay chain.
DDOVERZ_SENDTOFRONT
Moves this overlay to the front of the overlay chain.
lpDDSReference
Address of the IDirectDrawSurface4 interface for the DirectDraw surface to be used as a relative position in the overlay chain. This parameter is needed only for DDOVERZ_INSERTINBACKOF and DDOVERZ_INSERTINFRONTOF.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_NOTAOVERLAYSURFACE

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.

See Also

IDirectDrawSurface4::EnumOverlayZOrders


IDirectDrawVideoPort

Applications use the methods of the IDirectDrawVideoPort interface to channel live video data from a hardware video port to a DirectDraw surface. This section is a reference to the methods of this interface. For a conceptual overview, see Video Ports.

The methods of the IDirectDrawVideoPort interface can be organized into the following groups:

Color controls | GetColorControls
 | SetColorControls
Fields and Signals | GetFieldPolarity
 | GetVideoSignalStatus
Flipping | Flip
 | SetTargetSurface
Formats | GetInputFormats
 | GetOutputFormats
Timing and Synchronization | GetVideoLine
 | WaitForSync
Video control | StartVideo
 | StopVideo
 | UpdateVideo
Zoom factors | GetBandwidthInfo

The IDirectDrawVideoPort interface, like all COM interfaces, inherits the IUnknown interface methods. The IUnknown interface supports the following three methods:

IUnknown | AddRef
 | QueryInterface
 | Release

You can use the LPDIRECTDRAWVIDEOPORT data type to declare a variable that contains a pointer to an IDirectDrawVideoPort interface. The Dvp.h header file declares the LPDIRECTDRAWVIDEOPORT with the following code:

typedef struct IDirectDrawVideoPort    FAR *LPDIRECTDRAWVIDEOPORT;

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dvp.h.
Import Library: Use ddraw.lib.


IDirectDrawVideoPort::Flip

The IDirectDrawVideoPort::Flip method instructs the DirectDrawVideoPort object to write the next frame of video to a new surface.

HRESULT Flip(
  LPDIRECTDRAWSURFACE lpDDSurface,
  DWORD dwFlags
);

Parameters

lpDDSurface
Address of the IDirectDrawSurface interface for the surface that will receive the next frame of video. Setting this parameter to NULL causes DirectDraw to cycle through surfaces in the flipping chain in the order they were attached.
dwFlags
Flip options flags. This parameter can be one of the following values:
DDVPFLIP_VIDEO
The specified surface is to receive the normal video data.
DDVPFLIP_VBI
The specified surface is to receive only the data within the vertical blanking interval.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS

Remarks

This method can be used to prevent tearing. Calls to IDirectDrawVideoPort::Flip are asynchronous—the actual flip operation will always be synchronized with the vertical blank of the video signal.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dvp.h.
Import Library: Use ddraw.lib.


IDirectDrawVideoPort::GetBandwidthInfo

The IDirectDrawVideoPort::GetBandwidthInfo method retrieves the minimum required overlay zoom factors and device limitations of a video port that uses the provided output pixel format.

HRESULT GetBandwidthInfo(
  LPDDPIXELFORMAT lpddpfFormat,
  DWORD dwWidth,
  DWORD dwHeight,
  DWORD dwFlags,
  LPDDVIDEOPORTBANDWIDTH lpBandwidth
);

Parameters

lpddpfFormat
Address of a DDPIXELFORMAT structure that describes the output pixel format for which bandwidth information will be retrieved.
dwWidth and dwHeight
Dimensions of an overlay or video data. These interpretation of these parameters depends on the value specified in the dwFlags parameter.
dwFlags
Flags indicating how the method is to interpret the dwWidth and dwHeight parameters. This parameter can be one of the following values:
DDVPB_OVERLAY
The dwWidth and dwHeight parameters indicate the size of the source overlay surface. Use this flag when the video port is dependent on the overlay source size.
DDVPB_TYPE
The dwWidth and dwHeight parameters are not set. The method will retrieve the device's dependency type in the dwCaps member of the associated DDVIDEOPORTBANDWIDTH structure. Use this flag when you call this method the first time.
DDVPB_VIDEOPORT
The dwWidth and dwHeight parameters indicate the prescale size of the video data that the video port writes to the frame buffer. Use this flag when the video port is dependent on the overlay zoom factor.
lpBandwidth
Address of a DDVIDEOPORTBANDWIDTH structure that will be filled with the retrieved bandwidth and device dependency information.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS

Remarks

This method will usually be called twice. When you make the first call, specify the DDVPB_TYPE flag in the dwFlags parameter to retrieve information about the device's overlay dependency type. Subsequent calls using the DDVPB_VIDEOPORT or DDVPB_OVERLAY flags must be interpreted considering the device's dependency type.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dvp.h.
Import Library: Use ddraw.lib.


IDirectDrawVideoPort::GetColorControls

The IDirectDrawVideoPort::GetColorControls method returns the current color control settings associated with the video port.

HRESULT GetColorControls(
  LPDDCOLORCONTROL lpColorControl
);

Parameters

lpColorControl
Address of a DDCOLORCONTROL structure that will be filled with the current settings of the video port's color control.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_UNSUPPORTED

Remarks

The dwFlags member of the DDCOLORCONTROL structure indicate which of the color control options are supported.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dvp.h.
Import Library: Use ddraw.lib.


IDirectDrawVideoPort::GetFieldPolarity

The IDirectDrawVideoPort::GetFieldPolarity method retrieves the polarity of a video field.

HRESULT GetFieldPolarity(
  LPBOOL lpbFieldPolarity
);

Parameters

lpbFieldPolarity
Address of a variable that will be set to indicate the current field polarity. This value is set to TRUE if the current video field is the even field of an interlaced video signal and FALSE otherwise.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_UNSUPPORTED
DDERR_VIDEONOTACTIVE

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dvp.h.
Import Library: Use ddraw.lib.


IDirectDrawVideoPort::GetInputFormats

The IDirectDrawVideoPort::GetInputFormats method retrieves the input formats supported by the DirectDrawVideoPort object.

HRESULT GetInputFormats(
  LPDWORD lpNumFormats,
  LPDDPIXELFORMAT lpFormats,
  DWORD dwFlags
);

Parameters

lpNumFormats
Address of a variable containing the number of entries that the array at lpFormats can hold. If this number is less than the total number of codes, the method fills the array with as many codes as will fit, sets the value at lpNumFormats to indicate the total number of codes, and returns DDERR_MOREDATA.
lpFormats
Address of an array of DDPIXELFORMAT structures that will be filled in with the input formats supported by this DirectDrawVideoPort object. If this parameter is NULL, the method sets lpNumFormats to the number of supported formats and then returns DD_OK.
dwFlags
Flags specifying the part of the video signal for which formats will be enumerated. This parameter can be one of the following values:
DDVPFORMAT_VIDEO
Returns formats for the video data.
DDVPFORMAT_VBI
Returns formats for the VBI data.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_MOREDATA

Remarks

This method can also be used to return the number of formats supported. To do this, set the lpFormats parameter to NULL. When the method returns, the variable at lpNumFormats contains the total number of supported input formats.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dvp.h.
Import Library: Use ddraw.lib.


IDirectDrawVideoPort::GetOutputFormats

The IDirectDrawVideoPort::GetOutputFormats method retrieves a list of output formats that the DirectDrawVideoPort object supports for a specified input format.

HRESULT GetOutputFormats(
  LPDDPIXELFORMAT lpInputFormat,
  LPDWORD lpNumFormats,
  LPDDPIXELFORMAT lpFormats,
  DWORD dwFlags
);

Parameters

lpInputFormat
Address of a DDPIXELFORMAT structure that describes the input format for which conversion information is requested.
lpNumFormats
Address of a variable containing the number of entries that the array at lpFromats can hold. If this number is less than the total number of codes, the method fills the array with as many codes as will fit, sets the value at lpNumFormats to indicate the total number of codes, and returns DDERR_MOREDATA.
lpFormats
Address of an array of DDPIXELFORMAT structures that will be filled in with the output formats supported by this DirectDrawVideoPort object. If this parameter is NULL, the method sets lpNumFormats to the number of supported formats and then returns DD_OK.
dwFlags
Flags specifying the part of the video signal for which formats will be enumerated. This parameter can be one of the following values:
DDVPFORMAT_VIDEO
Returns formats for the video data.
DDVPFORMAT_VBI
Returns formats for the VBI data.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_MOREDATA

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dvp.h.
Import Library: Use ddraw.lib.


IDirectDrawVideoPort::GetVideoLine

The IDirectDrawVideoPort::GetVideoLine method retrieves the current line of video being written to the frame buffer.

HRESULT GetVideoLine(
  LPDWORD lpdwLine
);

Parameters

lpdwLine
Address of a variable that will be filled with a value indicating the video line currently being written to the frame buffer.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_UNSUPPORTED
DDERR_VERTICALBLANKINPROGRESS
DDERR_VIDEONOTACTIVE

Remarks

The value this method retrieves reflects the true video line being written, relative to the field height, before any prescaling occurs.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dvp.h.
Import Library: Use ddraw.lib.


IDirectDrawVideoPort::GetVideoSignalStatus

The IDirectDrawVideoPort::GetVideoSignalStatus method retrieves the status of the video signal currently being presented to the video port.

HRESULT GetVideoSignalStatus(
  LPDWORD lpdwStatus
);

Parameters

lpdwStatus
Address of a variable that will contain a return code indicating the quality of the video signal at the video port. The value will be set to one of the following codes:
DDVPSQ_NOSIGNAL
No video signal is present at the video port.
DDVPSQ_SIGNALOK
A valid video signal is present at the video port.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_UNSUPPORTED

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dvp.h.
Import Library: Use ddraw.lib.


IDirectDrawVideoPort::SetColorControls

The IDirectDrawVideoPort::SetColorControls method sets the color control settings associated with the video port.

HRESULT SetColorControls(
  LPDDCOLORCONTROL lpColorControl
);

Parameters

lpColorControl
Address of a DDCOLORCONTROL structure containing the new color control settings that will be applied to the video port.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_UNSUPPORTED

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dvp.h.
Import Library: Use ddraw.lib.


IDirectDrawVideoPort::SetTargetSurface

The IDirectDrawVideoPort::SetTargetSurface method sets the DirectDraw surface object that will receive the stream of live video data and/or the vertical blank interval data.

HRESULT SetTargetSurface(
  LPDIRECTDRAWSURFACE lpDDSurface,
  DWORD dwFlags
);

Parameters

lpDDSurface
Address of the DirectDrawSurface object that will receive the video data.
dwFlags
Value specifying the type of target surface.
DDVPTARGET_VIDEO
The specified surface should receive the normal video data and vertical interval data unless a separate surface was attached for this purpose.
DDVPTARGET_VBI
The specified surface should receive the data within the vertical blanking interval.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dvp.h.
Import Library: Use ddraw.lib.

See Also

IDirectDrawVideoPort::StartVideo, IDirectDrawVideoPort::StopVideo, IDirectDrawVideoPort::UpdateVideo


IDirectDrawVideoPort::StartVideo

The IDirectDrawVideoPort::StartVideo method enables the hardware video port and starts the flow of video data into the currently specified surface.

HRESULT StartVideo(
  LPDDVIDEOPORTINFO lpVideoInfo
);

Parameters

lpVideoInfo
Address of a pointer to a DDVIDEOPORTINFO structure.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_SURFACELOST

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dvp.h.
Import Library: Use ddraw.lib.

See Also

IDirectDrawVideoPort::SetTargetSurface, IDirectDrawVideoPort::StopVideo, IDirectDrawVideoPort::UpdateVideo


IDirectDrawVideoPort::StopVideo

The IDirectDrawVideoPort::StopVideo method stops the flow of video port data into the frame buffer.

HRESULT StopVideo();

Parameters

None.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value is DDERR_INVALIDOBJECT.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dvp.h.
Import Library: Use ddraw.lib.

See Also

IDirectDrawVideoPort::SetTargetSurface, IIDirectDrawVideoPort::StartVideo, IDirectDrawVideoPort::UpdateVideo


IDirectDrawVideoPort::UpdateVideo

The IDirectDrawVideoPort::UpdateVideo method updates parameters that govern the flow of video data from the video port to the DirectDrawSurface object.

HRESULT UpdateVideo(
  LPDDVIDEOPORTINFO lpVideoInfo
);

Parameters

lpVideoInfo
Address of a DDVIDEOPORTINFO structure that describes the video transfer parameters.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dvp.h.
Import Library: Use ddraw.lib.

See Also

IDirectDrawVideoPort::SetTargetSurface, IDirectDrawVideoPort::StartVideo, IDirectDrawVideoPort::StopVideo


IDirectDrawVideoPort::WaitForSync

The IDirectDrawVideoPort::WaitForSync method waits for VSYNC or until a given scan line is being drawn.

HRESULT WaitForSync(
  DWORD dwFlags,
  DWORD dwLine,
  DWORD dwTimeout
);

Parameters

dwFlags
Flag specifying how the method will wait for the video VSYNC or the specified line number.
DDVPWAIT_BEGIN
Return at the start of the vertical blanking interval.
DDVPWAIT_END
Return at the end of the vertical blanking interval.
DDVPWAIT_LINE
Return when the video counter either reaches or passes the line specified by the dwLine parameter.
dwLine
The video line determining when the method should return, relative to the field height, before prescaling. This parameter is ignored if the dwFlags parameter is set to DDVPWAIT_BEGIN or DDVPWAIT_END.
dwTimeout
Amount of time, in milliseconds, that the method will wait for the next video vertical blank before timing out. If this parameter is 0, the method waits 3 times the value specified in the dwMicrosecondsPerField member of the DDVIDEOPORTDESC.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following error values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_UNSUPPORTED
DDERR_VIDEONOTACTIVE
DDERR_WASSTILLDRAWING

Remarks

This method helps the caller synchronize with the video vertical blank interval or with an arbitrary line of video data. The method blocks the calling thread until either the video VSYNC occurs or when the video line counter matches the specified line number.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dvp.h.
Import Library: Use ddraw.lib.


Functions

This section contains information about the following DirectDraw global functions:

  • DirectDrawCreate
  • DirectDrawCreateClipper
  • DirectDrawEnumerate
  • DirectDrawEnumerateEx


DirectDrawCreate

The DirectDrawCreate function creates an instance of a DirectDraw object.

HRESULT WINAPI DirectDrawCreate(
  GUID FAR *lpGUID,
  LPDIRECTDRAW FAR *lplpDD,
  IUnknown FAR *pUnkOuter
);

Parameters

lpGUID
Address of the globally unique identifier (GUID) that represents the driver to be created. This can be NULL to indicate the active display driver, or you can pass one of the following flags to restrict the active display driver's behavior for debugging purposes:
DDCREATE_EMULATIONONLY
The DirectDraw object will use emulation for all features; it will not take advantage of any hardware supported features.
DDCREATE_HARDWAREONLY
The DirectDraw object will never emulate features not supported by the hardware. Attempts to call methods that require unsupported features will fail, returning DDERR_UNSUPPORTED.
lplpDD
Address of a variable that will be set to a valid IDirectDraw interface pointer if the call succeeds.
pUnkOuter
Allows for future compatibility with COM aggregation features. Presently, however, this method will return an error if this parameter is anything but NULL.

Return Values

If the function succeeds, the return value is DD_OK.

If the function fails, the return value may be one of the following error values:

DDERR_DIRECTDRAWALREADYCREATED
DDERR_GENERIC
DDERR_INVALIDDIRECTDRAWGUID
DDERR_INVALIDPARAMS
DDERR_NODIRECTDRAWHW
DDERR_OUTOFMEMORY

Remarks

This function attempts to initialize a DirectDraw object, and it then sets a pointer to the object if the call is successful.

On systems with multiple monitors, specifying NULL for lpGUID causes the DirectDraw object to run in emulation mode when the normal cooperative level is set. To make use of hardware acceleration on these systems, you must specify the device's GUID. For more information, see Devices and Acceleration in MultiMon Systems.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.


DirectDrawCreateClipper

The DirectDrawCreateClipper function creates an instance of a DirectDrawClipper object not associated with a DirectDraw object.

HRESULT WINAPI DirectDrawCreateClipper(
  DWORD dwFlags,
  LPDIRECTDRAWCLIPPER FAR *lplpDDClipper,
  IUnknown FAR *pUnkOuter
);

Parameters

dwFlags
This parameter is currently not used and must be set to 0.
lplpDDClipper
Address of a pointer that will be filled with the address of the new DirectDrawClipper object.
pUnkOuter
Allows for future compatibility with COM aggregation features. Presently, however, this method will return an error if this parameter is anything but NULL.

Return Values

If the function succeeds, the return value is DD_OK.

If the function fails, the return value may be one of the following error values:

DDERR_INVALIDPARAMS
DDERR_OUTOFMEMORY

Remarks

This function can be called before any DirectDraw objects are created. Because these DirectDrawClipper objects are not owned by any DirectDraw object, they are not automatically released when an application's objects are released. If the application does not explicitly release the DirectDrawClipper objects, DirectDraw will release them when the application terminates.

To create a DirectDrawClipper object owned by a specific DirectDraw object, use the IDirectDraw4::CreateClipper method.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.

See Also

IDirectDraw4::CreateClipper


DirectDrawEnumerate

This function is superseded by the DirectDrawEnumerateEx function.

The DirectDrawEnumerate function enumerates the primary DirectDraw display device and a non-display device (such as a 3-D accelerator that has no 2-D capabilities) if one is installed. The NULL entry always identifies the primary display device shared with GDI.

HRESULT WINAPI DirectDrawEnumerate(
  LPDDENUMCALLBACK lpCallback,
  LPVOID lpContext
);

Parameters

lpCallback
Address of a DDEnumCallback function that will be called with a description of each enumerated DirectDraw-enabled HAL.
lpContext
Address of an application-defined context that will be passed to the enumeration callback function each time it is called.

Return Values

If the function succeeds, the return value is DD_OK.

If the function fails, the return value is DDERR_INVALIDPARAMS.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.

See Also

DirectDrawEnumerateEx


DirectDrawEnumerateEx

The DirectDrawEnumerateEx function enumerates all DirectDraw devices installed on the system. The NULL entry always identifies the primary display device shared with GDI.

HRESULT WINAPI DirectDrawEnumerateEx(
  LPDDENUMCALLBACKEX lpCallback,
  LPVOID lpContext,
  DWORD  dwFlags
);

Parameters

lpCallback
Address of a DDEnumCallbackEx function that will be called with a description of each enumerated DirectDraw-enabled HAL.
lpContext
Address of an application-defined value that will be passed to the enumeration callback function each time it is called.
dwFlags
Flags specifying the enumeration scope. This parameter can be 0 or a combination of the following flags. If the value is 0, the function will enumerate only the primary display device.
DDENUM_ATTACHEDSECONDARYDEVICES
The function will enumerate the primary device, and any display devices that are attached to the desktop.
DDENUM_DETACHEDSECONDARYDEVICES
The function will enumerate the primary device, and any display devices that are not attached to the desktop.
DDENUM_NONDISPLAYDEVICES
The function will enumerate the primary device, and any non-display devices, such as 3-D accelerators that have no 2-D capabilities.

Return Values

If the function succeeds, the return value is DD_OK.

If the function fails, the return value is DDERR_INVALIDPARAMS.

Remarks

On systems with multiple monitors, this method enumerates multiple display devices. For more information, see Multiple Monitor Systems.

For Windows 98, this function is supported in DirectX 5.0 and later; for all other operating systems, DirectX 6.0 is required. Retrieve the DirectDrawEnumerateEx function's address from the Ddraw.dll dynamic-link library by calling the GetProcAddress Win32 function with the "DirectDrawEnumerateExA" (ANSI) or "DirectDrawEnumerateExW" (Unicode) process name strings. If GetProcAddress fails, then the installed version of the operating system does not support multiple monitors. For more information, see Enumerating Devices on MultiMon Systems.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 98.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.
Unicode: Implemented as Unicode and ANSI versions on Windows NT.


Callback Functions

This section contains information about the following callback functions used with DirectDraw:

  • DDEnumCallback
  • DDEnumCallbackEx
  • EnumModesCallback
  • EnumModesCallback2
  • EnumSurfacesCallback
  • EnumSurfacesCallback2
  • EnumVideoCallback


DDEnumCallback

The DDEnumCallback function is an application-defined callback function for the DirectDrawEnumerate function.

BOOL WINAPI DDEnumCallback(
  GUID FAR *lpGUID,
  LPSTR  lpDriverDescription,
  LPSTR  lpDriverName,
  LPVOID lpContext
);

Parameters

lpGUID
Address of the unique identifier of the DirectDraw object.
lpDriverDescription
Address of a string containing the driver description.
lpDriverName
Address of a string containing the driver name.
lpContext
Address of an application-defined structure that will be passed to the callback function each time the function is called.

Return Values

The callback function returns non-zero to continue the enumeration.

The callback function returns zero to stop it.

Remarks

You can use the LPDDENUMCALLBACK data type to declare a variable that can contain a pointer to this callback function.

If UNICODE is defined, the string values will be returned as type LPWSTR rather than LPSTR.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: User-defined.


DDEnumCallbackEx

The DDEnumCallbackEx function is an application-defined callback function for the DirectDrawEnumerateEx function.

BOOL WINAPI DDEnumCallbackEx(
  GUID FAR *lpGUID,
  LPSTR     lpDriverDescription,
  LPSTR     lpDriverName,
  LPVOID    lpContext,
  HMONITOR  hm
);

Parameters

lpGUID
Address of the unique identifier of the DirectDraw object.
lpDriverDescription
Address of a string containing the driver description.
lpDriverName
Address of a string containing the driver name.
lpContext
Address of an application-defined structure that will be passed to the callback function each time the function is called.
hm
Handle to the monitor associated with the enumerated DirectDraw object. This parameter will be NULL when the enumerated DirectDraw object is for the primary device, a non-display device (such as a 3-D accelerator with no 2-D capabilities), and devices not attached to the desktop.

Return Values

The callback function returns non-zero to continue the enumeration.

The callback function returns zero to stop it.

Remarks

You can use the LPDDENUMCALLBACKEX data type to declare a variable that can contain a pointer to this callback function.

If UNICODE is defined, the string values will be returned as type LPWSTR rather than LPSTR.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 98.
Header: Declared in ddraw.h.
Import Library: User-defined.

See Also

Enumerating Devices on MultiMon Systems, Multiple Monitor Systems


EnumModesCallback

The EnumModesCallback function is an application-defined callback function for the IDirectDraw3::EnumDisplayModes method, and its counterparts in earlier interfaces.

This callback function is superseded by the EnumModesCallback2 function that is used with the IDirectDraw4::EnumDisplayModes method.

HRESULT WINAPI EnumModesCallback(
  LPDDSURFACEDESC lpDDSurfaceDesc,
  LPVOID lpContext
);

Parameters

lpDDSurfaceDesc
Address of a read-only DDSURFACEDESC structure that provides the monitor frequency and the mode that can be created.
lpContext
Address of an application-defined structure that will be passed to the callback function each time the function is called.

Return Values

The callback function returns DDENUMRET_OK to continue the enumeration.

The callback function returns DDENUMRET_CANCEL to stop it.

Remarks

You can use the LPDDENUMMODESCALLBACK data type to declare a variable that can contain a pointer to this callback function.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: User-defined.


EnumModesCallback2

The EnumModesCallback2 function is an application-defined callback function for the IDirectDraw4::EnumDisplayModes method.

HRESULT WINAPI EnumModesCallback(
  LPDDSURFACEDESC2 lpDDSurfaceDesc,
  LPVOID lpContext
);

Parameters

lpDDSurfaceDesc
Address of a read-only DDSURFACEDESC2 structure that provides the monitor frequency and the mode that can be created.
lpContext
Address of an application-defined structure that will be passed to the callback function each time the function is called.

Return Values

The callback function returns DDENUMRET_OK to continue the enumeration.

The callback function returns DDENUMRET_CANCEL to stop it.

Remarks

You can use the LPDDENUMMODESCALLBACK2 data type to declare a variable that can contain a pointer to this callback function.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: User-defined.


EnumSurfacesCallback

The EnumSurfacesCallback function is an application-defined callback function for the IDirectDraw2::EnumSurfaces, IDirectDrawSurface3::EnumAttachedSurfaces, and IDirectDrawSurface3::EnumOverlayZOrders methods (and the versions from earlier interfaces).

HRESULT WINAPI EnumSurfacesCallback(
  LPDIRECTDRAWSURFACE lpDDSurface,
  LPDDSURFACEDESC lpDDSurfaceDesc,
  LPVOID lpContext
);

Parameters

lpDDSurface
Address of the IDirectDrawSurface interface for the attached surface.
lpDDSurfaceDesc
Address of a DDSURFACEDESC structure that describes the attached surface.
lpContext
Address of an application-defined structure that will be passed to the callback function each time the function is called.

Return Values

The callback function returns DDENUMRET_OK to continue the enumeration.

The callback function returns DDENUMRET_CANCEL to stop it.

Remarks

You can use the LPDDENUMSURFACESCALLBACK data type to declare a variable that can contain a pointer to this callback function.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: User-defined.


EnumSurfacesCallback2

The EnumSurfacesCallback2 function is an application-defined callback function for the IDirectDrawSurface4::EnumAttachedSurfaces and IDirectDrawSurface4::EnumOverlayZOrders methods.

HRESULT WINAPI EnumSurfacesCallback2(
  LPDIRECTDRAWSURFACE4 lpDDSurface,
  LPDDSURFACEDESC2 lpDDSurfaceDesc,
  LPVOID lpContext
);

Parameters

lpDDSurface
Address of the IDirectDrawSurface4 interface of the attached surface.
lpDDSurfaceDesc
Address of a DDSURFACEDESC2 structure that describes the attached surface.
lpContext
Address of an application-defined structure that will be passed to the callback function each time the function is called.

Return Values

The callback function returns DDENUMRET_OK to continue the enumeration.

The callback function returns DDENUMRET_CANCEL to stop it.

Remarks

You can use the LPDDENUMSURFACESCALLBACK2 data type to declare a variable that can contain a pointer to this callback function.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: User-defined.


EnumVideoCallback

The EnumVideoCallback function is an application-defined callback procedure for the IDDVideoPortContainer::EnumVideoPorts method.

HRESULT WINAPI EnumVideoCallback(
  LPDDVIDEOPORTCAPS lpDDVideoPortCaps,
  LPVOID lpContext
);

Parameters

lpDDVideoPortCaps
Pointer to the DDVIDEOPORTCAPS structure that contains the video port information, including the ID and capabilities. This data is read-only.
lpContext
Pointer to a caller-defined structure that is passed to the member every time it is called.

Return Values

The callback function returns DDENUMRET_OK to continue the enumeration.

The callback function returns DDENUMRET_CANCEL to stop it.

Remarks

Video-port related functions cannot be called from inside the EnumVideoCallback function. Attempts to do so will fail, returning DDERR_CURRENTLYNOTAVAIL.

You can use the LPDDENUMVIDEOCALLBACK data type to declare a variable that can contain a pointer to this callback function.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: User-defined.


Structures

This section contains information about the following structures used with DirectDraw:

  • DDBLTBATCH
  • DDBLTFX
  • DDCAPS
  • DDCOLORCONTROL
  • DDCOLORKEY
  • DDDEVICEIDENTIFIER
  • DDGAMMARAMP
  • DDOVERLAYFX
  • DDPIXELFORMAT
  • DDSCAPS
  • DDSCAPS2
  • DDSURFACEDESC
  • DDSURFACEDESC2
  • DDVIDEOPORTBANDWIDTH
  • DDVIDEOPORTCAPS
  • DDVIDEOPORTCONNECT
  • DDVIDEOPORTDESC
  • DDVIDEOPORTINFO
  • DDVIDEOPORTSTATUS

Note The memory for all DirectX structures should be initialized to zero before use. In addition, all structures that contain a dwSize member should set the member to the size of the structure, in bytes, before use. The following example performs these tasks on a common structure, DDCAPS:

DDCAPS ddcaps; // Can't use this yet.

ZeroMemory(&ddcaps, sizeof(DDCAPS));
ddcaps.dwSize = sizeof(DDCAPS);

// Now the structure can be used.
.
.


DDBLTBATCH

The DDBLTBATCH structure passes blit operations to the IDirectDrawSurface4::BltBatch method.

typedef struct _DDBLTBATCH{
    LPRECT              lprDest;
    LPDIRECTDRAWSURFACE lpDDSSrc;
    LPRECT              lprSrc;
    DWORD               dwFlags;
    LPDDBLTFX           lpDDBltFx;
} DDBLTBATCH,FAR *LPDDBLTBATCH;

Members

lprDest
Address of a RECT structure that defines the destination for the blit.
lpDDSSrc
Address of a DirectDrawSurface object that will be the source of the blit.
lprSrc
Address of a RECT structure that defines the source rectangle of the blit.
dwFlags
Optional control flags.
DDBLT_ALPHADEST
Uses either the alpha information in pixel format or the alpha channel surface attached to the destination surface as the alpha channel for this blit.
DDBLT_ALPHADESTCONSTOVERRIDE
Uses the dwAlphaDestConst member of the DDBLTFX structure as the alpha channel for the destination surface for this blit.
DDBLT_ALPHADESTNEG
Indicates that the destination surface becomes more transparent as the alpha value increases (0 is opaque).
DDBLT_ALPHADESTSURFACEOVERRIDE
Uses the lpDDSAlphaDest member of the DDBLTFX structure as the alpha channel for the destination surface for this blit.
DDBLT_ALPHAEDGEBLEND
Uses the dwAlphaEdgeBlend member of the DDBLTFX structure as the alpha channel for the edges of the image that border the color key colors.
DDBLT_ALPHASRC
Uses either the alpha information in pixel format or the alpha channel surface attached to the source surface as the alpha channel for this blit.
DDBLT_ALPHASRCCONSTOVERRIDE
Uses the dwAlphaSrcConst member of the DDBLTFX structure as the source alpha channel for this blit.
DDBLT_ALPHASRCNEG
Indicates that the source surface becomes more transparent as the alpha value increases (0 is opaque).
DDBLT_ALPHASRCSURFACEOVERRIDE
Uses the lpDDSAlphaSrc member of the DDBLTFX structure as the alpha channel source for this blit.
DDBLT_ASYNC
Processes this blit asynchronously through the FIFO hardware in the order received. If there is no room in the FIFO hardware, the call fails.
DDBLT_COLORFILL
Uses the dwFillColor member of the DDBLTFX structure as the RGB color that fills the destination rectangle on the destination surface.
DDBLT_DDFX
Uses the dwDDFX member of the DDBLTFX structure to specify the effects to be used for this blit.
DDBLT_DDROPS
Uses the dwDDROP member of the DDBLTFX structure to specify the raster operations (ROPs) that are not part of the Win32 API.
DDBLT_KEYDEST
Uses the color key associated with the destination surface.
DDBLT_KEYDESTOVERRIDE
Uses the ddckDestColorkey member of the DDBLTFX structure as the color key for the destination surface.
DDBLT_KEYSRC
Uses the color key associated with the source surface.
DDBLT_KEYSRCOVERRIDE
Uses the ddckSrcColorkey member of the DDBLTFX structure as the color key for the source surface.
DDBLT_ROP
Uses the dwROP member of the DDBLTFX structure for the ROP for this blit. The ROPs are the same as those defined in the Win32 API.
DDBLT_ROTATIONANGLE
Uses the dwRotationAngle member of the DDBLTFX structure as the rotation angle (specified in 1/100th of a degree) for the surface.
DDBLT_ZBUFFER
Performs a z-buffered blit using the z-buffers attached to the source and destination surfaces and the dwZBufferOpCode member of the DDBLTFX structure as the z-buffer opcode.
DDBLT_ZBUFFERDESTCONSTOVERRIDE
Performs a z-buffered blit using the dwZDestConst and dwZBufferOpCode members of the DDBLTFX structure as the z-buffer and z-buffer opcode, respectively, for the destination.
DDBLT_ZBUFFERDESTOVERRIDE
Performs a z-buffered blit using the lpDDSZBufferDest and dwZBufferOpCode members of the DDBLTFX structure as the z-buffer and z-buffer opcode, respectively, for the destination.
DDBLT_ZBUFFERSRCCONSTOVERRIDE
Performs a z-buffered blit using the dwZSrcConst and dwZBufferOpCode members of the DDBLTFX structure as the z-buffer and z-buffer opcode, respectively, for the source.
DDBLT_ZBUFFERSRCOVERRIDE
A z-buffered blit using the lpDDSZBufferSrc and dwZBufferOpCode members of the DDBLTFX structure as the z-buffer and z-buffer opcode, respectively, for the source.
lpDDBltFx
Address of a DDBLTFX structure specifying additional blit effects.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.


DDBLTFX

The DDBLTFX structure passes raster operations, effects, and override information to the IDirectDrawSurface4::Blt method. This structure is also part of the DDBLTBATCH structure used with the IDirectDrawSurface4::BltBatch method.

typedef struct _DDBLTFX{
    DWORD dwSize;
    DWORD dwDDFX;
    DWORD dwROP;
    DWORD dwDDROP;
    DWORD dwRotationAngle;
    DWORD dwZBufferOpCode;
    DWORD dwZBufferLow;
    DWORD dwZBufferHigh;
    DWORD dwZBufferBaseDest;
    DWORD dwZDestConstBitDepth;
    union
    {
        DWORD               dwZDestConst;
        LPDIRECTDRAWSURFACE lpDDSZBufferDest;
    } DUMMYUNIONNAMEN(1);
    DWORD dwZSrcConstBitDepth;
    union
    {
        DWORD               dwZSrcConst;
        LPDIRECTDRAWSURFACE lpDDSZBufferSrc;
    } DUMMYUNIONNAMEN(2);
    DWORD dwAlphaEdgeBlendBitDepth;
    DWORD dwAlphaEdgeBlend;
    DWORD dwReserved;
    DWORD dwAlphaDestConstBitDepth;
    union
    {
        DWORD               dwAlphaDestConst;
        LPDIRECTDRAWSURFACE lpDDSAlphaDest;
    } DUMMYUNIONNAMEN(3);
    DWORD dwAlphaSrcConstBitDepth;
    union
    {
        DWORD               dwAlphaSrcConst;
        LPDIRECTDRAWSURFACE lpDDSAlphaSrc;
    } DUMMYUNIONNAMEN(4);
    union
    {
        DWORD               dwFillColor;
        DWORD               dwFillDepth;
        DWORD               dwFillPixel;
        LPDIRECTDRAWSURFACE lpDDSPattern;
    } DUMMYUNIONNAMEN(5);
    DDCOLORKEY ddckDestColorkey;
    DDCOLORKEY ddckSrcColorkey;
} DDBLTFX,FAR* LPDDBLTFX;

Members

dwSize
Size of the structure, in bytes. This member must be initialized before the structure is used.
dwDDFX
Type of FX operations.
DDBLTFX_ARITHSTRETCHY
Uses arithmetic stretching along the y-axis for this blit.
DDBLTFX_MIRRORLEFTRIGHT
Turns the surface on its y-axis. This blit mirrors the surface from left to right.
DDBLTFX_MIRRORUPDOWN
Turns the surface on its x-axis. This blit mirrors the surface from top to bottom.
DDBLTFX_NOTEARING
Schedules this blit to avoid tearing.
DDBLTFX_ROTATE180
Rotates the surface 180 degrees clockwise during this blit.
DDBLTFX_ROTATE270
Rotates the surface 270 degrees clockwise during this blit.
DDBLTFX_ROTATE90
Rotates the surface 90 degrees clockwise during this blit.
DDBLTFX_ZBUFFERBASEDEST
Adds the dwZBufferBaseDest member to each of the source z-values before comparing them with the destination z-values during this z-blit.
DDBLTFX_ZBUFFERRANGE
Uses the dwZBufferLow and dwZBufferHigh members as range values to specify limits to the bits copied from a source surface during this z-blit.
dwROP
Win32 raster operations. You can retrieve a list of supported raster operations by calling the IDirectDraw4::GetCaps method.
dwDDROP
DirectDraw raster operations.
dwRotationAngle
Rotation angle for the blit.
dwZBufferOpCode
Z-buffer compares.
dwZBufferLow
Low limit of a z-buffer.
dwZBufferHigh
High limit of a z-buffer.
dwZBufferBaseDest
Destination base value of a z-buffer.
dwZDestConstBitDepth
Bit depth of the destination z-constant.
dwZDestConst
Constant used as the z-buffer destination.
lpDDSZBufferDest
Surface used as the z-buffer destination.
dwZSrcConstBitDepth
Bit depth of the source z-constant.
dwZSrcConst
Constant used as the z-buffer source.
lpDDSZBufferSrc
Surface used as the z-buffer source.
dwAlphaEdgeBlendBitDepth
Bit depth of the constant for an alpha edge blend.
dwAlphaEdgeBlend
Alpha constant used for edge blending.
dwReserved
Reserved for future use.
dwAlphaDestConstBitDepth
Bit depth of the destination alpha constant.
dwAlphaDestConst
Constant used as the alpha channel destination.
lpDDSAlphaDest
Surface used as the alpha channel destination.
dwAlphaSrcConstBitDepth
Bit depth of the source alpha constant.
dwAlphaSrcConst
Constant used as the alpha channel source.
lpDDSAlphaSrc
Surface used as the alpha channel source.
dwFillColor
Color used to fill a surface when DDBLT_COLORFILL is specified. This value must be a pixel appropriate to the pixel format of the destination surface. For a palettized surface it would be a palette index, and for a 16-bit RGB surface it would be a 16-bit pixel value.
dwFillDepth
Depth value for the z-buffer.
dwFillPixel
Pixel value for RGBA or RGBZ fills. Applications that use RGBZ fills should use this member, not dwFillColor or dwFillDepth.
lpDDSPattern
Surface to use as a pattern. The pattern can be used in certain blit operations that combine a source and a destination.
ddckDestColorkey
Destination color key override.
ddckSrcColorkey
Source color key override.

Remarks

The unions in this structure have been updated to work with compilers that don't support nameless unions. If your compiler doesn't support nameless unions, define the NONAMELESSUNION token before including the Ddraw.h header file.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.


DDCAPS

The DDCAPS structure represents the capabilities of the hardware exposed through the DirectDraw object. This structure contains a DDSCAPS structure used in this context to describe what kinds of DirectDrawSurface objects can be created. It may not be possible to simultaneously create all of the surfaces described by these capabilities. This structure is used with the IDirectDraw4::GetCaps method.

The ddraw.h header file contains multiple versions of this structure. See Remarks for more information.

typedef struct _DDCAPS {
    DWORD    dwSize;
    DWORD    dwCaps;                  // driver-specific caps
    DWORD    dwCaps2;                 // more driver-specific caps
    DWORD    dwCKeyCaps;              // color key caps
    DWORD    dwFXCaps;                // stretching and effects caps
    DWORD    dwFXAlphaCaps;           // alpha caps
    DWORD    dwPalCaps;               // palette caps
    DWORD    dwSVCaps;                // stereo vision caps
    DWORD    dwAlphaBltConstBitDepths;       // alpha bit-depth members
    DWORD    dwAlphaBltPixelBitDepths;       //  .
    DWORD    dwAlphaBltSurfaceBitDepths;     //  .
    DWORD    dwAlphaOverlayConstBitDepths;   //  .
    DWORD    dwAlphaOverlayPixelBitDepths;   //  .
    DWORD    dwAlphaOverlaySurfaceBitDepths; //  .
    DWORD    dwZBufferBitDepths;      // Z-buffer bit depth
    DWORD    dwVidMemTotal;           // total video memory
    DWORD    dwVidMemFree;            // total free video memory
    DWORD    dwMaxVisibleOverlays;    // maximum visible overlays
    DWORD    dwCurrVisibleOverlays;   // overlays currently visible
    DWORD    dwNumFourCCCodes;        // number of supported FOURCC codes
    DWORD    dwAlignBoundarySrc;      // overlay alignment restrictions
    DWORD    dwAlignSizeSrc;          //  .
    DWORD    dwAlignBoundaryDest;     //  .
    DWORD    dwAlignSizeDest;         //  .
    DWORD    dwAlignStrideAlign;      // stride alignment
    DWORD    dwRops[DD_ROP_SPACE];    // supported raster ops
    DWORD    dwReservedCaps;          // reserved
    DWORD    dwMinOverlayStretch;     // overlay stretch factors
    DWORD    dwMaxOverlayStretch;     //  .
    DWORD    dwMinLiveVideoStretch;   // obsolete
    DWORD    dwMaxLiveVideoStretch;   //  .
    DWORD    dwMinHwCodecStretch;     //  .
    DWORD    dwMaxHwCodecStretch;     //  .
    DWORD    dwReserved1;             // reserved
    DWORD    dwReserved2;             //  .
    DWORD    dwReserved3;             //  .
    DWORD    dwSVBCaps;               // system-to-video blit related caps
    DWORD    dwSVBCKeyCaps;           //  .
    DWORD    dwSVBFXCaps;             //  .
    DWORD    dwSVBRops[DD_ROP_SPACE]; //  .
    DWORD    dwVSBCaps;               // video-to-system blit related caps
    DWORD    dwVSBCKeyCaps;           //  .
    DWORD    dwVSBFXCaps;             //  .
    DWORD    dwVSBRops[DD_ROP_SPACE]; //  .
    DWORD    dwSSBCaps;               // system-to-system blit related caps
    DWORD    dwSSBCKeyCaps;           //  .
    DWORD    dwSSBCFXCaps;            //  .
    DWORD    dwSSBRops[DD_ROP_SPACE]; //  .
    DWORD    dwMaxVideoPorts;         // maximum number of live video ports
    DWORD    dwCurrVideoPorts;        // current number of live video ports
    DWORD    dwSVBCaps2;              // additional system-to-video blit caps
    DWORD    dwNLVBCaps;              // nonlocal-to-local video memory blit caps
    DWORD    dwNLVBCaps2;             //  .
    DWORD    dwNLVBCKeyCaps;          //  .
    DWORD    dwNLVBFXCaps;            //  .
    DWORD    dwNLVBRops[DD_ROP_SPACE];//  .
    DDSCAPS2 ddsCaps;                 // general surface caps
} DDCAPS,FAR* LPDDCAPS;

Members

dwSize
Size of the structure, in bytes. This member must be initialized before the structure is used.
dwCaps
Driver-specific capabilities.
DDCAPS_3D
Indicates that the display hardware has 3-D acceleration.
DDCAPS_ALIGNBOUNDARYDEST
Indicates that DirectDraw will support only those overlay destination rectangles with the x-axis aligned to the dwAlignBoundaryDest boundaries of the surface.
DDCAPS_ALIGNBOUNDARYSRC
Indicates that DirectDraw will support only those overlay source rectangles with the x-axis aligned to the dwAlignBoundarySrc boundaries of the surface.
DDCAPS_ALIGNSIZEDEST
Indicates that DirectDraw will support only those overlay destination rectangles whose x-axis sizes, in pixels, are dwAlignSizeDest multiples.
DDCAPS_ALIGNSIZESRC
Indicates that DirectDraw will support only those overlay source rectangles whose x-axis sizes, in pixels, are dwAlignSizeSrc multiples.
DDCAPS_ALIGNSTRIDE
Indicates that DirectDraw will create display memory surfaces that have a stride alignment equal to the dwAlignStrideAlign value.
DDCAPS_ALPHA
Indicates that the display hardware supports alpha-only surfaces. (See alpha channel)
DDCAPS_BANKSWITCHED
Indicates that the display hardware is bank-switched and is potentially very slow at random access to display memory.
DDCAPS_BLT
Indicates that display hardware is capable of blit operations.
DDCAPS_BLTCOLORFILL
Indicates that display hardware is capable of color filling with a blitter.
DDCAPS_BLTDEPTHFILL
Indicates that display hardware is capable of depth filling z-buffers with a blitter.
DDCAPS_BLTFOURCC
Indicates that display hardware is capable of color-space conversions during blit operations.
DDCAPS_BLTQUEUE
Indicates that display hardware is capable of asynchronous blit operations.
DDCAPS_BLTSTRETCH
Indicates that display hardware is capable of stretching during blit operations.
DDCAPS_CANBLTSYSMEM
Indicates that display hardware is capable of blitting to or from system memory.
DDCAPS_CANCLIP
Indicates that display hardware is capable of clipping with blitting.
DDCAPS_CANCLIPSTRETCHED
Indicates that display hardware is capable of clipping while stretch blitting.
DDCAPS_COLORKEY
Supports some form of color key in either overlay or blit operations. More specific color key capability information can be found in the dwCKeyCaps member.
DDCAPS_COLORKEYHWASSIST
Indicates that the color key is partially hardware assisted. This means that other resources (CPU or video memory) might be used. If this bit is not set, full hardware support is in place.
DDCAPS_GDI
Indicates that display hardware is shared with GDI.
DDCAPS_NOHARDWARE
Indicates that there is no hardware support.
DDCAPS_OVERLAY
Indicates that display hardware supports overlays.
DDCAPS_OVERLAYCANTCLIP
Indicates that display hardware supports overlays but cannot clip them.
DDCAPS_OVERLAYFOURCC
Indicates that overlay hardware is capable of color-space conversions during overlay operations.
DDCAPS_OVERLAYSTRETCH
Indicates that overlay hardware is capable of stretching. The dwMinOverlayStretch and dwMaxOverlayStretch members contain valid data.
DDCAPS_PALETTE
Indicates that DirectDraw is capable of creating and supporting DirectDrawPalette objects for more surfaces than only the primary surface.
DDCAPS_PALETTEVSYNC
Indicates that DirectDraw is capable of updating a palette synchronized with the vertical refresh.
DDCAPS_READSCANLINE
Indicates that display hardware is capable of returning the current scan line.
DDCAPS_STEREOVIEW
Indicates that display hardware has stereo vision capabilities.
DDCAPS_VBI
Indicates that display hardware is capable of generating a vertical-blank interrupt.
DDCAPS_ZBLTS
Supports the use of z-buffers with blit operations.
DDCAPS_ZOVERLAYS
Supports the use of the IDirectDrawSurface4::UpdateOverlayZOrder method as a z-value for overlays to control their layering.
dwCaps2
More driver-specific capabilities.
DDCAPS2_AUTOFLIPOVERLAY
The overlay can be automatically flipped to the next surface in the flip chain each time a video port VSYNC occurs, allowing the video port and the overlay to double buffer the video without CPU overhead. This option is only valid when the surface is receiving data from a video port. If the video port data is non-interlaced or non-interleaved, it will flip on every VSYNC. If the data is being interleaved in memory, it will flip on every other VSYNC.
DDCAPS2_CANBOBHARDWARE
The overlay hardware can display each field of an interlaced video stream individually.
DDCAPS2_CANBOBINTERLEAVED
The overlay hardware can display each field individually of an interlaced video stream while it is interleaved in memory without causing any artifacts that might normally occur without special hardware support. This option is only valid when the surface is receiving data from a video port and is only valid when the video is zoomed at least two times in the vertical direction.
DDCAPS2_CANBOBNONINTERLEAVED
The overlay hardware can display each field individually of an interlaced video stream while it is not interleaved in memory without causing any artifacts that might normally occur without special hardware support. This option is only valid when the surface is receiving data from a video port and is only valid when the video is zoomed at least two times in the vertical direction.
DDCAPS2_CANCALIBRATEGAMMA
The system has a calibrator installed that can automatically adjust the gamma ramp so that the result will be identical on all systems that have a calibrator. To invoke the calibrator when setting new gamma levels, use the DDSGR_CALIBRATE flag when calling the IDirectDrawGammaControl::SetGammaRamp method. Calibrating gamma ramps incurs some processing overhead, and should not be used frequently.
DDCAPS2_CANDROPZ16BIT
16-bit RGBZ values can be converted into sixteen-bit RGB values. (The system does not support eight-bit conversions.)
DDCAPS2_CANFLIPODDEVEN
The driver is capable of performing odd and even flip operations, as specified by the DDFLIP_ODD and DDFLIP_EVEN flags used with the IDirectDrawSurface4::Flip method.
DDCAPS2_CANRENDERWINDOWED
The driver is capable of rendering in windowed mode.
DDCAPS2_CERTIFIED
Indicates that display hardware is certified.
DDCAPS2_COLORCONTROLPRIMARY
The primary surface contains color controls (for instance, gamma)
DDCAPS2_COLORCONTROLOVERLAY
The overlay surface contains color controls (such as brightness, sharpness)
DDCAPS2_COPYFOURCC
Indicates that the driver supports blitting any FOURCC surface to another surface of the same FOURCC.
DDCAPS2_FLIPINTERVAL
Indicates that the driver will respond to the DDFLIP_INTERVAL* flags. (see IDirectDrawSurface4::Flip).
DDCAPS2_FLIPNOVSYNC
Indicates that the driver will respond to the DDFLIP_NOVSYNC flag (see IDirectDrawSurface4::Flip).
DDCAPS2_NO2DDURING3DSCENE
Indicates that 2-D operations such as IDirectDrawSurface4::Blt and IDirectDrawSurface4::Lock cannot be performed on any surfaces that Direct3D® is using between calls to the IDirect3DDevice3::BeginScene and IDirect3DDevice3::EndScene methods.
DDCAPS2_NONLOCALVIDMEM
Indicates that the display driver supports surfaces in non-local video memory.
DDCAPS2_NONLOCALVIDMEMCAPS
Indicates that blit capabilities for non-local video memory surfaces differ from local video memory surfaces. If this flag is present, the DDCAPS2_NONLOCALVIDMEM flag will also be present.
DDCAPS2_NOPAGELOCKREQUIRED
DMA blit operations are supported on system memory surfaces that are not page locked.
DDCAPS2_PRIMARYGAMMA
Supports dynamic gamma ramps for the primary surface. For more information, see Gamma and Color Controls.
DDCAPS2_VIDEOPORT
Indicates that display hardware supports live video.
DDCAPS2_WIDESURFACES
Indicates that the display surfaces supports surfaces wider than the primary surface.
dwCKeyCaps
Color-key capabilities.
DDCKEYCAPS_DESTBLT
Supports transparent blitting with a color key that identifies the replaceable bits of the destination surface for RGB colors.
DDCKEYCAPS_DESTBLTCLRSPACE
Supports transparent blitting with a color space that identifies the replaceable bits of the destination surface for RGB colors.
DDCKEYCAPS_DESTBLTCLRSPACEYUV
Supports transparent blitting with a color space that identifies the replaceable bits of the destination surface for YUV colors.
DDCKEYCAPS_DESTBLTYUV
Supports transparent blitting with a color key that identifies the replaceable bits of the destination surface for YUV colors.
DDCKEYCAPS_DESTOVERLAY
Supports overlaying with color keying of the replaceable bits of the destination surface being overlaid for RGB colors.
DDCKEYCAPS_DESTOVERLAYCLRSPACE
Supports a color space as the color key for the destination of RGB colors.
DDCKEYCAPS_DESTOVERLAYCLRSPACEYUV
Supports a color space as the color key for the destination of YUV colors.
DDCKEYCAPS_DESTOVERLAYONEACTIVE
Supports only one active destination color key value for visible overlay surfaces .
DDCKEYCAPS_DESTOVERLAYYUV
Supports overlaying using color keying of the replaceable bits of the destination surface being overlaid for YUV colors.
DDCKEYCAPS_NOCOSTOVERLAY
Indicates there are no bandwidth trade-offs for using the color key with an overlay.
DDCKEYCAPS_SRCBLT
Supports transparent blitting using the color key for the source with this surface for RGB colors.
DDCKEYCAPS_SRCBLTCLRSPACE
Supports transparent blitting using a color space for the source with this surface for RGB colors.
DDCKEYCAPS_SRCBLTCLRSPACEYUV
Supports transparent blitting using a color space for the source with this surface for YUV colors.
DDCKEYCAPS_SRCBLTYUV
Supports transparent blitting using the color key for the source with this surface for YUV colors.
DDCKEYCAPS_SRCOVERLAY
Supports overlaying using the color key for the source with this overlay surface for RGB colors.
DDCKEYCAPS_SRCOVERLAYCLRSPACE
Supports overlaying using a color space as the source color key for the overlay surface for RGB colors.
DDCKEYCAPS_SRCOVERLAYCLRSPACEYUV
Supports overlaying using a color space as the source color key for the overlay surface for YUV colors.
DDCKEYCAPS_SRCOVERLAYONEACTIVE
Supports only one active source color key value for visible overlay surfaces.
DDCKEYCAPS_SRCOVERLAYYUV
Supports overlaying using the color key for the source with this overlay surface for YUV colors.
dwFXCaps
Driver-specific stretching and effects capabilities.
DDFXCAPS_BLTALPHA
Supports alpha-blended blit operations.
DDFXCAPS_BLTARITHSTRETCHY
Uses arithmetic operations, rather than pixel-doubling techniques, to stretch and shrink surfaces during a blit operation. Occurs along the y-axis (vertically).
DDFXCAPS_BLTARITHSTRETCHYN
Uses arithmetic operations, rather than pixel-doubling techniques, to stretch and shrink surfaces during a blit operation. Occurs along the y-axis (vertically), and works only for integer stretching (×1, ×2, and so on).
DDFXCAPS_BLTFILTER
Driver can do surface-reconstruction filtering for warped blits.
DDFXCAPS_BLTMIRRORLEFTRIGHT
Supports mirroring left to right in a blit operation.
DDFXCAPS_BLTMIRRORUPDOWN
Supports mirroring top to bottom in a blit operation.
DDFXCAPS_BLTROTATION
Supports arbitrary rotation in a blit operation.
DDFXCAPS_BLTROTATION90
Supports 90-degree rotations in a blit operation.
DDFXCAPS_BLTSHRINKX
Supports arbitrary shrinking of a surface along the x-axis (horizontally). This flag is valid only for blit operations.
DDFXCAPS_BLTSHRINKXN
Supports integer shrinking (×1, ×2, and so on) of a surface along the x-axis (horizontally). This flag is valid only for blit operations.
DDFXCAPS_BLTSHRINKY
Supports arbitrary shrinking of a surface along the y-axis (vertically). This flag is valid only for blit operations.
DDFXCAPS_BLTSHRINKYN
Supports integer shrinking (×1, ×2, and so on) of a surface along the y-axis (vertically). This flag is valid only for blit operations.
DDFXCAPS_BLTSTRETCHX
Supports arbitrary stretching of a surface along the x-axis (horizontally). This flag is valid only for blit operations.
DDFXCAPS_BLTSTRETCHXN
Supports integer stretching (×1, ×2, and so on) of a surface along the x-axis (horizontally). This flag is valid only for blit operations.
DDFXCAPS_BLTSTRETCHY
Supports arbitrary stretching of a surface along the y-axis (vertically). This flag is valid only for blit operations.
DDFXCAPS_BLTSTRETCHYN
Supports integer stretching (×1, ×2, and so on) of a surface along the y-axis (vertically). This flag is valid only for blit operations.
DDFXCAPS_BLTTRANSFORM
Supports geometric transformations (or warps) for blitted sprites. Transformations are not currently supported for explicit blit operations.
DDFXCAPS_OVERLAYALPHA
Supports alpha blending for overlay surfaces.
DDFXCAPS_OVERLAYARITHSTRETCHY
Uses arithmetic operations, rather than pixel-doubling techniques, to stretch and shrink overlay surfaces. Occurs along the y-axis (vertically).
DDFXCAPS_OVERLAYARITHSTRETCHYN
Uses arithmetic operations, rather than pixel-doubling techniques, to stretch and shrink overlay surfaces. Occurs along the y-axis (vertically), and works only for integer stretching (×1, ×2, and so on).
DDFXCAPS_OVERLAYFILTER
Supports surface-reconstruction filtering for warped overlay sprites. Filtering is not currently supported for explicitly displayed overlay surfaces (those displayed with calls to IDirectDrawSurface4::UpdateOverlay).
DDFXCAPS_OVERLAYMIRRORLEFTRIGHT
Supports mirroring of overlays across the vertical axis.
DDFXCAPS_OVERLAYMIRRORUPDOWN
Supports mirroring of overlays across the horizontal axis.
DDFXCAPS_OVERLAYSHRINKX
Supports arbitrary shrinking of a surface along the x-axis (horizontally). This flag is valid only for DDSCAPS_OVERLAY surfaces. This flag indicates only the capabilities of a surface; it does not indicate that shrinking is available.
DDFXCAPS_OVERLAYSHRINKXN
Supports integer shrinking (×1, ×2, and so on) of a surface along the x-axis (horizontally). This flag is valid only for DDSCAPS_OVERLAY surfaces. This flag indicates only the capabilities of a surface; it does not indicate that shrinking is available.
DDFXCAPS_OVERLAYSHRINKY
Supports arbitrary shrinking of a surface along the y-axis (vertically). This flag is valid only for DDSCAPS_OVERLAY surfaces. This flag indicates only the capabilities of a surface; it does not indicate that shrinking is available.
DDFXCAPS_OVERLAYSHRINKYN
Supports integer shrinking (×1, ×2, and so on) of a surface along the y-axis (vertically). This flag is valid only for DDSCAPS_OVERLAY surfaces. This flag indicates only the capabilities of a surface; it does not indicate that shrinking is available.
DDFXCAPS_OVERLAYSTRETCHX
Supports arbitrary stretching of a surface along the x-axis (horizontally). This flag is valid only for DDSCAPS_OVERLAY surfaces. This flag indicates only the capabilities of a surface; it does not indicate that stretching is available.
DDFXCAPS_OVERLAYSTRETCHXN
Supports integer stretching (×1, ×2, and so on) of a surface along the x-axis (horizontally). This flag is valid only for DDSCAPS_OVERLAY surfaces. This flag indicates only the capabilities of a surface; it does not indicate that stretching is available.
DDFXCAPS_OVERLAYSTRETCHY
Supports arbitrary stretching of a surface along the y-axis (vertically). This flag is valid only for DDSCAPS_OVERLAY surfaces. This flag indicates only the capabilities of a surface; it does not indicate that stretching is available.
DDFXCAPS_OVERLAYSTRETCHYN
Supports integer stretching (×1, ×2, and so on) of a surface along the y-axis (vertically). This flag is valid only for DDSCAPS_OVERLAY surfaces. This flag indicates only the capabilities of a surface; it does not indicate that stretching is available.
DDFXCAPS_OVERLAYTRANSFORM
Supports geometric transformations (or warps) for overlay sprites. Transformations are not currently supported for explicitly displayed overlay surfaces (those displayed with calls to IDirectDrawSurface4::UpdateOverlay).
dwFXAlphaCaps
Driver-specific alpha capabilities.
DDFXALPHACAPS_BLTALPHAEDGEBLEND
Supports alpha blending around the edge of a source color-keyed surface. Used for blit operations.
DDFXALPHACAPS_BLTALPHAPIXELS
Supports alpha information in pixel format. The bit depth of alpha information in the pixel format can be 1, 2, 4, or 8. The alpha value becomes more opaque as the alpha value increases. Regardless of the depth of the alpha information, 0 is always the fully transparent value. Used for blit operations.
DDFXALPHACAPS_BLTALPHAPIXELSNEG
Supports alpha information in pixel format. The bit depth of alpha information in the pixel format can be 1, 2, 4, or 8. The alpha value becomes more transparent as the alpha value increases. Regardless of the depth of the alpha information, 0 is always the fully opaque value. This flag can be used only if DDCAPS_ALPHA is set. Used for blit operations.
DDFXALPHACAPS_BLTALPHASURFACES
Supports alpha-only surfaces. The bit depth of an alpha-only surface can be 1, 2, 4, or 8. The alpha value becomes more opaque as the alpha value increases. Regardless of the depth of the alpha information, 0 is always the fully transparent value. Used for blit operations.
DDFXALPHACAPS_BLTALPHASURFACESNEG
Indicates that the alpha channel becomes more transparent as the alpha value increases. The depth of the alpha channel data can be 1, 2, 4, or 8. Regardless of the depth of the alpha information, 0 is always the fully opaque value. This flag can be set only if DDCAPS_ALPHA has been set. Used for blit operations.
DDFXALPHACAPS_OVERLAYALPHAEDGEBLEND
Supports alpha blending around the edge of a source color-keyed surface. Used for overlays.
DDFXALPHACAPS_OVERLAYALPHAPIXELS
Supports alpha information in pixel format. The bit depth of alpha information in pixel format can be 1, 2, 4, or 8. The alpha value becomes more opaque as the alpha value increases. Regardless of the depth of the alpha information, 0 is always the fully transparent value. Used for overlays.
DDFXALPHACAPS_OVERLAYALPHAPIXELSNEG
Supports alpha information in pixel format. The bit depth of alpha information in pixel format can be 1, 2, 4, or 8. The alpha value becomes more transparent as the alpha value increases. Regardless of the depth of the alpha information, 0 is always the fully opaque value. This flag can be used only if DDCAPS_ALPHA has been set. Used for overlays.
DDFXALPHACAPS_OVERLAYALPHASURFACES
Supports alpha-only surfaces. The bit depth of an alpha-only surface can be 1, 2, 4, or 8. The alpha value becomes more opaque as the alpha value increases. Regardless of the depth of the alpha information, 0 is always the fully transparent value. Used for overlays.
DDFXALPHACAPS_OVERLAYALPHASURFACESNEG
Indicates that the alpha channel becomes more transparent as the alpha value increases. The depth of the alpha channel data can be 1, 2, 4, or 8. Regardless of the depth of the alpha information, 0 is always the fully opaque value. This flag can be used only if DDCAPS_ALPHA has been set. Used for overlays.
dwPalCaps
Palette capabilities.
DDPCAPS_1BIT
Supports palettes that contain 1 bit color entries (two colors).
DDPCAPS_2BIT
Supports palettes that contain 2 bit color entries (four colors).
DDPCAPS_4BIT
Supports palettes that contain 4 bit color entries (16 colors).
DDPCAPS_8BIT
Supports palettes that contain 8 bit color entries (256 colors).
DDPCAPS_8BITENTRIES
Specifies an index to an 8-bit color index. This field is valid only when used with the DDPCAPS_1BIT, DDPCAPS_2BIT, or DDPCAPS_4BIT capability and when the target surface is in 8 bits per pixel (bpp). Each color entry is 1 byte long and is an index to an 8-bpp palette on the destination surface.
DDPCAPS_ALPHA
Supports palettes that include an alpha component. For alpha-capable palettes, the peFlags member of for each PALETTEENTRY structure the palette contains is to be interpreted as a single 8-bit alpha value (in addition to the color data in the peRed, peGreen, and peBlue members). A palette created with this flag can only be attached to a texture surface.
DDPCAPS_ALLOW256
Supports palettes that can have all 256 entries defined.
DDPCAPS_PRIMARYSURFACE
Indicates that the palette is attached to the primary surface. Changing the palette has an immediate effect on the display unless the DDPCAPS_VSYNC capability is specified and supported.
DDPCAPS_PRIMARYSURFACELEFT
Indicates that the palette is attached to the primary surface on the left. Changing the palette has an immediate effect on the display unless the DDPCAPS_VSYNC capability is specified and supported.
DDPCAPS_VSYNC
Indicates that the palette can be modified synchronously with the monitor's refresh rate.
dwSVCaps
Stereo vision capabilities.
DDSVCAPS_ENIGMA
Indicates that the stereo view is accomplished using Enigma encoding.
DDSVCAPS_FLICKER
Indicates that the stereo view is accomplished using high-frequency flickering.
DDSVCAPS_REDBLUE
Indicates that the stereo view is accomplished when the viewer looks at the image through red and blue filters placed over the left and right eyes. All images must adapt their color spaces for this process.
DDSVCAPS_SPLIT
Indicates that the stereo view is accomplished with split-screen technology.
dwAlphaBltConstBitDepths
DDBD_2, DDBD_4, or DDBD_8. (Indicates 2-, 4-, or 8-bits per pixel.)
dwAlphaBltPixelBitDepths
DDBD_1, DDBD_2, DDBD_4, or DDBD_8. (Indicates 1-, 2-, 4-, or 8-bits per pixel.)
dwAlphaBltSurfaceBitDepths
DDBD_1, DDBD_2, DDBD_4, or DDBD_8. (Indicates 1-, 2-, 4-, or 8-bits per pixel.)
dwAlphaOverlayConstBitDepths
DDBD_2, DDBD_4, or DDBD_8. (Indicates 2-, 4-, or 8-bits per pixel.)
dwAlphaOverlayPixelBitDepths
DDBD_1, DDBD_2, DDBD_4, or DDBD_8. (Indicates 1-, 2-, 4-, or 8-bits per pixel.)
dwAlphaOverlaySurfaceBitDepths
DDBD_1, DDBD_2, DDBD_4, or DDBD_8. (Indicates 1-, 2-, 4-, or 8-bits per pixel.)
dwZBufferBitDepths
DDBD_8, DDBD_16, DDBD_24, or DDBD_32. (Indicates 8-, 16-, 24-, 32-bits per pixel.) This member is obsolete for DirectX 6.0 and later. Use the IDirect3D3::EnumZBufferFormats to retrieve information about supported depth buffer formats.
dwVidMemTotal
Total amount of display memory on the device, in bytes, less memory reserved for the primary surface and any private data structures reserved by the driver. (This value is the same as the total video memory reported by the IDirectDraw4::GetAvailableVidMem method.)
dwVidMemFree
Free display memory. This value equals the value in dwVidMemTotal, less any memory currently allocated by the application for surfaces. Unlike the GetAvailableVidMem method, which reports the memory available for a particular type of surface (like a texture), this value reflects the memory available for any type of surface.
dwMaxVisibleOverlays
Maximum number of visible overlays or overlay sprites.
dwCurrVisibleOverlays
Current number of visible overlays or overlay sprites.
dwNumFourCCCodes
Number of FourCC codes.
dwAlignBoundarySrc
Source rectangle alignment for an overlay surface, in pixels.
dwAlignSizeSrc
Source rectangle size alignment for an overlay surface, in pixels. Overlay source rectangles must have a pixel width that is a multiple of this value.
dwAlignBoundaryDest
Destination rectangle alignment for an overlay surface, in pixels.
dwAlignSizeDest
Destination rectangle size alignment for an overlay surface, in pixels. Overlay destination rectangles must have a pixel width that is a multiple of this value.
dwAlignStrideAlign
Stride alignment.
dwRops[DD_ROP_SPACE]
Raster operations supported.
dwReservedCaps
Reserved. Prior to DirectX 6.0, this member contained general surface capabilities, which are now contained in the ddsCaps member (a DDSCAPS2 structure).
dwMinOverlayStretch and dwMaxOverlayStretch
Minimum and maximum overlay stretch factors multiplied by 1000. For example, 1.3 = 1300.
dwMinLiveVideoStretch and dwMaxLiveVideoStretch
These members are obsolete; do not use.
dwMinHwCodecStretch and dwMaxHwCodecStretch
These members are obsolete; do not use.
dwReserved1, dwReserved2, and dwReserved3
Reserved for future use.
dwSVBCaps
Driver-specific capabilities for system-memory-to-display-memory blits. Valid flags are identical to the blit-related flags used with the dwCaps member.
dwSVBCKeyCaps
Driver color-key capabilities for system-memory-to-display-memory blits. Valid flags are identical to the blit-related flags used with for the dwCKeyCaps member.
dwSVBFXCaps
Driver FX capabilities for system-memory-to-display-memory blits. Valid flags are identical to the blit-related flags used with the dwFXCaps member.
dwSVBRops[DD_ROP_SPACE]
Raster operations supported for system-memory-to-display-memory blits.
dwVSBCaps
Driver-specific capabilities for display-memory-to-system-memory blits. Valid flags are identical to the blit-related flags used with the dwCaps member.
dwVSBCKeyCaps
Driver color-key capabilities for display-memory-to-system-memory blits. Valid flags are identical to the blit-related flags used with for the dwCKeyCaps member.
dwVSBFXCaps
Driver FX capabilities for display-memory-to-system-memory blits. Valid flags are identical to the blit-related flags used with the dwFXCaps member.
dwVSBRops[DD_ROP_SPACE]
Raster operations supported for display-memory-to-system-memory blits.
dwSSBCaps
Driver-specific capabilities for system-memory-to-system-memory blits. Valid flags are identical to the blit-related flags used with the dwCaps member.
dwSSBCKeyCaps
Driver color-key capabilities for system-memory-to-system-memory blits. Valid flags are identical to the blit-related flags used with for the dwCKeyCaps member.
dwSSBCFXCaps
Driver FX capabilities for system-memory-to-system-memory blits. Valid flags are identical to the blit-related flags used with the dwFXCaps member.
dwSSBRops[DD_ROP_SPACE]
Raster operations supported for system-memory-to-system-memory blits.
dwMaxVideoPorts
Maximum number of live video ports.
dwCurrVideoPorts
Current number of live video ports.
dwSVBCaps2
More driver-specific capabilities for system-memory-to-video-memory blits. Valid flags are identical to the blit-related flags used with the dwCaps2 member.
dwNLVBCaps
Driver-specific capabilities for nonlocal-to-local video memory blits. Valid flags are identical to the blit-related flags used with the dwCaps member.
dwNLVBCaps2
More driver-specific capabilities for nonlocal-to-local video memory blits. Valid flags are identical to the blit-related flags used with the dwCaps2 member.
dwNLVBCKeyCaps
Driver color-key capabilities for nonlocal-to-local video memory blits. Valid flags are identical to the blit-related flags used with for the dwCKeyCaps member.
dwNLVBFXCaps
Driver FX capabilities for nonlocal-to-local video memory blits. Valid flags are identical to the blit-related flags used with the dwFXCaps member.
dwNLVBRops[DD_ROP_SPACE]
Raster operations supported for nonlocal-to-local video memory blits.
ddsCaps
DDSCAPS2 structure with general surface capabilities.

Remarks

For backward compatibility with previous versions of DirectX, the ddraw.h header file contains multiple definitions for the DDCAPS structure. The version that passes the preprocessor is determined by the value of the DIRECTDRAW_VERSION constant. For details, see Component Version Constants.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.


DDCOLORCONTROL

The DDCOLORCONTROL structure defines the color controls associated with a DirectDrawVideoPortObject, an overlay surface, or a primary surface.

typedef struct _DDCOLORCONTROL {
    DWORD   dwSize;
    DWORD   dwFlags;
    LONG    lBrightness;
    LONG    lContrast;
    LONG    lHue;
    LONG    lSaturation;
    LONG    lSharpness;
    LONG    lGamma;
    LONG    lColorEnable;
    DWORD   dwReserved1;
} DDCOLORCONTROL, FAR *LPDDCOLORCONTROL;

Members

dwSize
The the size of the structure, in bytes. This member must be initialized before use.
dwFlags
Flags specifying which structure members contain valid data . When the structure is returned by the IDirectDrawColorControl::GetColorControls method, it also indicates which options are supported by the device.
DDCOLOR_BRIGHTNESS
The lBrightness member contains valid data.
DDCOLOR_COLORENABLE
The lColorEnable member contains valid data.
DDCOLOR_CONTRAST
The lContrast member contains valid data.
DDCOLOR_GAMMA
The lGamma member contains valid data.
DDCOLOR_HUE
The lHue member contains valid data.
DDCOLOR_SATURATION
The lSaturation member contains valid data.
DDCOLOR_SHARPNESS
The lSharpness member contains valid data.
lBrightness
Luminance intensity, in IRE units times 100. The valid range is 0 to 10,000. The default is 750, which translates to 7.5 IRE.
lContrast
Relative difference between higher and lower intensity luminance values in IRE units times 100. The valid range is 0 to 20,000. The default value is 10,000 (100 IRE). Higher values of contrast cause darker luminance values to tend towards black, and cause lighter luminance values to tend towards white. Lower values of contrast cause all luminance values to move towards the middle luminance values.
lHue
Phase relationship of the chrominance components. Hue is specified in degrees and the valid range is -180 to 180. The default is 0.
lSaturation
Color intensity, in IRE units times 100. The valid range is 0 to 20,000. The default value is 10,000, which translates to 100 IRE.
lSharpness
Sharpness in arbitrary units. The valid range is 0 to 10. The default value is 5.
lGamma
Controls the amount of gamma correction applied to the luminance values. The valid range is 1 to 500 gamma units, with a default of 1.
lColorEnable
Flag indicating whether color is used. If this member is zero, color is not used; if it is 1, then color is used. The default value is 1.
dwReserved1
This member is reserved.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.


DDDEVICEIDENTIFIER

The DDDEVICEIDENTIFIER structure is passed to the IDirectDraw4::GetDeviceIdentifier method to obtain information about a device.

typedef struct tagDDDEVICEIDENTIFIER {
    char    szDriver[MAX_DDDEVICEID_STRING];
    char    szDescription[MAX_DDDEVICEID_STRING];
    LARGE_INTEGER  liDriverVersion;
    DWORD   dwVendorId;
    DWORD   dwDeviceId;
    DWORD   dwSubSysId;
    DWORD   dwRevision;
    GUID    guidDeviceIdentifier;
} DDDEVICEIDENTIFIER, * LPDDDEVICEIDENTIFIER;

Members

szDriver
Name of the driver.
szDescription
Description of the driver.
liDriverVersion
Version of the driver. It is legal to do less than and greater than comparisons on the whole 64 bits. Caution should be exercised if you use this element to identify problematic drivers. It is recommended that guidDeviceIdentifier be used for this purpose.

The data takes the following form:

wProduct = HIWORD(liDriverVersion.HighPart)
wVersion = LOWORD(liDriverVersion.HighPart)
wSubVersion = HIWORD(liDriverVersion.LowPart)
wBuild = LOWORD(liDriverVersion.LowPart)
dwVendorId
Identifier of the manufacturer. Can be 0 if unknown.
dwDeviceId
Identifier of the type of chipset. Can be 0 if unknown.
dwSubSysId
Identifier of the subsystem. Typically this means the particular board. Can be 0 if unknown.
dwRevision
Identifier of the revision level of the chipset. Can be 0 if unknown.
guidDeviceIdentifier
Unique identifier for the driver/chipset pair. Use this value if you wish to track changes to the driver/chipset in order to reprofile the graphics subsystem. It can also be used to identify particular problematic drivers.

Remarks

The values in szDriver and szDescription are for presentation to the user only. They should not be used to identify particular drivers, because different strings might be associated with the same device, or the same driver from different vendors might be described differently.

The dwVendorId, dwDeviceId, dwSubSysId, and dwRevision members can be used to identify particular chipsets, but use extreme caution.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.


DDGAMMARAMP

The DDGAMMARAMP structure contains red, green, and blue ramp data for the IDirectDrawGammaControl::GetGammaRamp and IDirectDrawGammaControl::SetGammaRamp methods.

typedef struct _DDGAMMARAMP {
    WORD red[256];
    WORD green[256];
    WORD blue[256];
} DDGAMMARAMP, FAR * LPDDGAMMARAMP;

Members

red, green, and blue
Array of 256 WORD elements that describe the red, green, and blue gamma ramps.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.

See Also

Gamma and Color Controls


DDCOLORKEY

The DDCOLORKEY structure describes a source color key, destination color key, or color space. A color key is specified if the low and high range values are the same. This structure is used with the IDirectDrawSurface4::GetColorKey and IDirectDrawSurface4::SetColorKey methods.

typedef struct _DDCOLORKEY{
    DWORD dwColorSpaceLowValue;
    DWORD dwColorSpaceHighValue;
} DDCOLORKEY,FAR* LPDDCOLORKEY;

Members

dwColorSpaceLowValue
Low value, inclusive, of the color range that is to be used as the color key.
dwColorSpaceHighValue
High value, inclusive, of the color range that is to be used as the color key.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.


DDOVERLAYFX

The DDOVERLAYFX structure passes override information to the IDirectDrawSurface4::UpdateOverlay method.

typedef struct _DDOVERLAYFX{
    DWORD dwSize;
    DWORD dwAlphaEdgeBlendBitDepth;
    DWORD dwAlphaEdgeBlend;
    DWORD dwReserved;
    DWORD dwAlphaDestConstBitDepth;
    union
    {
        DWORD               dwAlphaDestConst;
        LPDIRECTDRAWSURFACE lpDDSAlphaDest;
    } DUMMYUNIONNAMEN(1);
    DWORD dwAlphaSrcConstBitDepth;
    union
    {
        DWORD               dwAlphaSrcConst;
        LPDIRECTDRAWSURFACE lpDDSAlphaSrc;
    } DUMMYUNIONNAMEN(2);
    DDCOLORKEY dckDestColorkey;
    DDCOLORKEY dckSrcColorkey;

    DWORD dwDDFX;
    DWORD dwFlags;
} DDOVERLAYFX,FAR *LPDDOVERLAYFX;

Members

dwSize
Size of the structure, in bytes. This members must be initialized before the structure is used.
dwAlphaEdgeBlendBitDepth
Bit depth used to specify the constant for an alpha edge blend.
dwAlphaEdgeBlend
Constant to use as the alpha for an edge blend.
dwReserved
Reserved for future use.
dwAlphaDestConstBitDepth
Bit depth used to specify the alpha constant for a destination.
dwAlphaDestConst
Constant to use as the alpha channel for a destination.
lpDDSAlphaDest
Address of a surface to use as the alpha channel for a destination.
dwAlphaSrcConstBitDepth
Bit depth used to specify the alpha constant for a source.
dwAlphaSrcConst
Constant to use as the alpha channel for a source.
lpDDSAlphaSrc
Address of a surface to use as the alpha channel for a source.
dckDestColorkey
Destination color key override.
dckSrcColorkey
Source color key override.
dwDDFX
Overlay FX flags.
DDOVERFX_ARITHSTRETCHY
If stretching, use arithmetic stretching along the y-axis for this overlay.
DDOVERFX_MIRRORLEFTRIGHT
Mirror the overlay around the vertical axis.
DDOVERFX_MIRRORUPDOWN
Mirror the overlay around the horizontal axis.
dwFlags
This member is currently not used and must be set to 0.

Remarks

The unions in this structure have been updated to work with compilers that don't support nameless unions. If your compiler doesn't support nameless unions, define the NONAMELESSUNION token before including the Ddraw.h header file.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.


DDPIXELFORMAT

The DDPIXELFORMAT structure describes the pixel format of a DirectDrawSurface object for the IDirectDrawSurface4::GetPixelFormat method.

typedef struct _DDPIXELFORMAT{
    DWORD dwSize;
    DWORD dwFlags;
    DWORD dwFourCC;
    union
    {
        DWORD dwRGBBitCount;
        DWORD dwYUVBitCount;
        DWORD dwZBufferBitDepth;
        DWORD dwAlphaBitDepth;
        DWORD dwLuminanceBitCount; // new for DirectX 6.0
        DWORD dwBumpBitCount;      // new for DirectX 6.0
    } DUMMYUNIONNAMEN(1);
    union
    {
        DWORD dwRBitMask;
        DWORD dwYBitMask;
        DWORD dwStencilBitDepth;   // new for DirectX 6.0
        DWORD dwLuminanceBitMask;  // new for DirectX 6.0
        DWORD dwBumpDuBitMask;     // new for DirectX 6.0
    } DUMMYUNIONNAMEN(2);
    union
    {
        DWORD dwGBitMask;
        DWORD dwUBitMask;
        DWORD dwZBitMask;          // new for DirectX 6.0
        DWORD dwBumpDvBitMask;     // new for DirectX 6.0
    } DUMMYUNIONNAMEN(3);
    union
    {
        DWORD dwBBitMask;
        DWORD dwVBitMask;
        DWORD dwStencilBitMask;    // new for DirectX 6.0
        DWORD dwBumpLuminanceBitMask;  // new for DirectX 6.0
    } DUMMYUNIONNAMEN(4);
    union
    {
        DWORD dwRGBAlphaBitMask;
        DWORD dwYUVAlphaBitMask;
        DWORD dwLuminanceAlphaBitMask; // new for DirectX 6.0
        DWORD dwRGBZBitMask;
        DWORD dwYUVZBitMask;
    } DUMMYUNIONNAMEN(5);
} DDPIXELFORMAT, FAR* LPDDPIXELFORMAT;

Members

dwSize
Size of the structure, in bytes. This member must be initialized before the structure is used.
dwFlags
Optional control flags.
DDPF_ALPHA
The pixel format describes an alpha-only surface.
DDPF_ALPHAPIXELS
The surface has alpha channel information in the pixel format.
DDPF_ALPHAPREMULT
The surface uses the premultiplied alpha format. That is, the color components in each pixel are premultiplied by the alpha component.
DDPF_BUMPLUMINANCE
The luminance data in the pixel format is valid, and the dwLuminanceBitMask member describes valid luminance bits for a luminance-only or luminance-alpha surface.
DDPF_BUMPDUDV
Bump-map data in the pixel format is valid. Bump-map information is in the dwBumpBitCount, dwBumpDuBitMask, dwBumpDvBitMask, and dwBumpLuminanceBitMask members.
DDPF_COMPRESSED
The surface will accept pixel data in the specified format and compress it during the write operation.
DDPF_FOURCC
The dwFourCC member is valid and contains a FOURCC code describing a non-RGB pixel format.
DDPF_LUMINANCE
The pixel format describes a luminance-only or luminance-alpha surface.
DDPF_PALETTEINDEXED1
DDPF_PALETTEINDEXED2
DDPF_PALETTEINDEXED4
DDPF_PALETTEINDEXED8
The surface is 1-, 2-, 4-, or 8-bit color indexed.
DDPF_PALETTEINDEXEDTO8
The surface is 1-, 2-, or 4-bit color indexed to an 8-bit palette.
DDPF_RGB
The RGB data in the pixel format structure is valid.
DDPF_RGBTOYUV
The surface will accept RGB data and translate it during the write operation to YUV data. The format of the data to be written will be contained in the pixel format structure. The DDPF_RGB flag will be set.
DDPF_STENCILBUFFER
The surface encodes stencil and depth information in each pixel of the z-buffer. This flag can only be used if the DDPF_ZBUFFER flag is also specified.
DDPF_YUV
The YUV data in the pixel format structure is valid.
DDPF_ZBUFFER
The pixel format describes a z-buffer surface.
DDPF_ZPIXELS
The surface contains z information in the pixels.
dwFourCC
FourCC code. For more information see, Four Character Codes (FOURCC).
dwRGBBitCount
RGB bits per pixel (4, 8, 16, 24, or 32).
dwYUVBitCount
YUV bits per pixel (4, 8, 16, 24, or 32).
dwZBufferBitDepth
Z-buffer bit depth (8, 16, 24, or 32).
dwAlphaBitDepth
Alpha channel bit depth (1, 2, 4, or 8) for an alpha-only surface (DDPF_ALPHA). For pixel formats that contain alpha information interleaved with color data (DDPF_ALPHAPIXELS), you must count the bits in the dwRGBAlphaBitMask member to obtain the bit-depth of the alpha component. For more information, see Remarks.
dwLuminanceBitCount
Total luminance bits per pixel. This member applies only to luminance-only and luminance-alpha surfaces.
dwBumpBitCount
Total bump-map bits per pixel in a bump-map surface.
dwRBitMask
Mask for red bits.
dwYBitMask
Mask for Y bits.
dwStencilBitDepth
Bit depth of the stencil buffer. This member specifies how many bits are reserved within each pixel of the z-buffer for stencil information (the total number of z-bits is equal to dwZBufferBitDepth minus dwStencilBitDepth).
dwLuminanceBitMask
Mask for luminance bits.
dwBumpDuBitMask
Mask for bump-map UΔ bits.
dwGBitMask
Mask for green bits.
dwUBitMask
Mask for U bits.
dwZBitMask
Mask for z bits.
dwBumpDvBitMask
Mask for bump-map VΔ bits.
dwBBitMask
Mask for blue bits.
dwVBitMask
Mask for V bits.
dwStencilBitMask
Mask for stencil bits within each z-buffer pixel.
dwBumpLuminanceBitMask
Mask for luminance in a bump-map pixel.
dwRGBAlphaBitMask and dwYUVAlphaBitMask and dwLuminanceAlphaBitMask
Masks for alpha channel.
dwRGBZBitMask and dwYUVZBitMask
Masks for z channel.

Remarks

The dwAlphaBitDepth member reflects the bit depth of an alpha-only pixel format (DDPF_ALPHA). For pixel formats that include the alpha component with color components (DDPF_ALPHAPIXELS), the alpha bit depth is obtained by counting the bits in the various mask members. The following example function returns the number of bits set in a given bitmask:

WORD GetNumberOfBits( DWORD dwMask )
{
    WORD wBits = 0;
    while( dwMask )
    {
        dwMask = dwMask & ( dwMask - 1 );
        wBits++;
    }
    return wBits;
}

The unions in this structure have been updated to work with compilers that don't support nameless unions. If your compiler doesn't support nameless unions, define the NONAMELESSUNION token before including the Ddraw.h header file.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.

See Also

Off-Screen Surface Formats


DDSCAPS

The DDSCAPS structure defines the capabilities of a DirectDrawSurface object. This structure is part of the DDCAPS and DDSURFACEDESC structures.

typedef struct _DDSCAPS{
    DWORD dwCaps;
} DDSCAPS, FAR* LPDDSCAPS;

Members

dwCaps
Capabilities of the surface. One or more of the following flags:
DDSCAPS_3D
Unsupported. Use the DDSCAPS_3DDEVICE instead.
DDSCAPS_3DDEVICE
Indicates that this surface can be used for 3-D rendering. Applications can use this flag to ensure that a device that can only render to a certain heap has off-screen surfaces allocated from the correct heap. If this flag is set for a heap, the surface is not allocated from that heap.
DDSCAPS_ALLOCONLOAD
Indicates that memory for the surface is not allocated until the surface is loaded by using the IDirect3DTexture2::Load.
DDSCAPS_ALPHA
Indicates that this surface contains alpha-only information.
DDSCAPS_BACKBUFFER
Indicates that this surface is the back buffer of a surface flipping structure. Typically, this capability is set by the CreateSurface method when the DDSCAPS_FLIP flag is used. Only the surface that immediately precedes the DDSCAPS_FRONTBUFFER surface has this capability set. The other surfaces are identified as back buffers by the presence of the DDSCAPS_FLIP flag, their attachment order, and the absence of the DDSCAPS_FRONTBUFFER and DDSCAPS_BACKBUFFER capabilities. If this capability is sent to the CreateSurface method, a stand-alone back buffer is being created. After this method is called, this surface could be attached to a front buffer, another back buffer, or both to form a flipping surface structure. For more information, see IDirectDrawSurface4::AddAttachedSurface. DirectDraw supports an arbitrary number of surfaces in a flipping structure.
DDSCAPS_COMPLEX
Indicates that a complex surface is being described. A complex surface results in the creation of more than one surface. The additional surfaces are attached to the root surface. The complex structure can be destroyed only by destroying the root.
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. DirectDraw sets the DDSCAPS_FRONTBUFFER bit on the front-buffer surface and the DDSCAPS_BACKBUFFER bit on the surface adjacent to the front-buffer surface. The dwBackBufferCount member of the DDSURFACEDESC structure must be set to at least 1 in order for the method call to succeed. The DDSCAPS_COMPLEX capability must always be set when creating multiple surfaces by using the CreateSurface method.
DDSCAPS_FRONTBUFFER
Indicates that this surface is the front buffer of a surface flipping structure. This flag is typically set by the CreateSurface method when the DDSCAPS_FLIP capability is set. If this capability is sent to the CreateSurface method, a stand-alone front buffer is created. This surface will not have the DDSCAPS_FLIP capability. It can be attached to other back buffers to form a flipping structure by using IDirectDrawSurface4::AddAttachedSurface.
DDSCAPS_HWCODEC
Indicates that this surface should be able to have a stream decompressed to it by the hardware.
DDSCAPS_LIVEVIDEO
Indicates that this surface should be able to receive live video.
DDSCAPS_LOCALVIDMEM
Indicates that this surface exists in true, local video memory rather than non-local video memory. If this flag is specified then DDSCAPS_VIDEOMEMORY must be specified as well. This flag cannot be used with the DDSCAPS_NONLOCALVIDMEM flag.
DDSCAPS_MIPMAP
Indicates that this surface is one level of a mipmap. This surface will be attached to other DDSCAPS_MIPMAP surfaces to form the mipmap. This can be done explicitly by creating a number of surfaces and attaching them by using the IDirectDrawSurface4::AddAttachedSurface method, or implicitly by the CreateSurface method. If this capability is set, DDSCAPS_TEXTURE must also be set.
DDSCAPS_MODEX
Indicates that this surface is a 320×200 or 320×240 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, then DDSCAPS_VIDEOMEMORY flag must be specified as well. This cannot be used with the DDSCAPS_LOCALVIDMEM flag.
DDSCAPS_OFFSCREENPLAIN
Indicates that this surface is any off-screen surface that is not an overlay, texture, z-buffer, front-buffer, back-buffer, or alpha surface. It is used to identify plain surfaces.
DDSCAPS_OPTIMIZED
Not currently implemented.
DDSCAPS_OVERLAY
Indicates that this surface is an overlay. It may or may not be directly visible depending on whether it is currently being overlaid onto the primary surface. DDSCAPS_VISIBLE can be used to determine if it is being overlaid at the moment.
DDSCAPS_OWNDC
Indicates that this surface will have a device context (DC) association for a long period.
DDSCAPS_PALETTE
Indicates that this device driver allows unique DirectDrawPalette objects to be created and attached to this surface.
DDSCAPS_PRIMARYSURFACE
Indicates the surface is the primary surface. It represents what is visible to the user at the moment.
DDSCAPS_PRIMARYSURFACELEFT
Indicates that this surface is the primary surface for the left eye. It represents what is visible to the user's left eye at the moment. When this surface is created, the surface with the DDSCAPS_PRIMARYSURFACE capability represents what is seen by the user's right eye.
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_TEXTURE
Indicates that this surface can be used as a 3-D texture. It does not indicate whether the surface is being used for that purpose.
DDSCAPS_VIDEOMEMORY
Indicates that this surface exists in display memory.
DDSCAPS_VIDEOPORT
Indicates that this surface can receive data from a video port.
DDSCAPS_VISIBLE
Indicates that changes made to this surface are immediately visible. It is always set for the primary surface, as well as for overlays while they are being overlaid and texture maps while they are being textured.
DDSCAPS_WRITEONLY
Indicates that only write access is permitted to the surface. Read access from the surface may generate a general protection (GP) fault, but the read results from this surface will not be meaningful.
DDSCAPS_ZBUFFER
Indicates that this surface is the z-buffer. The z-buffer contains information that cannot be displayed. Instead, it contains bit-depth information that is used to determine which pixels are visible and which are obscured.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.


DDSCAPS2

The DDSCAPS2 structure defines the capabilities of a DirectDrawSurface object. This structure is part of the DDSURFACEDESC2 structure.

typedef struct _DDSCAPS2 {
    DWORD    dwCaps;   // Surface capabilities
    DWORD    dwCaps2;  // More surface capabilities
    DWORD    dwCaps3;  // Not currently used
    DWORD    dwCaps4;  // .
} DDSCAPS2, FAR* LPDDSCAPS2;

Members

dwCaps
One or more flag values representing the capabilities of the surface. (The flags in this member are identical to those in the corresponding member of the DDSCAPS structure.)
DDSCAPS_3D
Unsupported. Use the DDSCAPS_3DDEVICE instead.
DDSCAPS_3DDEVICE
Indicates that this surface can be used for 3-D rendering. Applications can use this flag to ensure that a device that can only render to a certain heap has off-screen surfaces allocated from the correct heap. If this flag is set for a heap, the surface is not allocated from that heap.
DDSCAPS_ALLOCONLOAD
Indicates that memory for the surface is not allocated until the surface is loaded by using the IDirect3DTexture2::Load.
DDSCAPS_ALPHA
Indicates that this surface contains alpha-only information.
DDSCAPS_BACKBUFFER
Indicates that this surface is the back buffer of a surface flipping structure. Typically, this capability is set by the CreateSurface method when the DDSCAPS_FLIP flag is used. Only the surface that immediately precedes the DDSCAPS_FRONTBUFFER surface has this capability set. The other surfaces are identified as back buffers by the presence of the DDSCAPS_FLIP flag, their attachment order, and the absence of the DDSCAPS_FRONTBUFFER and DDSCAPS_BACKBUFFER capabilities. If this capability is sent to the CreateSurface method, a stand-alone back buffer is being created. After this method is called, this surface could be attached to a front buffer, another back buffer, or both to form a flipping surface structure. For more information, see IDirectDrawSurface4::AddAttachedSurface. DirectDraw supports an arbitrary number of surfaces in a flipping structure.
DDSCAPS_COMPLEX
Indicates that a complex surface is being described. A complex surface results in the creation of more than one surface. The additional surfaces are attached to the root surface. The complex structure can be destroyed only by destroying the root.
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. DirectDraw sets the DDSCAPS_FRONTBUFFER bit on the front-buffer surface and the DDSCAPS_BACKBUFFER bit on the surface adjacent to the front-buffer surface. The dwBackBufferCount member of the DDSURFACEDESC structure must be set to at least 1 in order for the method call to succeed. The DDSCAPS_COMPLEX capability must always be set when creating multiple surfaces by using the CreateSurface method.
DDSCAPS_FRONTBUFFER
Indicates that this surface is the front buffer of a surface flipping structure. This flag is typically set by the CreateSurface method when the DDSCAPS_FLIP capability is set. If this capability is sent to the CreateSurface method, a stand-alone front buffer is created. This surface will not have the DDSCAPS_FLIP capability. It can be attached to other back buffers to form a flipping structure by using IDirectDrawSurface4::AddAttachedSurface.
DDSCAPS_HWCODEC
Indicates that this surface should be able to have a stream decompressed to it by the hardware.
DDSCAPS_LIVEVIDEO
Indicates that this surface should be able to receive live video.
DDSCAPS_LOCALVIDMEM
Indicates that this surface exists in true, local video memory rather than non-local video memory. If this flag is specified then DDSCAPS_VIDEOMEMORY must be specified as well. This flag cannot be used with the DDSCAPS_NONLOCALVIDMEM flag.
DDSCAPS_MIPMAP
Indicates that this surface is one level of a mipmap. This surface will be attached to other DDSCAPS_MIPMAP surfaces to form the mipmap. This can be done explicitly by creating a number of surfaces and attaching them by using the IDirectDrawSurface4::AddAttachedSurface method, or implicitly by the CreateSurface method. If this capability is set, DDSCAPS_TEXTURE must also be set.
DDSCAPS_MODEX
Indicates that this surface is a 320×200 or 320×240 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, then DDSCAPS_VIDEOMEMORY flag must be specified as well. This cannot be used with the DDSCAPS_LOCALVIDMEM flag.
DDSCAPS_OFFSCREENPLAIN
Indicates that this surface is any off-screen surface that is not an overlay, texture, z-buffer, front-buffer, back-buffer, or alpha surface. It is used to identify plain surfaces.
DDSCAPS_OPTIMIZED
Not currently implemented.
DDSCAPS_OVERLAY
Indicates that this surface is an overlay. It may or may not be directly visible depending on whether it is currently being overlaid onto the primary surface. DDSCAPS_VISIBLE can be used to determine if it is being overlaid at the moment.
DDSCAPS_OWNDC
Indicates that this surface will have a device context (DC) association for a long period.
DDSCAPS_PALETTE
Indicates that this device driver allows unique DirectDrawPalette objects to be created and attached to this surface.
DDSCAPS_PRIMARYSURFACE
Indicates the surface is the primary surface. It represents what is visible to the user at the moment.
DDSCAPS_PRIMARYSURFACELEFT
Indicates that this surface is the primary surface for the left eye. It represents what is visible to the user's left eye at the moment. When this surface is created, the surface with the DDSCAPS_PRIMARYSURFACE capability represents what is seen by the user's right eye.
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_TEXTURE
Indicates that this surface can be used as a 3-D texture. It does not indicate whether the surface is being used for that purpose.
DDSCAPS_VIDEOMEMORY
Indicates that this surface exists in display memory.
DDSCAPS_VIDEOPORT
Indicates that this surface can receive data from a video port.
DDSCAPS_VISIBLE
Indicates that changes made to this surface are immediately visible. It is always set for the primary surface, as well as for overlays while they are being overlaid and texture maps while they are being textured.
DDSCAPS_WRITEONLY
Indicates that only write access is permitted to the surface. Read access from the surface may generate a general protection (GP) fault, but the read results from this surface will not be meaningful.
DDSCAPS_ZBUFFER
Indicates that this surface is the z-buffer. The z-buffer contains information that cannot be displayed. Instead, it contains bit-depth information that is used to determine which pixels are visible and which are obscured.
dwCaps2
Additional surface capabilities. This member can contain one or more of the following capability flags or, when using this structure with the IDirectDrawSurface4::SetSurfaceDesc method, this member can contain an additional flag to indicate how the surface memory was allocated:
Capability flags
DDSCAPS2_HARDWAREDEINTERLACE
Indicates that this surface will receive data from a video port using the de-interlacing hardware. This allows the driver to allocate memory for any extra buffers that may be required. The DDSCAPS_VIDEOPORT and DDSCAPS_OVERLAY flags must also be set.
DDSCAPS2_HINTANTIALIASING
Indicates that the application intends to use antialiasing. Only valid if DDSCAPS_3DDEVICE is also set.
DDSCAPS2_HINTDYNAMIC
Indicates to the driver that this surface will be locked very frequently (for procedural textures, dynamic light maps, and so on). This flag can only be used for texture surfaces (DDSCAPS_TEXTURE flag set in the dwCaps member). This flag cannot be used with the DDSCAPS2_HINTSTATIC or DDSCAPS2_OPAQUE flags.
DDSCAPS2_HINTSTATIC
Indicates to the driver that this surface can be reordered or retiled on load. This operation will not change the size of the texture. It is relatively fast and symmetrical, since the application may lock these bits (although it will take a performance hit when doing so).

This flag can only be used for texture surfaces (DDSCAPS_TEXTURE flag set in the dwCaps member). This flag cannot be used with the DDSCAPS2_HINTDYNAMIC or DDSCAPS2_OPAQUE flags.

DDSCAPS2_OPAQUE
Indicates to the driver that this surface will never be locked again. The driver is free to optimize this surface by retiling and actual compression. Such a surface cannot be locked or used in blit operations, attempts to lock or blit a surface with this capability will fail. This flag can only be used for texture surfaces (DDSCAPS_TEXTURE flag set in the dwCaps member). This flag cannot be used with the DDSCAPS2_HINTDYNAMIC or DDSCAPS2_HINTSTATIC flags.
DDSCAPS2_TEXTUREMANAGE
Indicates that the client would like this texture surface to be managed by DirectDraw and Direct3D Immediate Mode. This flag can only be used for texture surfaces (DDSCAPS_TEXTURE flag set in the dwCaps member). For more information, see Automatic Texture Management in the Direct3D Immediate Mode documentation. Do not use this flag if your application uses Direct3D Retained Mode. Instead, create textures in system memory and allow Retained Mode to manage them.
dwCaps3 and dwCaps4
Not currently used.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.


DDSURFACEDESC

The DDSURFACEDESC structure contains a description of a surface. This structure is passed to the IDirectDraw2::CreateSurface method. The relevant members differ for each potential type of surface.

When using the IDirectDraw4 interface, this structure is superseded by the DDSURFACEDESC2 structure.

typedef struct _DDSURFACEDESC {
    DWORD          dwSize;
    DWORD          dwFlags;
    DWORD          dwHeight;
    DWORD          dwWidth;
    union
    {
        LONG       lPitch;
        DWORD      dwLinearSize;
    };
    DWORD          dwBackBufferCount;
    union
    {
        DWORD      dwMipMapCount;
        DWORD      dwZBufferBitDepth;
        DWORD      dwRefreshRate;
    };
    DWORD          dwAlphaBitDepth;
    DWORD          dwReserved;
    LPVOID         lpSurface;
    DDCOLORKEY     ddckCKDestOverlay;
    DDCOLORKEY     ddckCKDestBlt;
    DDCOLORKEY     ddckCKSrcOverlay;
    DDCOLORKEY     ddckCKSrcBlt;
    DDPIXELFORMAT  ddpfPixelFormat;
    DDSCAPS        ddsCaps;
} DDSURFACEDESC, FAR* LPDDSURFACEDESC;

Members

dwSize
Size of the structure, in bytes. This member must be initialized before the structure is used.
dwFlags
Optional control flags. One or more of the following flags:
DDSD_ALL
Indicates that all input members are valid.
DDSD_ALPHABITDEPTH
Indicates that the dwAlphaBitDepth member is valid.
DDSD_BACKBUFFERCOUNT
Indicates that the dwBackBufferCount member is valid.
DDSD_CAPS
Indicates that the ddsCaps member is valid.
DDSD_CKDESTBLT
Indicates that the ddckCKDestBlt member is valid.
DDSD_CKDESTOVERLAY
Indicates that the ddckCKDestOverlay member is valid.
DDSD_CKSRCBLT
Indicates that the ddckCKSrcBlt member is valid.
DDSD_CKSRCOVERLAY
Indicates that the ddckCKSrcOverlay member is valid.
DDSD_HEIGHT
Indicates that the dwHeight member is valid.
DDSD_LINEARSIZE
Indicates that dwLinearSize member is valid.
DDSD_LPSURFACE
Indicates that the lpSurface member is valid.
DDSD_MIPMAPCOUNT
Indicates that the dwMipMapCount member is valid.
DDSD_PITCH
Indicates that the lPitch member is valid.
DDSD_PIXELFORMAT
Indicates that the ddpfPixelFormat member is valid.
DDSD_REFRESHRATE
Indicates that the dwRefreshRate member is valid.
DDSD_WIDTH
Indicates that the dwWidth member is valid.
DDSD_ZBUFFERBITDEPTH
Indicates that the dwZBufferBitDepth member is valid.
dwHeight and dwWidth
Dimensions of the surface to be created, in pixels.
lPitch
Distance, in bytes, to the start of next line. When used with the IDirectDrawSurface4::GetSurfaceDesc method, this is a return value. When creating a surface from existing memory or when calling the IDirectDrawSurface4::SetSurfaceDesc method, this is an input value that must be a DWORD multiple.
dwLinearSize
The size of the buffer. Currently returned only for compressed texture surfaces.
dwBackBufferCount
Number of back buffers.
dwMipMapCount
Number of mipmap levels.
dwZBufferBitDepth
Depth of z-buffer. This member is obsolete for DirectX 6.0 and later. Use the IDirect3D3::EnumZBufferFormats to retrieve information about supported depth buffer formats.
dwRefreshRate
Refresh rate (used when the display mode is described). The value of 0 indicates an adapter fault.
dwAlphaBitDepth
Depth of alpha buffer.
dwReserved
Reserved.
lpSurface
Address of the associated surface memory. When calling IDirectDrawSurface4::Lock, this member contains a valid pointer to surface memory after the call returns. When creating a surface from existing memory or when using the IDirectDrawSurface4::SetSurfaceDesc method, this member is an input value that is the address of system memory allocated by the calling application. Do not set this member if your application needs DirectDraw to allocate and manage surface memory.
ddckCKDestOverlay
DDCOLORKEY structure that describes the destination color key to be used for an overlay surface.
ddckCKDestBlt
DDCOLORKEY structure that describes the destination color key for blit operations.
ddckCKSrcOverlay
DDCOLORKEY structure that describes the source color key to be used for an overlay surface.
ddckCKSrcBlt
DDCOLORKEY structure that describes the source color key for blit operations.
ddpfPixelFormat
DDPIXELFORMAT structure that describes the surface's pixel format.
ddsCaps
DDSCAPS structure containing the surface's capabilities.

Remarks

This structure is similar to the DDSURFACEDESC2 structure, but contains a DDSCAPS structure as the ddsCaps member, rather than a DDSCAPS2 structure. Unlike DDSURFACEDESC2, this structure contains the dwZBufferBitDepth member.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.


DDSURFACEDESC2

The DDSURFACEDESC2 structure contains a description of a surface. This structure is used to pass surface parameters to the IDirectDraw4::CreateSurface and IDirectDrawSurface4::SetSurfaceDesc methods. It is also used to retrieve information about a surface in calls to IDirectDrawSurface4::Lock and IDirectDrawSurface4::GetSurfaceDesc. The relevant members differ for each potential type of surface.

typedef struct _DDSURFACEDESC2 {
    DWORD         dwSize;
    DWORD         dwFlags;
    DWORD         dwHeight;
    DWORD         dwWidth;
    union
    {
        LONG      lPitch;
        DWORD     dwLinearSize;
    } DUMMYUNIONNAMEN(1);
    DWORD         dwBackBufferCount;
    union
    {
        DWORD     dwMipMapCount;
        DWORD     dwRefreshRate;
    } DUMMYUNIONNAMEN(2);
    DWORD         dwAlphaBitDepth;
    DWORD         dwReserved;
    LPVOID        lpSurface;
    DDCOLORKEY    ddckCKDestOverlay;
    DDCOLORKEY    ddckCKDestBlt;
    DDCOLORKEY    ddckCKSrcOverlay;
    DDCOLORKEY    ddckCKSrcBlt;
    DDPIXELFORMAT ddpfPixelFormat;
    DDSCAPS2      ddsCaps;
    DWORD         dwTextureStage;
} DDSURFACEDESC2, FAR* LPDDSURFACEDESC2;

Members

dwSize
Size of the structure, in bytes. This member must be initialized before the structure is used.
dwFlags
Optional control flags. One or more of the following flags:
DDSD_ALL
Indicates that all input members are valid.
DDSD_ALPHABITDEPTH
Indicates that the dwAlphaBitDepth member is valid.
DDSD_BACKBUFFERCOUNT
Indicates that the dwBackBufferCount member is valid.
DDSD_CAPS
Indicates that the ddsCaps member is valid.
DDSD_CKDESTBLT
Indicates that the ddckCKDestBlt member is valid.
DDSD_CKDESTOVERLAY
Indicates that the ddckCKDestOverlay member is valid.
DDSD_CKSRCBLT
Indicates that the ddckCKSrcBlt member is valid.
DDSD_CKSRCOVERLAY
Indicates that the ddckCKSrcOverlay member is valid.
DDSD_HEIGHT
Indicates that the dwHeight member is valid.
DDSD_LINEARSIZE
Indicates that the dwLinearSize member is valid.
DDSD_LPSURFACE
Indicates that the lpSurface member is valid.
DDSD_MIPMAPCOUNT
Indicates that the dwMipMapCount member is valid.
DDSD_PITCH
Indicates that the lPitch member is valid.
DDSD_PIXELFORMAT
Indicates that the ddpfPixelFormat member is valid.
DDSD_REFRESHRATE
Indicates that the dwRefreshRate member is valid.
DDSD_TEXTURESTAGE
Indicates that the dwTextureStage member is valid.
DDSD_WIDTH
Indicates that the dwWidth member is valid.
DDSD_ZBUFFERBITDEPTH
Obsolete; see remarks.
dwHeight and dwWidth
Dimensions of the surface to be created, in pixels.
lPitch
Distance, in bytes, to the start of next line. When used with the IDirectDrawSurface4::GetSurfaceDesc method, this is a return value. When used with the IDirectDrawSurface4::SetSurfaceDesc method, this is an input value that must be a DWORD multiple. See remarks for more information.
dwLinearSize
The size of the buffer. Currently returned only for compressed texture surfaces.
dwBackBufferCount
Number of back buffers.
dwMipMapCount
Number of mipmap levels.
dwRefreshRate
Refresh rate (used when the display mode is described). The value of 0 indicates an adapter fault.
dwAlphaBitDepth
Depth of alpha buffer.
dwReserved
Reserved.
lpSurface
Address of the associated surface memory. When calling IDirectDrawSurface4::Lock, this member is a valid pointer to surface memory. When calling IDirectDrawSurface4::SetSurfaceDesc, this member is a pointer to system memory that the caller explicitly allocates for the DirectDrawSurface object. See remarks for more information.
ddckCKDestOverlay
DDCOLORKEY structure that describes the destination color key to be used for an overlay surface.
ddckCKDestBlt
DDCOLORKEY structure that describes the destination color key for blit operations.
ddckCKSrcOverlay
DDCOLORKEY structure that describes the source color key to be used for an overlay surface.
ddckCKSrcBlt
DDCOLORKEY structure that describes the source color key for blit operations.
ddpfPixelFormat
DDPIXELFORMAT structure that describes the surface's pixel format.
ddsCaps
DDSCAPS2 structure containing the surface's capabilities.
dwTextureStage
Stage identifier used to bind a texture to a specific stage in 3-D device's multitexture cascade. Although not required for all hardware, setting this member is recommended for best performance on the largest variety of 3-D accelerators. Hardware that requires explicitly assigned textures will expose the D3DDEVCAPS_SEPARATETEXTUREMEMORIES 3-D device capability in the D3DDEVICEDESC structure that is filled by the IDirect3DDevice3::GetCaps method.

Remarks

The lPitch and lpSurface members are output values when calling the IDirectDrawSurface4::GetSurfaceDesc method. When creating surfaces from existing memory, or updating surface characteristics, these members are input values that describe the pitch and location of memory allocated by the calling application for use by DirectDraw. DirectDraw does not attempt to manage or free memory allocated by the application. For more information, see Creating Client Memory Surfaces and Updating Surface Characteristics.

This structure is nearly identical to the DDSURFACEDESC structure, but contains a DDSCAPS2 structure as the ddsCaps member. Unlike DDSURFACEDESC, this structure doesn't contain the dwZBufferBitDepth member. Z-buffer depth is provided in the ddpfPixelFormat member.

The unions in this structure were written to work with compilers that don't support nameless unions. If your compiler doesn't support nameless unions, define the NONAMELESSUNION token before including the Ddraw.h header file.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.


DDVIDEOPORTBANDWIDTH

The DDVIDEOPORTBANDWIDTH structure describes the bandwidth characteristics of an overlay surface when used with a particular video port and pixel format configuration. This structure is used with the IDirectDrawVideoPort::GetBandwidthInfo method.

typedef struct _DDVIDEOPORTBANDWIDTH {
    DWORD dwSize;
    DWORD dwCaps;
    DWORD dwOverlay;
    DWORD dwColorkey;
    DWORD dwYInterpolate;
    DWORD dwYInterpAndColorkey;
    DWORD dwReserved1;
    DWORD dwReserved2;
} DDVIDEOPORTBANDWIDTH,*LPDDVIDEOPORTBANDWIDTH;

Members

dwSize
Size of this structure, in bytes. This member must be initialized before use.
dwCaps
Flag values specifying device dependency. This member can be one of the following values:
DDVPBCAPS_DESTINATION
This device's capabilities are described in terms of the overlay's minimum stretch factor. Bandwidth information provided for this device refers to the destination overlay size.
DDVPBCAPS_SOURCE
This device's capabilities are described in terms of the required source overlay size. Bandwidth information provided for this device refers to the source overlay size.
dwOverlay
Stretch factor or overlay source size at which an overlay is supported multiplied by 1000. For example 1.3 = 1300, or .75 = 750.
dwColorkey
Stretch factor or overlay source size at which an overlay with color keying is supported multiplied by 1000. For example 1.3 = 1300, or .75 = 750.
dwYInterpolate
Stretch factor or overlay source size at which an overlay with y-axis interpolation is supported multiplied by 1000. For example 1.3 = 1300, or .75 = 750.
dwYInterpAndColorkey
Stretch factor or overlay source size at which an overlay with y-axis interpolation and color keying is supported multiplied by 1000. For example 1.3 = 1300, or .75 = 750.
dwReserved1 and dwReserved2
Reserved; set to zero.

Remarks

When DDVPBCAPS_DESTINATION is specified, the stretch factors described in the other members describe the minimum stretch factor required to display an overlay with the dimensions given when calling the GetBandwidthInfo method. Stretch factor values under 1000 mean that the video port is capable of shrinking an overlay when displayed, and values over 1000 mean that the overlay must be stretched larger than their source to be displayed.

When DDVPBCAPS_SOURCE is specified, the stretch factors described in the other members describe how much you must shrink the overlay source in order for it to be displayed. In this case, the best possible value is 1000, meaning that no shrinking is required. Smaller values tell you that the source rectangle you specified when calling GetBandwidthInfo were too large and must be smaller. For example, if the stretch factor is 750 and you specified 320 pixels for the dwWidth parameter, then you will not be able to display the overlay at that size. To successfully display the overlay, you must use a source rectangle 240 pixels wide to successfully display the overlay.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dvp.h.


DDVIDEOPORTCAPS

The DDVIDEOPORTCAPS structure describes the capabilities and alignment restrictions of a video port. This structure is used with the IDDVideoPortContainer::EnumVideoPorts method.

typedef struct _DDVIDEOPORTCAPS {
    DWORD dwSize;
    DWORD dwFlags;
    DWORD dwMaxWidth;
    DWORD dwMaxVBIWidth;
    DWORD dwMaxHeight;
    DWORD dwVideoPortID;
    DWORD dwCaps;
    DWORD dwFX;
    DWORD dwNumAutoFlipSurfaces;
    DWORD dwAlignVideoPortBoundary;
    DWORD dwAlignVideoPortPrescaleWidth;
    DWORD dwAlignVideoPortCropBoundary;
    DWORD dwAlignVideoPortCropWidth;
    DWORD dwPreshrinkXStep;
    DWORD dwPreshrinkYStep;
    DWORD dwNumVBIAutoFlipSurfaces;
    DWORD dwNumPreferredAutoflip;
    WORD  wNumFilterTapsX;
    WORD  wNumFilterTapsY;
} DDVIDEOPORTCAPS, *LPDDVIDEOPORTCAPS;

Members

dwSize
Size of the structure, in bytes. This must be initialized before use.
dwFlags
Flag values indicating the fields that contain valid data. The following flags are defined:
DDVPD_AUTOFLIP
The dwNumAutoFlipSurfaces member is valid.
DDVPD_ALIGN
The dwAlignVideoPortBoundary, dwAlignVideoPortPrescaleWidth, dwAlignVideoPortCropBoundary, and dwAlignVideoPortCropWidth are valid.
DDVPD_CAPS
The dwCaps member is valid.
DDVPD_FILTERQUALITY
The wNumFilterTapsX and wNumFilterTapsY members are valid.
DDVPD_FX
The dwFX member is valid.
DDVPD_HEIGHT
The dwMaxHeight member is valid.
DDVPD_ID
The dwVideoPortID member is valid.
DDVPD_PREFERREDAUTOFLIP
The dwNumPreferredAutoflip member is valid.
DDVPD_WIDTH
The dwMaxWidth member is valid.
dwMaxWidth
Maximum width of the video port field.
dwMaxVBIWidth
Maximum width of the VBI data.
dwMaxHeight
Maximum height of the video port field.
dwVideoPortID
Zero-based index identifying the video port.
dwCaps
Video port capabilities.
DDVPCAPS_AUTOFLIP
Flip can be performed automatically to avoid tearing when a VREF occurs. If the data is being interleaved in memory, it will flip on every other VREF.
DDVPCAPS_COLORCONTROL
Can perform color control operations on incoming data before writing to the frame buffer.
DDVPCAPS_INTERLACED
Supports interlaced video.
DDVPCAPS_NONINTERLACED
Supports non-interlaced video.
DDVPCAPS_OVERSAMPLEDVBI
Can accept VBI data in a different format or width than the regular video data.
DDVPCAPS_READBACKFIELD
Supports the IDirectDrawVideoPort::GetFieldPolarity method.
DDVPCAPS_READBACKLINE
Supports the IDirectDrawVideoPort::GetVideoLine method.
DDVPCAPS_SHAREABLE
Supports two genlocked video streams that share the video port, where one stream uses the even fields and the other uses the odd fields. Separate parameters (including address, scaling, cropping, and so on) are maintained for both fields.
DDVPCAPS_SKIPEVENFIELDS
Even fields of video can be automatically discarded.
DDVPCAPS_SKIPODDFIELDS
Odd fields of video can be automatically discarded.
DDVPCAPS_SYNCMASTER
Can drive the graphics sync (refresh rate) based on the video port sync.
DDVPCAPS_SYSTEMMEMORY
Capable of writing to surfaces created in system memory.
DDVPCAPS_VBIANDVIDEOINDEPENDENT
Indicates that the VBI and video portions of the video stream can be controlled by independent processes.
DDVPCAPS_VBISURFACE
Data within the VBI can be written to a different surface.
dwFX
Additional video port capabilities.
DDVPFX_CROPTOPDATA
Limited cropping is available to crop VBI data.
DDVPFX_CROPX
Incoming data can be cropped in the x-direction before it is written to the surface.
DDVPFX_CROPY
Incoming data can be cropped in the y-direction before it is written to the surface.
DDVPFX_IGNOREVBIXCROP
The video port can ignore the left and right cropping coordinates when cropping oversampled VBI data.
DDVPFX_INTERLEAVE
Supports interleaving interlaced fields in memory.
DDVPFX_MIRRORLEFTRIGHT
Supports mirroring left to right as the video data is written into the frame buffer.
DDVPFX_MIRRORUPDOWN
Supports mirroring top to bottom as the video data is written into the frame buffer.
DDVPFX_PRESHRINKX
Data can be arbitrarily shrunk in the x-direction before it is written to the surface.
DDVPFX_PRESHRINKY
Data can be arbitrarily shrunk in the y-direction before it is written to the surface.
DDVPFX_PRESHRINKXB
Data can be binary shrunk (1/2, 1/4, 1/8, and so on) in the x-direction before it is written to the surface.
DDVPFX_PRESHRINKYB
Data can be binary shrunk (1/2, 1/4, 1/8, and so on) in the y-direction before it is written to the surface.
DDVPCAPS_PRESHRINKXS
Data can be shrunk in the x-direction by increments of 1/x, where x is specified in the dwShrinkXStep member.
DDVPCAPS_PRESHRINKYS
Data can be shrunk in the y-direction by increments of 1/y, where y is specified in the dwShrinkYStep
DDVPFX_PRESTRETCHX
Data can be arbitrarily stretched in the x-direction before it is written to the surface.
DDVPFX_PRESTRETCHY
Data can be arbitrarily stretched in the y-direction before it is written to the surface.
DDVPFX_PRESTRETCHXN
Data can be integer stretched in the x-direction before it is written to the surface. (1x, 2x, 3x, and so forth)
DDVPFX_PRESTRETCHYN
Data can be integer stretched in the y-direction before it is written to the surface. (1x, 2x, 3x, and so forth)
DDVPFX_VBICONVERT
Data within the VBI can be converted independently of the remaining video data.
DDVPFX_VBINOINTERLEAVE
Interleaving can be disabled for data within the VBI.
DDVPFX_VBINOSCALE
Scaling can be disabled for data within the VBI.
dwNumAutoFlipSurfaces
Maximum number of auto-flippable surfaces supported by the video port.
dwAlignVideoPortBoundary
Byte restriction of placement within the surface.
dwAlignVideoPortPrescaleWidth
Byte restriction of width after prescaling.
dwAlignVideoPortCropBoundary
Byte restriction of left cropping.
dwAlignVideoPortCropWidth
Byte restriction of cropping width.
dwPreshrinkXStep
Width can be shrunk in the x-direction in steps of 1/dwPreshrinkXStep.
dwPreshrinkYStep
Height can be shrunk in the y-direction in steps of 1/dwPreshrinkYStep.
dwNumVBIAutoFlipSurfaces
Maximum number of auto-flipping surfaces capable of receiving data transmitted during the vertical blanking interval (VBI) independent from the remainder of the video stream. When constructing the auto-flip chain, the number of VBI surfaces must equal the number of surfaces receiving the remainder of the video data.
dwNumPreferredAutoflip
Optimal number of auto-flippable surfaces supported by the hardware.
wNumFilterTapsX and wNumFilterTapsY
Number of taps the prescaler filter uses in the x- and y-directions. The value of 0 indicates that no prescaling is performed in that direction, 1 indicates that the prescaler performs replication, 2 indicates that the prescaler uses two taps, and so on.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dvp.h.


DDVIDEOPORTCONNECT

The DDVIDEOPORTCONNECT structure describes a video port connection. This structure is used with the IDDVideoPortContainer::GetVideoPortConnectInfo method.

typedef struct _DDVIDEOPORTCONNECT{
    DWORD dwSize;
    DWORD dwPortWidth;
    GUID  guidTypeID;
    DWORD dwFlags;
    ULONG_PTR dwReserved1;
} DDVIDEOPORTCONNECT,*LPDDVIDEOPORTCONNECT;

Members

dwSize
Size of the structure, in bytes. This member must be initialized before use.
dwPortWidth
Width of the video port. This value represents the number of physical pins on the video port, not the width of a surface in memory. This member must always be set, even when the value in the guidTypeID member assumes a certain size.
guidTypeID
A GUID that describes the sync characteristics of the video port. The following port types are predefined:
DDVPTYPE_E_HREFH_VREFH
External syncs where HREF is active high and VREF is active high.
DDVPTYPE_E_HREFH_VREFL
External syncs where HREF is active high and VREF is active low.
DDVPTYPE_E_HREFL_VREFH
External syncs where HREF is active low and VREF is active high.
DDVPTYPE_E_HREFL_VREFL
External syncs where HREF is active low and VREF is active low.
DDVPTYPE_CCIR656
Sync information is embedded in the data stream according to the CCIR656 specification.
DDVPTYPE_BROOKTREE
Sync information is embedded in the data stream using the Brooktree definition.
DDVPTYPE_PHILIPS
Sync information is embedded in the data stream using the Philips definition.
dwFlags
Flags describing the capabilities of the video-port connection. This member can be set by DirectDraw when connection information is being retrieved or by the client when connection information is being set. This member can be a combination of the following flags:
DDVPCONNECT_DOUBLECLOCK
Indicates that the video port either supports double-clocking data or should double-clock data. This flag is only valid with an external sync.
DDVPCONNECT_VACT
Indicates that the video port either supports using an external VACT signal or should use the external VACT signal. This flag is only valid with an external sync.
DDVPCONNECT_INVERTPOLARITY
Indicates that the video port is capable of inverting the field polarities or is to invert field polarities.

When a video port inverts field polarities, it treats even fields as odd fields and vice versa.

DDVPCONNECT_DISCARDSVREFDATA
The video port discards any data written during the VREF period, causing it to not be written to the frame buffer. This flag is read-only.
DDVPCONNECT_HALFLINE
The video port will write half lines into the frame buffer, sometimes causing the data to be displayed incorrectly. This flag is read-only.
DDVPCONNECT_INTERLACED
Indicates that the signal is interlaced. This flag is only used by the client when creating a video port object.
DDVPCONNECT_SHAREEVEN
The physical video port is shareable, and that this video port object will use the even fields. This flag is only used by the client when creating the video port object.
DDVPCONNECT_SHAREODD
The physical video port is shareable, and that this video port object will use the odd fields. This flag is only used by the client when creating the video port object.
dwReserved1
Reserved; set to zero.

Remarks

This structure is used independently and as a member of the DDVIDEOPORTDESC structure.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dvp.h.


DDVIDEOPORTDESC

The DDVIDEOPORTDESC structure describes a video-port object to be created. This structure is used with the IDDVideoPortContainer::CreateVideoPort method.

typedef struct _DDVIDEOPORTDESC {
    DWORD dwSize;
    DWORD dwFieldWidth;
    DWORD dwVBIWidth;
    DWORD dwFieldHeight;
    DWORD dwMicrosecondsPerField;
    DWORD dwMaxPixelsPerSecond;
    DWORD dwVideoPortID;
    DWORD dwReserved1;
    DDVIDEOPORTCONNECT VideoPortType;
    ULONG_PTR dwReserved2;
    ULONG_PTR dwReserved3;
 } DDVIDEOPORTDESC, *LPDDVIDEOPORTDESC;

Members

dwSize
Size of this structure, in bytes. This member must be initialized before use.
dwFieldWidth
Width of incoming video stream, in pixels.
dwVBIWidth
Width of the VBI data in the incoming video stream, in pixels.
dwFieldHeight
Field height for fields in the incoming video stream, in scan lines.
dwMicrosecondsPerField
Time interval, in microseconds, between live video VREF periods. This number should be rounded up to the nearest microsecond.
dwMaxPixelsPerSecond
Maximum pixel rate per second.
dwVideoPortID
The zero-based ID of the physical video port to be used.
dwReserved1
Reserved; set to zero.
VideoPortType
A DDVIDEOPORTCONNECT structure describing the connection characteristics of the video port.
dwReserved2 and dwReserved3
Reserved; set to zero.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dvp.h.


DDVIDEOPORTINFO

The DDVIDEOPORTINFO structure describes the transfer of video data to a surface. This structure is used with the IDirectDrawVideoPort::StartVideo method.

typedef struct _DDVIDEOPORTINFO{
    DWORD dwSize;
    DWORD dwOriginX;
    DWORD dwOriginY;
    DWORD dwVPFlags;
    RECT rCrop;
    DWORD dwPrescaleWidth;
    DWORD dwPrescaleHeight;
    LPDDPIXELFORMAT lpddpfInputFormat;
    LPDDPIXELFORMAT lpddpfVBIInputFormat;
    LPDDPIXELFORMAT lpddpfVBIOutputFormat;
    DWORD dwVBIHeight;
    ULONG_PTR dwReserved1;
    ULONG_PTR dwReserved2;
} DDVIDEOPORTINFO,*LPDDVIDEOPORTINFO;

Members

dwSize
Size of this structure, in bytes. This member must be initialized before use.
dwOriginX and dwOriginY
X- and y-coordinates for the origin of the video data in the surface.
dwVPFlags
Video port options.
DDVP_AUTOFLIP
Perform automatic flipping. For more information, see Auto-flipping.
DDVP_CONVERT
Perform conversion using the information in the lpddpfVBIOutputFormat member.
DDVP_CROP
Perform cropping using the rectangle specified by the rCrop member.
DDVP_IGNOREVBIXCROP
The video port should ignore left and right cropping coordinates when cropping oversampled VBI data.
DDVP_INTERLEAVE
Interlaced fields should be interleaved in memory.
DDVP_MIRRORLEFTRIGHT
Mirror image data from left to right as it is written into the frame buffer.
DDVP_MIRRORUPDOWN
Mirror image data from top to bottom as it is written into the frame buffer.
DDVP_OVERRIDEBOBWEAVE
Override automatic display method chosen by the driver, using only the display method set by the caller when creating the overlay surface.
DDVP_PRESCALE
Perform pre-scaling or pre-zooming based on the values in the dwPrescaleHeight and dwPrescaleWidth members.
DDVP_SKIPEVENFIELDS
Ignore input of even fields.
DDVP_SKIPODDFIELDS
Ignore input of odd fields.
DDVP_SYNCMASTER
Indicates that the video port VREF should drive the graphics VREF, locking the refresh rate to the video port.
DDVP_VBICONVERT
The lpddpfVBIOutputFormat member contains data that should be used to convert VBI data.
DDVP_VBINOSCALE
VBI data should not be scaled.
DDVP_VBINOINTERLEAVE
Interleaving can be disabled for data within the VBI.
rCrop
Cropping rectangle. This member is optional.
dwPrescaleWidth
Pre-scaling or zooming in the x-direction. This member is optional.
dwPrescaleHeight
Pre-scaling or zooming in the y-direction. This member is optional.
lpddpfInputFormat
A DDPIXELFORMAT structure describing the pixel format to be written to the video port. This will often be identical to the surface's pixel format, but can differ if the video port is to perform conversion.
lpddpfVBIInputFormatand lpddpfVBIOutputFormat
DDPIXELFORMAT structures describing the input and output pixel formats of the data within the vertical blanking interval.
dwVBIHeight
The amount of data within the vertical blanking interval, in scan lines.
dwReserved1 and dwReserved2
Reserved; set to zero.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dvp.h.


DDVIDEOPORTSTATUS

The DDVIDEOPORTSTATUS structure describes the status of a video-port object. This structure is used with the IDDVideoPortContainer::QueryVideoPortStatus method.

typedef struct _DDVIDEOPORTSTATUS {
    DWORD dwSize;
    BOOL  bInUse;
    DWORD dwFlags;
    DWORD dwReserved1;
    DDVIDEOPORTCONNECT VideoPortType;
    ULONG_PTR dwReserved2;
    ULONG_PTR dwReserved3;
} DDVIDEOPORTSTATUS, *LPDDVIDEOPORTSTATUS;

Members

dwSize
Size of this structure, in bytes. This member must be initialized before use.
bInUse
Value indicating the current status of the video port. This member is TRUE if the video port is currently being used, and FALSE otherwise.
dwFlags
Flags
DDVPSTATUS_VBIONLY
The video port interface is only controlling the VBI portion of the video stream.
DDVPSTATUS_VIDEOONLY
The video port interface is only controlling the video portion of the video stream.
dwReserved1
Reserved; set to zero.
VideoPortType
A DDVIDEOPORTCONNECT structure that receives information about the video-port connection.
dwReserved2 and dwReserved3
Reserved; set to zero.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dvp.h.


Return Values

Errors are represented by negative values and cannot be combined. This table lists the values that can be returned by all methods of the IDirectDraw4, IDirectDrawSurface4, IDirectDrawPalette, IDirectDrawClipper, IDDVideoPortContainer, and IDirectDrawVideoPort interfaces. For a list of the error codes that each method can return, see the method description.

DD_OK
The request completed successfully.
DDERR_ALREADYINITIALIZED
The object has already been initialized.
DDERR_BLTFASTCANTCLIP
A DirectDrawClipper object is attached to a source surface that has passed into a call to the IDirectDrawSurface4::BltFast method.
DDERR_CANNOTATTACHSURFACE
A surface cannot be attached to another requested surface.
DDERR_CANNOTDETACHSURFACE
A surface cannot be detached from another requested surface.
DDERR_CANTCREATEDC
Windows can not create any more device contexts (DCs), or a DC was requested for a palette-indexed surface when the surface had no palette and the display mode was not palette-indexed (in this case DirectDraw cannot select a proper palette into the DC).
DDERR_CANTDUPLICATE
Primary and 3-D surfaces, or surfaces that are implicitly created, cannot be duplicated.
DDERR_CANTLOCKSURFACE
Access to this surface is refused because an attempt was made to lock the primary surface without DCI support.
DDERR_CANTPAGELOCK
An attempt to page lock a surface failed. Page lock will not work on a display-memory surface or an emulated primary surface.
DDERR_CANTPAGEUNLOCK
An attempt to page unlock a surface failed. Page unlock will not work on a display-memory surface or an emulated primary surface.
DDERR_CLIPPERISUSINGHWND
An attempt was made to set a clip list for a DirectDrawClipper object that is already monitoring a window handle.
DDERR_COLORKEYNOTSET
No source color key is specified for this operation.
DDERR_CURRENTLYNOTAVAIL
No support is currently available.
DDERR_DCALREADYCREATED
A device context (DC) has already been returned for this surface. Only one DC can be retrieved for each surface.
DDERR_DEVICEDOESNTOWNSURFACE
Surfaces created by one DirectDraw device cannot be used directly by another DirectDraw device.
DDERR_DIRECTDRAWALREADYCREATED
A DirectDraw object representing this driver has already been created for this process.
DDERR_EXCEPTION
An exception was encountered while performing the requested operation.
DDERR_EXCLUSIVEMODEALREADYSET
An attempt was made to set the cooperative level when it was already set to exclusive.
DDERR_EXPIRED
The data has expired and is therefore no longer valid.
DDERR_GENERIC
There is an undefined error condition.
DDERR_HEIGHTALIGN
The height of the provided rectangle is not a multiple of the required alignment.
DDERR_HWNDALREADYSET
The DirectDraw cooperative level window handle has already been set. It cannot be reset while the process has surfaces or palettes created.
DDERR_HWNDSUBCLASSED
DirectDraw is prevented from restoring state because the DirectDraw cooperative level window handle has been subclassed.
DDERR_IMPLICITLYCREATED
The surface cannot be restored because it is an implicitly created surface.
DDERR_INCOMPATIBLEPRIMARY
The primary surface creation request does not match with the existing primary surface.
DDERR_INVALIDCAPS
One or more of the capability bits passed to the callback function are incorrect.
DDERR_INVALIDCLIPLIST
DirectDraw does not support the provided clip list.
DDERR_INVALIDDIRECTDRAWGUID
The globally unique identifier (GUID) passed to the DirectDrawCreate function is not a valid DirectDraw driver identifier.
DDERR_INVALIDMODE
DirectDraw does not support the requested mode.
DDERR_INVALIDOBJECT
DirectDraw received a pointer that was an invalid DirectDraw object.
DDERR_INVALIDPARAMS
One or more of the parameters passed to the method are incorrect.
DDERR_INVALIDPIXELFORMAT
The pixel format was invalid as specified.
DDERR_INVALIDPOSITION
The position of the overlay on the destination is no longer legal.
DDERR_INVALIDRECT
The provided rectangle was invalid.
DDERR_INVALIDSTREAM
The specified stream contains invalid data.
DDERR_INVALIDSURFACETYPE
The requested operation could not be performed because the surface was of the wrong type.
DDERR_LOCKEDSURFACES
One or more surfaces are locked, causing the failure of the requested operation.
DDERR_MOREDATA
There is more data available than the specified buffer size can hold.
DDERR_NO3D
No 3-D hardware or emulation is present.
DDERR_NOALPHAHW
No alpha acceleration hardware is present or available, causing the failure of the requested operation.
DDERR_NOBLTHW
No blitter hardware is present.
DDERR_NOCLIPLIST
No clip list is available.
DDERR_NOCLIPPERATTACHED
No DirectDrawClipper object is attached to the surface object.
DDERR_NOCOLORCONVHW
The operation cannot be carried out because no color-conversion hardware is present or available.
DDERR_NOCOLORKEY
The surface does not currently have a color key.
DDERR_NOCOLORKEYHW
The operation cannot be carried out because there is no hardware support for the destination color key.
DDERR_NOCOOPERATIVELEVELSET
A create function is called without the IDirectDraw4::SetCooperativeLevel method being called.
DDERR_NODC
No DC has ever been created for this surface.
DDERR_NODDROPSHW
No DirectDraw raster operation (ROP) hardware is available.
DDERR_NODIRECTDRAWHW
Hardware-only DirectDraw object creation is not possible; the driver does not support any hardware.
DDERR_NODIRECTDRAWSUPPORT
DirectDraw support is not possible with the current display driver.
DDERR_NOEMULATION
Software emulation is not available.
DDERR_NOEXCLUSIVEMODE
The operation requires the application to have exclusive mode, but the application does not have exclusive mode.
DDERR_NOFLIPHW
Flipping visible surfaces is not supported.
DDERR_NOFOCUSWINDOW
An attempt was made to create or set a device window without first setting the focus window.
DDERR_NOGDI
No GDI is present.
DDERR_NOHWND
Clipper notification requires a window handle, or no window handle has been previously set as the cooperative level window handle.
DDERR_NOMIPMAPHW
The operation cannot be carried out because no mipmap capable texture mapping hardware is present or available.
DDERR_NOMIRRORHW
The operation cannot be carried out because no mirroring hardware is present or available.
DDERR_NONONLOCALVIDMEM
An attempt was made to allocate non-local video memory from a device that does not support non-local video memory.
DDERR_NOOPTIMIZEHW
The device does not support optimized surfaces.
DDERR_NOOVERLAYDEST
The IDirectDrawSurface4::GetOverlayPosition method is called on an overlay that the IDirectDrawSurface4::UpdateOverlay method has not been called on to establish a destination.
DDERR_NOOVERLAYHW
The operation cannot be carried out because no overlay hardware is present or available.
DDERR_NOPALETTEATTACHED
No palette object is attached to this surface.
DDERR_NOPALETTEHW
There is no hardware support for 16- or 256-color palettes.
DDERR_NORASTEROPHW
The operation cannot be carried out because no appropriate raster operation hardware is present or available.
DDERR_NOROTATIONHW
The operation cannot be carried out because no rotation hardware is present or available.
DDERR_NOSTRETCHHW
The operation cannot be carried out because there is no hardware support for stretching.
DDERR_NOT4BITCOLOR
The DirectDrawSurface object is not using a 4-bit color palette and the requested operation requires a 4-bit color palette.
DDERR_NOT4BITCOLORINDEX
The DirectDrawSurface object is not using a 4-bit color index palette and the requested operation requires a 4-bit color index palette.
DDERR_NOT8BITCOLOR
The DirectDrawSurface object is not using an 8-bit color palette and the requested operation requires an 8-bit color palette.
DDERR_NOTAOVERLAYSURFACE
An overlay component is called for a non-overlay surface.
DDERR_NOTEXTUREHW
The operation cannot be carried out because no texture-mapping hardware is present or available.
DDERR_NOTFLIPPABLE
An attempt has been made to flip a surface that cannot be flipped.
DDERR_NOTFOUND
The requested item was not found.
DDERR_NOTINITIALIZED
An attempt was made to call an interface method of a DirectDraw object created by CoCreateInstance before the object was initialized.
DDERR_NOTLOADED
The surface is an optimized surface, but it has not yet been allocated any memory.
DDERR_NOTLOCKED
An attempt is made to unlock a surface that was not locked.
DDERR_NOTPAGELOCKED
An attempt is made to page unlock a surface with no outstanding page locks.
DDERR_NOTPALETTIZED
The surface being used is not a palette-based surface.
DDERR_NOVSYNCHW
The operation cannot be carried out because there is no hardware support for vertical blank synchronized operations.
DDERR_NOZBUFFERHW
The operation to create a z-buffer in display memory or to perform a blit using a z-buffer cannot be carried out because there is no hardware support for z-buffers.
DDERR_NOZOVERLAYHW
The overlay surfaces cannot be z-layered based on the z-order because the hardware does not support z-ordering of overlays.
DDERR_OUTOFCAPS
The hardware needed for the requested operation has already been allocated.
DDERR_OUTOFMEMORY
DirectDraw does not have enough memory to perform the operation.
DDERR_OUTOFVIDEOMEMORY
DirectDraw does not have enough display memory to perform the operation.
DDERR_OVERLAPPINGRECTS
Operation could not be carried out because the source and destination rectangles are on the same surface and overlap each other.
DDERR_OVERLAYCANTCLIP
The hardware does not support clipped overlays.
DDERR_OVERLAYCOLORKEYONLYONEACTIVE
An attempt was made to have more than one color key active on an overlay.
DDERR_OVERLAYNOTVISIBLE
The IDirectDrawSurface4::GetOverlayPosition method is called on a hidden overlay.
DDERR_PALETTEBUSY
Access to this palette is refused because the palette is locked by another thread.
DDERR_PRIMARYSURFACEALREADYEXISTS
This process has already created a primary surface.
DDERR_REGIONTOOSMALL
The region passed to the IDirectDrawClipper::GetClipList method is too small.
DDERR_SURFACEALREADYATTACHED
An attempt was made to attach a surface to another surface to which it is already attached.
DDERR_SURFACEALREADYDEPENDENT
An attempt was made to make a surface a dependency of another surface to which it is already dependent.
DDERR_SURFACEBUSY
Access to the surface is refused because the surface is locked by another thread.
DDERR_SURFACEISOBSCURED
Access to the surface is refused because the surface is obscured.
DDERR_SURFACELOST
Access to the surface is refused because the surface memory is gone. Call the IDirectDrawSurface4::Restore method on this surface to restore the memory associated with it.
DDERR_SURFACENOTATTACHED
The requested surface is not attached.
DDERR_TOOBIGHEIGHT
The height requested by DirectDraw is too large.
DDERR_TOOBIGSIZE
The size requested by DirectDraw is too large. However, the individual height and width are valid sizes.
DDERR_TOOBIGWIDTH
The width requested by DirectDraw is too large.
DDERR_UNSUPPORTED
The operation is not supported.
DDERR_UNSUPPORTEDFORMAT
The pixel format requested is not supported by DirectDraw.
DDERR_UNSUPPORTEDMASK
The bitmask in the pixel format requested is not supported by DirectDraw.
DDERR_UNSUPPORTEDMODE
The display is currently in an unsupported mode.
DDERR_VERTICALBLANKINPROGRESS
A vertical blank is in progress.
DDERR_VIDEONOTACTIVE
The video port is not active.
DDERR_WASSTILLDRAWING
The previous blit operation that is transferring information to or from this surface is incomplete.
DDERR_WRONGMODE
This surface cannot be restored because it was created in a different mode.
DDERR_XALIGN
The provided rectangle was not horizontally aligned on a required boundary.


Pixel Format Masks

This section contains information about the pixel formats supported by the hardware-emulation layer (HEL). The following topics are discussed:

  • Texture Map Formats
  • Off-Screen Surface Formats


Texture Map Formats

A wide range of texture pixel formats are supported by the HEL. The following table shows these formats. The Masks column contains the red, green, blue, and alpha masks for each set of pixel format flags and bit depths.

Pixel format flags | Bit depth | Masks
DDPF_RGB | | 1 | R: 0x00000000
DDPF_PALETTEINDEXED1 |  | G: 0x00000000
 |  | B: 0x00000000
 |  | A: 0x00000000
DDPF_RGB | | 1 | R: 0x00000000
DDPF_PALETTEINDEXED1 | |  | G: 0x00000000
DDPF_PALETTEINDEXEDTO8 |  | B: 0x00000000
 |  | A: 0x00000000
DDPF_RGB | | 2 | R: 0x00000000
DDPF_PALETTEINDEXED2 |  | G: 0x00000000
 |  | B: 0x00000000
 |  | A: 0x00000000
DDPF_RGB | | 2 | R: 0x00000000
DDPF_PALETTEINDEXED2 | |  | G: 0x00000000
DDPF_PALETTEINDEXEDTO8 |  | B: 0x00000000
 |  | A: 0x00000000
DDPF_RGB | | 4 | R: 0x00000000
DDPF_PALETTEINDEXED4 |  | G: 0x00000000
 |  | B: 0x00000000
 |  | A: 0x00000000
DDPF_RGB | | 4 | R: 0x00000000
DDPF_PALETTEINDEXED4 | |  | G: 0x00000000
DDPF_PALETTEINDEXEDTO8 |  | B: 0x00000000
 |  | A: 0x00000000
DDPF_RGB | | 8 | R: 0x00000000
DDPF_PALETTEINDEXED8 |  | G: 0x00000000
 |  | B: 0x00000000
 |  | A: 0x00000000
DDPF_RGB | 8 | R: 0x000000E0
 |  | G: 0x0000001C
 |  | B: 0x00000003
 |  | A: 0x00000000
DDPF_RGB | | 16 | R: 0x00000F00
DDPF_ALPHAPIXELS |  | G: 0x000000F0
 |  | B: 0x0000000F
 |  | A: 0x0000F000
DDPF_RGB | 16 | R: 0x0000F800
 |  | G: 0x000007E0
 |  | B: 0x0000001F
 |  | A: 0x00000000
DDPF_RGB | 16 | R: 0x0000001F
 |  | G: 0x000007E0
 |  | B: 0x0000F800
 |  | A: 0x00000000
DDPF_RGB | 16 | R: 0x00007C00
 |  | G: 0x000003E0
 |  | B: 0x0000001F
 |  | A: 0x00000000
DDPF_RGB | | 16 | R: 0x00007C00
DDPF_ALPHAPIXELS |  | G: 0x000003E0
 |  | B: 0x0000001F
 |  | A: 0x00008000
DDPF_RGB | 24 | R: 0x00FF0000
 |  | G: 0x0000FF00
 |  | B: 0x000000FF
 |  | A: 0x00000000
DDPF_RGB | 24 | R: 0x000000FF
 |  | G: 0x0000FF00
 |  | B: 0x00FF0000
 |  | A: 0x00000000
DDPF_RGB | 32 | R: 0x00FF0000
 |  | G: 0x0000FF00
 |  | B: 0x000000FF
 |  | A: 0x00000000
DDPF_RGB | 32 | R: 0x000000FF
 |  | G: 0x0000FF00
 |  | B: 0x00FF0000
 |  | A: 0x00000000
DDPF_RGB | | 32 | R: 0x00FF0000
DDPF_ALPHAPIXELS |  | G: 0x0000FF00
 |  | B: 0x000000FF
 |  | A: 0xFF000000
DDPF_RGB | | 32 | R: 0x000000FF
DDPF_ALPHAPIXELS |  | G: 0x0000FF00
 |  | B: 0x00FF0000
 |  | A: 0xFF000000

The HEL can create these formats in system memory. The DirectDraw device driver for a 3-D–accelerated display card may create textures of other formats in display memory. Such a driver exports the DDSCAPS_TEXTURE flag to indicate that it can create textures.


Off-Screen Surface Formats

The following table shows the pixel formats for off-screen plain surfaces supported by the DirectX® 5 HEL. The Masks column contains the red, green, blue, and alpha masks for each set of pixel format flags and bit depths.

Pixel format flags | Bit depth | Masks
DDPF_RGB | | 1 | R: 0x00000000
DDPF_PALETTEINDEXED1 |  | G: 0x00000000
 |  | B: 0x00000000
 |  | A: 0x00000000
DDPF_RGB | | 2 | R: 0x00000000
DDPF_PALETTEINDEXED2 |  | G: 0x00000000
 |  | B: 0x00000000
 |  | A: 0x00000000
DDPF_RGB | | 4 | R: 0x00000000
DDPF_PALETTEINDEXED4 |  | G: 0x00000000
 |  | B: 0x00000000
 |  | A: 0x00000000
DDPF_RGB | | 8 | R: 0x00000000
DDPF_PALETTEINDEXED8 |  | G: 0x00000000
 |  | B: 0x00000000
 |  | A: 0x00000000
DDPF_RGB | 16 | R: 0x0000F800
 |  | G: 0x000007E0
 |  | B: 0x0000001F
 |  | A: 0x00000000
DDPF_RGB | 16 | R: 0x00007C00
 |  | G: 0x000003E0
 |  | B: 0x0000001F
 |  | A: 0x00000000
DDPF_RGB | 24 | R: 0x00FF0000
 |  | G: 0x0000FF00
 |  | B: 0x000000FF
 |  | A: 0x00000000
DDPF_RGB | 24 | R: 0x000000FF
 |  | G: 0x0000FF00
 |  | B: 0x00FF0000
 |  | A: 0x00000000
DDPF_RGB | 32 | R: 0x00FF0000
 |  | G: 0x0000FF00
 |  | B: 0x000000FF
 |  | A: 0x00000000
DDPF_RGB | 32 | R: 0x000000FF
 |  | G: 0x0000FF00
 |  | B: 0x00FF0000
 |  | A: 0x00000000
DDPF_RGB | | 32 | R: 0x0000F800
DDPF_ZPIXELS |  | G: 0x000007E0
 |  | B: 0x0000001F
 |  | Z: 0xFFFF0000
DDPF_RGB | | 32 | R: 0x00007C00
DDPF_ZPIXELS |  | G: 0x000003E0
 |  | B: 0x0000001F
 |  | Z: 0xFFFF0000

In addition to supporting a wide range of off-screen surface formats, the HEL also supports surfaces intended for use by Direct3D, or other 3-D renderers.


Four Character Codes (FOURCC)

DirectDraw utilizes a special set of codes that are four characters in length. These codes, called four character codes or FOURCCs, are stored in file headers of files containing multimedia data such as bitmap images, sound, or video. FOURCCs describe the software technology that was used to produce multimedia data. By implication, they also describe the format of the data itself.

DirectDraw applications use FOURCCs for image color and format conversion. If an application calls the IDirectDrawSurface4::GetPixelFormat method to request the pixel format of a surface whose format is not RGB, the dwFourCC member of the DDPIXELFORMAT structure identifies the FOURCC when the method returns. For more information, see Converting Color and Format.

In addition, the biCompression member of the BITMAPINFOHEADER structure can be set to a FOURCC to indicate the codec used to compress or decompress an image.

FOURCCs are registered with Microsoft by the vendors of the respective multimedia software technologies. Some common FOURCCs appear in the following list.

FOURCC | Company | Technology Name
AUR2 | AuraVision Corporation | AuraVision Aura 2: YUV 422
AURA | AuraVision Corporation | AuraVision Aura 1: YUV 411
CHAM | Winnov, Inc. | MM_WINNOV_CAVIARA_CHAMPAGNE
CVID | Supermac | Cinepak by Supermac
CYUV | Creative Labs, Inc | Creative Labs YUV
DXT1 | Microsoft Corporation | DirectX Texture Compression format 1
DXT2 | Microsoft Corporation | DirectX Texture Compression format 2
DXT3 | Microsoft Corporation | DirectX Texture Compression format 3
DXT4 | Microsoft Corporation | DirectX Texture Compression format 4
DXT5 | Microsoft Corporation | DirectX Texture Compression format 5
FVF1 | Iterated Systems, Inc. | Fractal Video Frame
IF09 | Intel Corporation | Intel Intermediate YUV9
IV31 | Intel Corporation | Indeo 3.1
JPEG | Microsoft Corporation | Still Image JPEG DIB
MJPG | Microsoft Corporation | Motion JPEG Dib Format
MRLE | Microsoft Corporation | Run Length Encoding
MSVC | Microsoft Corporation | Video 1
PHMO | IBM Corporation | Photomotion
RT21 | Intel Corporation | Indeo 2.1
ULTI | IBM Corporation | Ultimotion
V422 | Vitec Multimedia | 24 bit YUV 4:2:2
V655 | Vitec Multimedia | 16 bit YUV 4:2:2
VDCT | Vitec Multimedia | Video Maker Pro DIB
VIDS | Vitec Multimedia | YUV 4:2:2 CCIR 601 for V422
YU92 | Intel Corporation | YUV
YUV8 | Winnov, Inc. | MM_WINNOV_CAVIAR_YUV8
YUV9 | Intel Corporation | YUV9
YUYV | Canopus, Co., Ltd. | BI_YUYV, Canopus
ZPEG | Metheus | Video Zipper


DirectDraw Samples

This section gives brief descriptions of sample applications in the DirectX Programmer's Reference primarily intended to demonstrate the DirectDraw component. The following sample programs are included:

  • DDEnum Sample
  • DDEx1 Sample
  • DDEx2 Sample
  • DDEx3 Sample
  • DDEx4 Sample
  • DDEx5 Sample
  • DDOverlay Sample
  • Donut Sample
  • Flip2D Sample
  • FSWindow Sample
  • Font Sample
  • Memtime Sample
  • Mosquito Sample
  • Multimonitor Space Donuts Sample
  • Space Donuts Sample
  • Stretch Sample
  • Stretch2 Sample
  • Stretch3 Sample
  • Switcher Sample
  • Wormhole Sample

Although DirectX samples include Microsoft® Visual C++® project workspace files, you might need to verify other settings in your development environment to ensure that the samples compile properly. For more information, see Compiling DirectX Samples and Other DirectX Applications.


DDEnum Sample

Description

This sample shows how to enumerate the current DirectDraw devices and how to get information using the IDirectDraw4::GetDeviceIdentifier method.

Path

Source: (SDK root)\Samples\Multimedia\DDraw\Src\DDEnum

Executable: (SDK root)\Samples\Multimedia\DDraw\Bin

User's Guide

The user interface is a simple dialog box. Two buttons, Prev and Next, display information for the previous or next device that was enumerated. Click the Close button to exit the application.


DDEx1 Sample

Description

DDEx1 demonstrates the tasks required to initialize and run a DirectDraw application.

Path

Source: (SDK root)\Samples\Multimedia\DDraw\Src\Ddex1

Executable: (SDK root)\Samples\Multimedia\DDraw\Bin

User's Guide

DDEx1 requires no user input. Press the F12 key or the ESC key to quit the program.

Programming Notes

This program shows how to initialize DirectDraw and create a DirectDraw surface. It creates a back buffer and uses page flipping to alternately display the contents of the front and back buffers. Other techniques demonstrated include color fills and using GDI functions on a DirectDraw surface.


DDEx2 Sample

Description

The DDEx2 program is an extension of DDEx1 that adds a bitmap.

Path

Source: (SDK root)\Samples\Multimedia\DDraw\Src\Ddex2

Executable: (SDK root)\Samples\Multimedia\DDraw\bin

User's Guide

DDEx2 requires no user input. Press F12 or ESC to quit the program.

Programming Notes

DDEx2 shows how to set a palettized video mode. Routines in DDutil.cpp load a bitmap file and copy it to a DirectDraw surface.


DDEx3 Sample

Description

The DDEx3 program is an extension of DDEx2. This example demonstrates the use of off-screen surfaces.

Path

Source: (SDK root)\Samples\Multimedia\DDraw\Src\Ddex3

Executable: (SDK root)\Samples\Multimedia\DDraw\Bin

User's Guide

DDEx3 requires no user input. Press F12 or ESC to quit the program.

The program requires at least 1.2 MB of video RAM.

Programming Notes

In addition to the front and back buffers, the program creates two off-screen surfaces and loads bitmaps into them. It calls the IDirectDrawSurface4::BltFast method to copy the contents of an off-screen surface to the back buffer, alternating the source surface on each frame. After it blits the bitmap to the back buffer, DDEx3 flips the front and back buffers.


DDEx4 Sample

Description

The DDEx4 program is an extension of DDEx3. It demonstrates a simple animation technique.

Path

Source: (SDK root)\Samples\Multimedia\DDraw\Src\Ddex4

Executable: (SDK root)\Samples\Multimedia\DDraw\Bin

User's Guide

DDEx4 requires no user input. Press F12 or ESC to quit the program.

This program requires at least 1.2 MB of video RAM.

Programming Notes

Unlike DDEx3, the DDEx4 program creates only one off-screen surface. It loads a bitmap containing a series of animation images onto this surface. To create the animation, it blits portions of the off-screen surface to the back buffer, then flips the front and back buffers.

The blitting routines illustrate the use of a source color key to create a sprite with a transparent background.


DDEx5 Sample

Description

The DDEx5 program is an extension of DDEx4. It demonstrates a simple palette manipulation.

Path

Source: (SDK root)\Samples\Multimedia\DDraw\Src\Ddex5

Executable: (SDK root)\Samples\Multimedia\DDraw\Bin

User's Guide

DDEx4 requires no user input. Press F12 or ESC to quit the program.

This program requires at least 1.2 MB of video RAM.

Programming Notes

The program uses IDirectDrawPalette::GetEntries to read a palette, modifies the entries, and then uses IDirectDrawPalette::SetEntries to update the palette.


DDOverlay Sample

Description

This sample application demonstrates the use of overlays in a windowed DirectDraw application.

Path

Source: (SDK root)\Samples\Multimedia\DDraw\Src\DDovrly

Executable: (SDK root)\Samples\Multimedia\DDraw\Bin

User's Guide

Your hardware must support overlays in order for the program to run.

Try moving, resizing, and minimizing and restoring the window. Press ALT+F4 or click the Close button to quit.

Programming Notes

The program checks for overlay support, loads a bitmap into an overlay surface, and updates the window from the overlay surface in response to Windows messages.


Donut Sample

Description

The Donut program uses DirectDraw to display an animated sprite directly on the screen. In non-exclusive mode, the sprite appears on top of the desktop and any windows. In exclusive mode, it appears on an otherwise blank screen.

Path

Source: (SDK root)\Samples\Multimedia\DDraw\Src\Donut

Executable: (SDK root)\Samples\Multimedia\DDraw\Bin

User's Guide

The Donut application requires no user input. Press F12 or ESC to quit. Note that because the program does not run in a window, you may have to switch to it by using the taskbar or ALT+TAB before you can close it.

You can specify various command line switches to modify the operational characteristics of this program. Each command line switch consists of one character, and need not be preceded with a hyphen or slash. Alphabetical characters must be capitals. The switches are as follows:

0 | Default. Display the donut in the left position.
1 | Display the donut in the middle position.
2 | Display the donut in the right position.
X | Use exclusive mode. The default is non-exclusive mode.
A | Switch to 640x480x8 resolution and use exclusive mode.
B | Switch to 800x600x8 resolution and use exclusive mode.
C | Switch to 1024x768x8 resolution and use exclusive mode.
D | Switch to 1280x1024x8 resolution and use exclusive mode.

The switches can be combined. If you specify two or more command line switches that contradict each other, the last switch is used.

If you run the program in non-exclusive mode, it attempts to continue to run even when it loses focus. If you run it in exclusive mode, it does not attempt to modify the screen when it doesn't have focus.

Programming Notes

The Donut program creates a primary DirectDraw surface and two off-screen surfaces. Animation images are blitted from the off-screen surfaces directly to the primary surface during each frame.

The program demonstrates how DirectX applications can set the video mode based on user input. It is also useful for testing multiple exclusive mode applications interacting with multiple non-exclusive mode applications.


Flip2D Sample

Description

This sample program demonstrates DirectDraw animation using surface flipping.

Path

Source: (SDK root)\Samples\Multimedia\DDraw\Src\Flip2d

Executable: (SDK root)\Samples\Multimedia\DDraw\Bin

User's Guide

The Flip2D program displays and animates a cube. You can change the screen mode by pressing the F10 key and selecting a resolution and color depth value from the Modes menu. Use the Cube menu or the keyboard shortcuts to increase (F7) or decrease (F8) the displayed size of the cube, or to switch to GDI drawing on the primary surface (F9).

Programming Notes

Normally the cube is rendered on the back buffer and then the surface is flipped to the front. You can compare the results with those from rendering directly on to the front surface by choosing GDI drawing.

The palette that the Flip2D program uses for 8-bpp modes is red, green and blue wash. There isn't enough room in the palette for yellow, orange, and purple. In 8-bpp modes the Flip2D sample application maps yellow, orange and purple to red. If you select DrawWithGDI from the Cube menu, yellow, orange, purple are drawn without very many shades. This is because the program is using system colors, and there are only a few shades of yellow, orange, and purple available in the system palette.


Font Sample

Description

This sample program shows how to directly lock and access video memory, using text generated from a GDI font. There are much better ways to draw text into a DirectDrawSurface, and the only point of this sample is to show exactly how to lock and access the video memory directly.

Path

Source: (SDK root)\Samples\Multimedia\DDraw\Src\Font

Executable: (SDK root)\Samples\Multimedia\DDraw\Bin

User's Guide

The program repeatedly updates a text string in the Arial font and moves it randomly about the screen. No user input is required. Quit by closing the window.

Programming Notes

The program creates a font in a memory device context and a DIB section, and uses them to get access to the pixels once GDI has drawn them. The text bitmap is then put on the primary surface with a straight memory copy. It could easily be moved instead to an off-screen surface which could then be blitted as needed, transparently or not.


FSWindow Sample

Description

This sample shows how you can bring up a dialog box, or any other type of window, while your application is running in DirectDraw's full-screen exclusive mode. Even devices that are non-GDI are detected and supported by creating a bitmap from their window contents and then blitting that to the device.

Path

Source: (SDK root)\Samples\Multimedia\DDraw\Src\FSWindow

Executable: (SDK root)\Samples\Multimedia\DDraw\Bin

User's Guide

If you have more than one device, the sample starts by displaying a dialog box so that you can select which device to run the sample on. It then switches to full-screen exclusive mode and displays a dialog box and the mouse cursor.

Click on the Cancel or OK button to close the dialog and hide the mouse cursor. Press F1 to bring the dialog and cursor back. Press Esc to exit the program when the dialog is no longer displayed.

Programming Notes

Most of the important code is in the Fswindow.cpp file.

The sample uses just the dynamic content mode, which constantly refreshes the dialog box to show which controls have focus, text in the edit field, and so on. The static content mode consumes less CPU time and would be good for pop-up windows that display help messages, for example.

It is important to understand that the content window can be any type of window. It could be an HTML Help window, or a window with a rich edit control to display formatted text. The window does not need to have a square clipping region; it could have a complex clipping region that fits the shape of the window you want to display.


Memtime Sample

Description

The Memtime sample program is intended to be a demonstration of the advantages and disadvantages of various drawing methods. It runs a series of tests of memory bandwidth and displays a report.

Path

Source: (SDK root)\Samples\Multimedia\DDraw\Src\MemTime

Executable: None.

User's Guide

Choose Time All from the main menu to begin the tests. Note that your screen will change resolution during the tests. It will also go blank for short periods of time.

Programming Notes

The sample is not intended as an example of particular techniques in DirectDraw programming. Of more interest are the results of the memory tests.


Mosquito Sample

Description

This program demonstrates DirectDraw animation using overlays.

Path

Source: (SDK root)\Samples\Multimedia\DDraw\Src\Mosquito

Executable: (SDK root)\Samples\Multimedia\DDraw\Bin

User's Guide

To run the Mosquito application, you must have a display adapter that supports overlays. On a computer with overlay support, the program creates a large mosquito that flies around the screen. If your display adapter card doesn't support source color keying for overlays, you'll see an ugly, black, rectangular background around the mosquito.

Some cards have better overlay support in certain resolutions that others. If you know your card has overlay support through DirectDraw, but the Mosquito program is having problems creating or displaying the overlay, try switching to a lower screen resolution or color depth and restarting the application.

Programming Notes

The program creates a complex overlay surface and animates by flipping.


Multimonitor Space Donuts Sample

Description

This version of Space Donuts demonstrates the multimonitor capabilities of DirectX.

Path

Source: (SDK root)\Samples\Multimedia\DDraw\Src\MultiNut

Executable: (SDK root)\Samples\Multimedia\DDraw\Bin

User's Guide

In order to run the program, you must have Windows 2000 or Windows 98 configured for multiple monitors.

The program will run on up to nine monitors. The play area is determined by the monitor configuration of your Windows desktop, which may be adjusted on the Settings tab of the Display Control Panel. The amount of video RAM you have on each video card will determine the maximum resolutions at which you will experience a reasonable frame rate. If the frame rate is slow, try exiting, lowering the resolution or color depth of your windows desktop, and restart.

Multimonitor Space Donuts supports two command-line switches:

-w# | Put monitor number # in windowed mode
-s | Turn sound off

For information on the keyboard interface, see Space Donuts.


Space Donuts Sample

Description

This simple game shows how to combine DirectDraw, DirectInput, and DirectSound. Although it demonstrates other DirectX components, it is primarily intended to show how to animate multiple sprites.

Path

Source: (SDK root)\Samples\Multimedia\DDraw\Src\Donuts

Executable: (SDK root)\Samples\Multimedia\DDraw\Bin

User's Guide

Input is from the keyboard by default, but you can select a joystick from the Game menu.

The commands are listed on the opening screen. All numbers must be entered from the numeric keypad. "Joy" refers to a joystick button.

Key | Command
ESC, F12 | Quit
4 | Turn left
6 | Turn right
5 (Joy 3) | Stop
8 | Accelerate forward
2 | Accelerate backward
7 (Joy 2) | Shield
SPACEBAR (Joy 1) | Fire
ENTER | Start game
F1 | Toggle trailing afterimage effect on/off
F3 | Turn audio on/off
F5 | Toggle frame rate display on/off
F10 | Main menu

Space Donuts defaults to 640x480 at 256 colors. You can specify a different resolution and pixel depth on the command line.

The game uses the following command line switches, which are case-sensitive:

e | Use software emulation, not hardware acceleration
t | Test mode, no input required
x | Stress mode. Never stop if you can help it
S | Turn sound off/on

These switches may be followed by three option numbers representing x-resolution, y-resolution, and bits per pixel. For example:

donuts -S 800 600 16

Programming Notes

This game demonstrates many of the features of DirectDraw. It takes advantage of hardware acceleration if it is supported by the driver.

The program requires less than 1 MB of video RAM.

The sound code is deliberately designed to stress the DirectSound API. It is not intended to be a demonstration of how to use DirectSound API efficiently. For example, each bullet on the screen uses a different sound buffer. Space Donuts creates over 70 sound buffers (including duplicates), and between 20 to 25 may be playing at any time.

The sounds are implemented using the helper functions in Dsutil.h and Dsutil.c (found in the Sdk\Samples\Misc directory). These functions might help you to add sound to your application quickly and easily.


Stretch Sample

Description

The Stretch sample application program illustrates stretching and clipping while blitting a bitmap image.

Path

Source: (SDK root)\Samples\Multimedia\DDraw\Src\Stretch

Executable: (SDK root)\Samples\Multimedia\DDraw\Bin

User's Guide

Stretch must be run in a video mode that uses 8 bits per pixel. It will not work properly in other video modes.

The program displays a red torus moving in its client window. Control the rotational speed with the Stop, Slow, and Fast options in the Rotation menu. Alter the size of the window by selecting items from the Size menu, or by resizing the window with the mouse.

Programming Notes

Any time you resize the Stretch program window to a size other than 1x1, you are using the image stretching capabilities of the DirectDraw blitting methods.

The clipper for the primary surface is set to the client window. To demonstrate clipping, partially overlap another window over the Stretch program's window. When Stretch blits the bitmap, the portion of the bitmap that would fall within the other window is clipped.


Stretch2 Sample

Description

Stretch2 is an extension of the Stretch program. In addition to the capabilities of the Stretch example, Stretch2 illustrates how an application can use DirectDraw on multiple monitors.

Path

Source: (SDK root)\Samples\Multimedia\DDraw\Src\Stretch2

Executable: (SDK root)\Samples\Multimedia\DDraw\Bin

User's Guide

Resize the window to see the bitmap stretch. If you have more than one monitor attached to your computer, the window can be dragged from monitor to monitor.

Programming Notes

Look at how the application handles WM_MOVE to detect when the window moves monitors. Also note how it converts from window client coordinates to device coordinates.

Multimon.h contains stub functions that enable the program to run on Windows 95 or Windows NT 4.0.


Stretch3 Sample

Description

The Stretch3 application is an improved version of the Stretch2 program. It demonstrates more complex handling of DirectDraw images on multiple monitors.

Path

Source: (SDK root)\Samples\Multimedia\DDraw\Src\Stretch3

Executable: (SDK root)\Samples\Multimedia\DDraw\Bin

User's Guide

Resize the window to see the bitmap stretch. If you have more than one monitor attached to your computer, the window can be dragged from monitor to monitor.


Switcher Sample

Description

This sample shows how to switch between the normal and exclusive cooperative levels in DirectDraw.

Path

Source: (SDK root)\Samples\Multimedia\DDraw\Src\Switcher

Executable: (SDK root)\Samples\Multimedia\DDraw\Bin

User's Guide

Press ALT+ENTER to switch between full-screen and windowed mode. Quit the program by pressing ESC.

Programming Notes

In normal (windowed) mode, the sample assigns a clipper, shows the mouse cursor, and handles window moves, WM_PAINT messages, and pausing caused by losing focus to other applications. In exclusive (full-screen) mode it uses page flipping rather than blitting to update the scene.


Wormhole Sample

Description

This sample program shows how palette changes can create an animated effect.

Path

Source: (SDK root)\Samples\Multimedia\DDraw\Src\Wormhole

Executable: (SDK root)\Samples\Multimedia\DDraw\Bin

User's Guide

Press F12 or ESC to quit the program.

Programming Notes

Imagine a 4x4 display using 4 colors. We could set the colors up to look something like this:

Now we can cycle all of the colors in each row to the right. The one on the right will wrap-around to the left.

If we continue this cycling we would get animated lines moving to the right. The same can be done to animate the lines going down:

Now if we expand our palette to 16 color we can combine moving down and right at the same time.

Move right:

Move down:

Move right and down:

Now if you tile these 4x4 blocks end to end and cycle the colors as above, you get a moving checkerboard. Wormhole does the same thing, except that it uses 15x15 blocks (225 colors) and instead of tiling the blocks end to end on a flat plane, it tiles them in 3-D converging at the center of the wormhole.

The following code will generate the 3-D wormhole using the aforementioned 15x15 grids:

//Do all the work!
//convert r,theta,z to x,y,x to screen x,y
//plot the point
//z=-1.0+(log(2.0*j/DIVS) is the line that sets the math eqn for plot
//Feel free to try other functions!
//Cylindrical coordinates, e.g. z=f(r,theta)

#define STRETCH 25
#define PI      3.14159265358979323846
#define XCENTER 160
#define YCENTER 50
#define DIVS    1200
#define SPOKES  2400

void transarray(void)
    {
    float x,y,z;
    int i,j,color;
    for(j=1;j<DIVS+1;j++)
        for(i=0;i<SPOKES;i++)
            {
            z=-1.0+(log(2.0*j/DIVS));
            x=(320.0*j/DIVS*cos(2*PI*i/SPOKES));
            y=(240.0*j/DIVS*sin(2*PI*i/SPOKES));
            y=y-STRETCH*z;
            x+=XCENTER;
            y+=YCENTER;
            color=((i/8)%15)+15*((j/6)%15)+1;
            if ((x>=0)&&(x<=320)&&(y>=0)&&(y<=200))
                plot((int) x,(int) y,color);
            }
    }

After loading the bitmap to a DirectDraw surface, all that is left to do is rotate the colors and you have a wormhole.


DirectSound

This section provides information about the DirectSound® component of the Microsoft DirectX® application programming interface (API). Information is found under the following main headings:

  • About DirectSound
  • Why Use DirectSound?
  • DirectSound Architecture
  • DirectSound Essentials
  • DirectSound Tutorials
  • DirectSound Reference
  • DirectSound Samples


About DirectSound

The Microsoft® DirectSound® application programming interface (API) is the wave-audio component of the DirectX® API. DirectSound provides low-latency mixing, hardware acceleration, and direct access to the sound device. It provides this functionality while maintaining compatibility with existing device drivers.

DirectSound enables wave sound capture and playback. It also supports property sets, which enable application developers to take advantage of extended services offered by sound cards and their associated drivers.


Why Use DirectSound?

The overriding design goal in DirectX is speed. Like other components of DirectX, DirectSound allows you to use the hardware in the most efficient way possible while insulating you from the specific details of that hardware with a device-independent interface. Your applications will work well with the simplest audio hardware but will also take advantage of the special features of cards and drivers that have been enhanced for use with DirectSound.

Here are some other things that DirectSound makes easy:

  • Querying hardware capabilities at run time to determine the best solution for any given personal computer configuration
  • Using property sets so that new hardware capabilities can be exploited even when they are not directly supported by DirectSound
  • Low-latency mixing of audio streams for rapid response
  • Implementing three dimensional (3-D) sound
  • Capturing sound

Despite the advantages of DirectSound, the standard waveform-audio functions in Windows® continue to be a practical solution for certain tasks. For example, an application can easily play a single sound or audio stream, such as introductory music, by using the PlaySound or waveOut functions.


DirectSound Architecture

This section introduces the components of DirectSound and explains how DirectSound works with the hardware and with other applications. The following topics are discussed:

  • Architectural Overview for DirectSound
  • Sound Data
  • Playback Overview
  • Capture Overview
  • Property Sets Overview
  • Hardware Abstraction and Emulation
  • System Integration


Architectural Overview for DirectSound

DirectSound implements a new model for playing and capturing digital sound samples and mixing sample sources. Like other elements of the DirectX API, DirectSound uses the hardware to its greatest advantage whenever possible, and it emulates hardware features in software when the feature is not present in the hardware.

DirectSound playback is built on the IDirectSound Component Object Model (COM) interface and on other interfaces for manipulating sound buffers and 3-D effects. These interfaces are IDirectSoundBuffer, IDirectSound3DBuffer, and IDirectSound3DListener

DirectSound capture is based on the IDirectSoundCapture and IDirectSoundCaptureBuffer COM interfaces.

Another COM interface, IKsPropertySet, provides methods that allow applications to take advantage of extended capabilities of sound cards, even those introduced in the future.

Finally, the IDirectSoundNotify interface is used to signal events when playback or capture has reached a certain point in a buffer.

For more information about COM concepts that you should understand to create applications with the DirectX APIs, see The Component Object Model.


Sound Data

DirectSound and DirectSoundCapture work with waveform audio data, which consists of digital samples of the sound at a fixed frequency. The particular format of a sound can be described by a WAVEFORMATEX structure. This structure is documented in the Multimedia Structures section of the Platform SDK documentation, but is briefly described here for convenience:

typedef struct {
    WORD  wFormatTag;
    WORD  nChannels;
    DWORD nSamplesPerSec;
    DWORD nAvgBytesPerSec;
    WORD  nBlockAlign;
    WORD  wBitsPerSample;
    WORD  cbSize;
} WAVEFORMATEX;

The wFormatTag member contains a unique identifier assigned by Microsoft Corporation. A complete list can be found in the Mmreg.h header file. The only tag valid with DirectSound is WAVE_FORMAT_PCM. This tag indicates Pulse Code Modulation (PCM), an uncompressed format in which each samples represents the amplitude of the signal at the time of sampling. DirectSoundCapture can capture data in other formats by using the Audio Compression Manager.

For information on using non-PCM data with DirectSound, see Compressed Wave Formats.

The nChannels member describes the number of channels, usually either one (mono) or two (stereo). For stereo data, the samples are interleaved. The nSamplesPerSec member describes the sampling rate, or frequency, in hertz. Typical values are 11,025, 22,050, and 44,100.

The wBitsPerSample member gives the size of each sample, generally 8 or 16 bits. The value in nBlockAlign is the number of bytes required for each complete sample, and for PCM formats is equal to (wBitsPerSample * nChannels / 8). The value in nAvgBytesPerSec is the product of nBlockAlign and nSamplesPerSec.

Finally, cbSize gives the size of any extra fields required to describe a specialized wave format. This member is always zero for PCM formats.


Playback Overview

The DirectSound buffer object represents a buffer containing sound data. Buffer objects are used to start, stop, and pause sound playback, as well as to set attributes such as frequency and format.

The primary sound buffer holds the audio that the listener will hear. Secondary sound buffers each contain a single sound or stream of audio. DirectSound automatically creates a primary buffer, but it is the application's responsibility to create secondary buffers. When sounds in secondary buffers are played, DirectSound mixes them in the primary buffer and sends them to the output device. Only the available processing time limits the number of buffers that DirectSound can mix.

It is your responsibility to stream data in the correct format into the secondary sound buffers. DirectSound does not include methods for parsing a sound file or a wave resource. However, there is code in the accompanying sample applications that will help you with this task. For more information, see Using Wave Files and Reading Wave Data from a Resource.

Depending on the card type, DirectSound buffers can exist in hardware as on-board RAM, wave-table memory, a direct memory access (DMA) channel, or a virtual buffer (for an I/O port based audio card). Where there is no hardware implementation of a DirectSound buffer, it is emulated in system memory.

Multiple applications can create DirectSound objects for the same sound device. When the input focus changes between applications, the audio output automatically switches from one application's streams to another's. As a result, applications do not have to repeatedly play and stop their buffers when the input focus changes.

In order to know when a streaming buffer is ready to receive new data, or when any buffer has stopped, an application can use the IDirectSoundNotify interface to set up notification positions. When the play cursor reaches one of these positions, an event is signaled. Alternatively, an application can regularly poll the position of the play cursor.


Capture Overview

The DirectSoundCapture object is used to query the capabilities of sound capture devices and to create buffers for capturing audio from an input source. DirectSoundCapture allows capturing of data in PCM or compressed formats.

The DirectSoundCaptureBuffer object represents a buffer used for receiving data from the input device. Like playback buffers, this buffer is conceptually circular: when input reaches the end of the buffer, it automatically starts again at the beginning.

The methods of the DirectSoundCaptureBuffer object allow you to retrieve the properties of the buffer, start and stop audio capture, and lock portions of the memory so that you can safely retrieve data for saving to a file or for some other purpose.

As with playback, DirectSound allows you to request notification when captured data reaches a specified position within the buffer, or when capture has stopped. This service is provided through the IDirectSoundNotify interface.


Property Sets Overview

Through property sets, DirectSound is able to support extended services offered by manufacturers of sound cards and their associated drivers.

Hardware vendors define new capabilities as properties and publish the specification for these properties. You, the application developer, can then use the methods of the IKsPropertySet interface to determine whether a particular set of properties is available on the target hardware and to manipulate those properties, for instance by turning special effects on and off.

Property sets allow for the unlimited extension of the capabilities of DirectSound. You use a single method, IKsPropertySet::Set, to alter the state of the device in any way specified by the manufacturer.


Hardware Abstraction and Emulation

DirectSound accesses the sound hardware through the DirectSound hardware abstraction layer (HAL), an interface that is implemented by the audio-device driver.

The DirectSound HAL provides the following functionality:

  • Acquires and releases control of the audio hardware
  • Describes the capabilities of the audio hardware
  • Performs the specified operation when hardware is available
  • Causes the operation request to report failure when hardware is unavailable

The device driver does not perform any software emulation; it simply reports the capabilities of the hardware to DirectSound and passes requests from DirectSound to the hardware. If the hardware cannot perform a requested operation, the device driver reports failure of the request and DirectSound emulates the operation.

Your application can use DirectSound as long as the DirectX run-time files are present on the user's system. If the sound hardware does not have an installed DirectSound driver, DirectSound uses its hardware emulation layer (HEL), which employs the Windows multimedia waveform-audio (waveIn and waveOut) functions. Most DirectSound features are still available through the HEL, but of course hardware acceleration is not possible. To find out whether your application is running under an emulation driver, call the IDirectSound::GetCaps method and check for the DSCAPS_EMULDRIVER flag.

DirectSound automatically takes advantage of accelerated sound hardware, including hardware mixing and hardware sound-buffer memory. Your application need not query the hardware or program specifically to use hardware acceleration. However, for you to make the best possible use of the available hardware resources, you can query DirectSound at run time (by using the various GetCaps methods) to receive a full description of the capabilities of the sound device, and then use different routines optimized for the presence or absence of a given feature. You can also specify which sound buffers should receive hardware acceleration.


System Integration

The following illustration shows the relationships between DirectSound and other system audio components.

DirectSound and the standard Windows waveform-audio functions provide alternative paths to the waveform-audio portion of the sound hardware. A single device provides access from one path at a time. If a waveform-audio driver has allocated a device, an attempt to allocate that same device by using DirectSound will fail. Similarly, if a DirectSound driver has allocated a device, an attempt to allocate the device by using the waveform-audio driver will fail.

If two sound devices are installed in the system, your application can access each device independently through either DirectSound or the waveform-audio functions.

Note Microsoft Video for Windows currently uses the waveform-audio functions to play the audio track of an audio visual interleaved (.avi) file. Therefore, if your application is using DirectSound and you play an .avi file, the audio track will not be audible. Similarly, if you play an .avi file and attempt to create a DirectSound object, the creation function will return an error.

For now, applications can release the DirectSound object by calling IDirectSound::Release before playing an .avi file. Applications can then re-create and reinitialize the DirectSound object and its DirectSoundBuffer objects when the video finishes playing.


DirectSound Essentials

This section gives a practical overview of how the various DirectSound interfaces are used in order to play and capture sound. The following topics are discussed:

  • DirectSound Devices
  • DirectSound Buffers
  • DirectSound in 3-D
  • DirectSound 3-D Buffers
  • DirectSound 3-D Listeners
  • DirectSoundCapture
  • DirectSound Property Sets
  • Optimizing DirectSound Performance
  • Using Wave Files
  • Reading Wave Data from a Resource

Note Most of the examples of method calls throughout this section are given in the C language form, which accesses methods by means of a pointer to a table of pointers to functions, and requires a this pointer as the first parameter in any call. For example, a C call to the IDirectSound::GetCaps method takes this form:

lpDirectSound->lpVtbl->GetCaps(lpDirectSound, &dscaps);

The same method call in the C++ form, which treats COM interface methods just like class methods, looks like this:

lpDirectSound->GetCaps(&dscaps);

Dsound.h contains macros that expand to either the C or C++ form of the method call, depending on the environment. These macros simplify the C calls and also make it possible to develop routines that can be used in either language. For example:

IDirectSound_GetCaps(lpDirectSound, &dscaps);


DirectSound Devices

The first step in implementing DirectSound in an application is to create a DirectSound object, which represents a sound device and gives access to the IDirectSound interface.

This section describes how your application can enumerate available sound devices, create the DirectSound object for a device, and use the methods of the object to set the cooperative level, retrieve the capabilities of the device, create sound buffers, set the configuration of the system's speakers, and compact hardware memory.

  • Enumeration of Sound Devices
  • Creating the DirectSound Object
  • Cooperative Levels
  • Device Capabilities
  • Speaker Configuration
  • Compacting Hardware Memory


Enumeration of Sound Devices

For an application that is simply going to play sounds through the user's preferred playback device, you don't need to enumerate the available devices. When you create the DirectSound object with NULL as the device identifier, the interface will automatically be associated with the default device if one is present. (If no device driver is present, the call to the DirectSoundCreate function fails.)

However, if you are looking for a particular kind of device, wish to offer the user a choice of devices, or need to work with two or more devices, you must get DirectSound to enumerate the devices available on the system.

Enumeration serves three purposes:

  • Reports what hardware is available
  • Supplies a globally unique identifier (GUID) for each device
  • Allows you to initialize DirectSound for each device as it is enumerated, so that you can check the capabilities of the device

To enumerate devices you must first set up a callback function that will be called each time DirectSound finds a device. You can do anything you want within this function, and you can give it any name, but you must declare it in the same form as DSEnumCallback, a prototype in this documentation. The callback function must return TRUE if enumeration is to continue, or FALSE otherwise (for instance, after finding a device with the capabilities you need).

The following callback function, extracted from Dsenum.c in the Dsshow sample, adds information about each enumerated device to a combo box. Note that the first three parameters are supplied by the device driver. The fourth parameter is passed on from the DirectSoundEnumerate function.

BOOL CALLBACK DSEnumProc(LPGUID lpGUID,
                         LPCTSTR lpszDesc,
                         LPCTSTR lpszDrvName,
                         LPVOID lpContext )
{
    HWND   hCombo = *(HWND *)lpContext;
    LPGUID lpTemp = NULL;

    if ( lpGUID != NULL )
    {
        if (( lpTemp = malloc( sizeof(GUID))) == NULL )
        return( TRUE );

        memcpy( lpTemp, lpGUID, sizeof(GUID));
    }

    ComboBox_AddString( hCombo, lpszDesc );
    ComboBox_SetItemData( hCombo,
                ComboBox_FindString( hCombo, 0, lpszDesc ),
                lpTemp );
    return( TRUE );
}

The enumeration is set in motion when the dialog containing the combo box is initialized:

if FAILED(DirectSoundEnumerate((LPDSENUMCALLBACK)DSEnumProc,
        &hCombo))
{
    EndDialog( hDlg, TRUE );
    return( TRUE );
}

In this case the address of the combo box handle is passed into DirectSoundEnumerate, which in turn passes it to the callback function. This parameter can be any 32-bit value that you want to have access to within the callback.


Creating the DirectSound Object

The simplest way to create the DirectSound object is with the DirectSoundCreate function. The first parameter of this function specifies the GUID of the device to be associated with the object. You can obtain this GUID by Enumeration of Sound Devices, or you can simply pass NULL to create the object for the default device.

LPDIRECTSOUND lpds;
HRESULT hr = DirectSoundCreate(NULL, &lpds, NULL));

The function returns an error if there is no sound device or if the sound device is under the control of an application using the waveform-audio (non-DirectSound) functions. You should prepare your applications for this call to fail so that they can either continue without sound or prompt the user to close the application that is already using the sound device.

You can also create the DirectSound object by using the CoCreateInstance function, as follows:

  1. Initialize COM at the start of your application by calling CoInitialize and specifying NULL.
    if FAILED(CoInitialize(NULL))
    return FALSE;
  2. Create your DirectSound object by using CoCreateInstance and the IDirectSound::Initialize method, rather than the DirectSoundCreate function.
    LPDIRECTSOUND lpds;
dsrval = CoCreateInstance(&CLSID_DirectSound,
                          NULL,
                          CLSCTX_INPROC_SERVER,
                          &IID_IDirectSound,
                          &lpds);
if SUCCEEDED(dsrval)
    dsrval = IDirectSound_Initialize(lpds, NULL);

CLSID_DirectSound is the class identifier of the DirectSound driver object class and IID_IDirectSound is the DirectSound interface that you should use. The lpds parameter is the uninitialized object CoCreateInstance returns.

Before you use a DirectSound object created with the CoCreateInstance function, you must call the IDirectSound::Initialize method. This method takes the same driver GUID parameter that DirectSoundCreate uses (NULL in this case). After the DirectSound object is initialized, you can use and release the DirectSound object as if it had been created by using the DirectSoundCreate function.

Before you close the application, close the COM library by calling the CoUninitialize function, as follows:

CoUninitialize();


Cooperative Levels

Because Windows is a multitasking environment, more than one application may be working with a device driver at any one time. Through the use of cooperative levels, DirectX makes sure that each application does not gain access to the device in the wrong way or at the wrong time. Each DirectSound application has a cooperative level that determines the extent to which it is allowed to access the device.

After creating a DirectSound object, you must set the cooperative level for the device with the IDirectSound::SetCooperativeLevel method before you can play sounds.

DirectSound defines four cooperative levels for sound devices: normal, priority, exclusive, and write-primary. These are represented by the values DSSCL_NORMAL, DSSCL_PRIORITY, DSSCL_EXCLUSIVE, and DSSCL_WRITEPRIMARY.

Game applications should use DSSCL_PRIORITY in almost all circumstances. This level gives the most robust behavior while allowing the application control over sampling rate and bit depth. The priority cooperative level also allows audio from other applications (such as IP telephony) to be heard along with the audio from the game. The priority and exclusive levels provide identical performance, so DSSCL_EXCLUSIVE should be used only for applications that require all other applications to be muted. For a music-authoring application, for example, it might be critical that no other audio be heard during playback.

The following C example sets the cooperative level for the DirectSound device initialized at Creating the DirectSound Object. The hwnd parameter is the handle to the application window.

HRESULT hr = lpDirectSound->lpVtbl->SetCooperativeLevel(
        lpDirectSound, hwnd, DSSCL_PRIORITY);

Normal Cooperative Level

At the normal cooperative level, the application cannot set the format of the primary sound buffer, write to the primary buffer, or compact the on-board memory of the device. All applications at this cooperative level use a primary buffer format of 22 kHz, stereo sound, and 8-bit samples, so that the device can switch between applications as smoothly as possible.

Priority Cooperative Level

When using a DirectSound device with the priority cooperative level, the application has first rights to hardware resources, such as hardware mixing, and can set the format of the primary sound buffer and compact the on-board memory of the device.

Exclusive Cooperative Level

At the exclusive cooperative level, the application has all the privileges of the priority level. In addition, when the application is in the foreground, its buffers are the only ones that are audible.

Write-primary Cooperative Level

The highest cooperative level is write-primary. When using a DirectSound device with this cooperative level, your application has direct access to the primary sound buffer. In this mode, the application must write directly to the primary buffer. Secondary buffers cannot be played while this is happening.

An application must be set to the write-primary level in order to obtain direct write access to the audio samples in the primary buffer. If the application is not set to this level, then all calls to the IDirectSoundBuffer::Lock method for the primary buffer will fail.

When your application is set to the write-primary cooperative level and gains the foreground, all secondary buffers for other applications are stopped and marked as lost. When your application in turn moves to the background, its primary buffer is marked as lost and must be restored when the application again moves to the foreground. For more information, see Buffer Management.

You cannot set the write-primary cooperative level if a DirectSound driver is not present on the user's system. To determine whether this is the case, call the IDirectSound::GetCaps method and check for the DSCAPS_EMULDRIVER flag in the DSCAPS structure.

For more information, see Access to the Primary Buffer.


Device Capabilities

DirectSound allows your application to retrieve the hardware capabilities of the sound device. Most applications will not need to do this, because DirectSound automatically takes advantage of any available hardware acceleration. However, high-performance applications can use the information to scale their sound requirements to the available hardware. For example, an application might play more sounds if hardware mixing is available than if it is not.

After calling the DirectSoundCreate function to create a DirectSound object, your application can retrieve the capabilities of the sound device by calling the IDirectSound::GetCaps method.

The following example retrieves the capabilities of the device that was initialized in Creating the DirectSound Object.

DSCAPS dscaps;

dscaps.dwSize = sizeof(DSCAPS);
HRESULT hr = lpDirectSound->lpVtbl->GetCaps(lpDirectSound,
    &dscaps);

The DSCAPS structure receives information about the performance and resources of the sound device, including the maximum resources of each type and the resources that are currently available. Note that the dwSize member of this structure must be initialized before the method is called.

If your application scales to hardware capabilities, you should call the IDirectSound::GetCaps method between every buffer allocation to determine if there are enough resources to create the next buffer.


Speaker Configuration

DirectSound uses the speaker configuration—that is, the position of the speakers relative to the listener—to optimize 3-D effects for the user's sound system.

In Windows 98 and Windows 2000, the speaker configuration can be set by the user in Control Panel. An application can retrieve this value by using IDirectSound::GetSpeakerConfig and override it by calling IDirectSound::SetSpeakerConfig.

In Windows 95, GetSpeakerConfig simply returns a default value or the last value you set with SetSpeakerConfig.


Compacting Hardware Memory

As long as it has at least the priority cooperative level, your application can use the IDirectSound::Compact method to move any on-board sound memory into a contiguous block to make the largest portion of free memory available.


DirectSound Buffers

This section covers the creation and management of DirectSoundBuffer objects, which are the fundamental mechanism for playing sounds. The following topics are discussed:

  • Buffer Basics
  • Static and Streaming Sound Buffers
  • Creating Secondary Buffers
  • Buffer Control Options
  • Access to the Primary Buffer
  • Playing Sounds
  • Playback Controls
  • Current Play and Write Positions
  • Play Buffer Notification
  • Mixing Sounds
  • Custom Mixers
  • Buffer Management
  • Compressed Wave Formats

Most of the information in this section applies to 3-D sound buffers as well. For information specific to the IDirectSound3DBuffer interface, see DirectSound 3-D Buffers.

For information about capture buffers, see DirectSoundCapture.


Buffer Basics

When you initialize DirectSound in your application, it automatically creates and manages a primary sound buffer for mixing sounds and sending them to the output device.

Your application must create at least one secondary sound buffer for storing and playing individual sounds. For more information on how to do this, see Creating Secondary Buffers.

A secondary buffer can exist throughout the life of an application or it may be destroyed when no longer needed. It may contain a single sound that is to be played repeatedly, such as a sound effect in a game, or it may be filled with new data from time to time. The application can play a sound stored in a secondary buffer as a single event or as a looping sound that plays continuously. Secondary buffers can also be used to stream data, in cases where a sound file contains more data than can conveniently be stored in memory.

For more information on the different kinds of secondary buffers, see Static and Streaming Sound Buffers.

You can create two or more secondary buffers in the same physical memory by using the IDirectSound::DuplicateSoundBuffer method. Note that if the original buffer is in hardware memory and hardware resources are not available for the duplicate buffer, this call may fail.

You mix sounds from different secondary buffers simply by playing them at the same time. Any number of secondary buffers can be played at one time, up to the limits of available processing power.

The DirectSound mixer can provide as little as 20 milliseconds of latency, so there is no perceptible delay before play begins. Under these conditions, if your application plays a buffer and immediately begins a screen animation, the audio and video appear to start at the same time. However, if DirectSound must emulate hardware features in software, the mixer cannot achieve low latency and a longer delay (typically 100-150 milliseconds) occurs before the sound is reproduced.

Normally you do not have to concern yourself at all with the primary buffer; DirectSound manages it behind the scenes. However, if your application is to perform its own mixing, DirectSound will let you write directly to the primary buffer. If you do this, you cannot also use secondary buffers. For more information, see Access to the Primary Buffer.


Static and Streaming Sound Buffers

When you create a secondary sound buffer, you specify whether it is a static sound buffer or a streaming sound buffer. A static buffer contains a complete sound in memory. A streaming buffer holds only a portion of a sound, such as 3 seconds of data from a 15-second bit of voice dialog. When using a streaming sound buffer, your application must periodically write new data to the buffer.

If a sound device has on-board sound memory, DirectSound attempts to place static buffers in the hardware memory. These buffers can then take advantage of hardware mixing, and the processing system incurs little or no overhead to mix these sounds. This is particularly useful for sounds your application plays repeatedly, because the sound data must be downloaded only once to the hardware memory.

Streaming buffers are generally located in main system memory to allow efficient writing to the buffer, although you can use hardware mixing on peripheral component interconnect (PCI) machines or other fast buses.

DirectSound distinguishes between static and streaming buffers in order to optimize performance, but it does not restrict how you can use the buffer. If a streaming buffer is big enough, there is nothing to prevent you from writing an entire sound to it in one chunk. In fact, if you do not intend to use the sound more than once, it can be more efficient to use a streaming buffer because by doing so you eliminate the step of downloading the data to hardware memory.

Your application may attempt to explicitly locate buffers in hardware or software. If you attempt to create a hardware buffer and there is insufficient memory or mixing capacity, the buffer creation request fails. Many existing sound cards do not have any on-board memory or mixing capacity, so no hardware buffers can be created on these devices.

For more information, see Creating Secondary Buffers.


Creating Secondary Buffers

To create a sound buffer, your application fills a DSBUFFERDESC structure and then passes its address to the IDirectSound::CreateSoundBuffer method. This method creates a DirectSoundBuffer object and returns a pointer to an IDirectSoundBuffer interface. Your application uses this interface to manipulate and play the buffer.

The following example illustrates how to create a basic secondary sound buffer:

BOOL AppCreateBasicBuffer(
        LPDIRECTSOUND lpDirectSound,
        LPDIRECTSOUNDBUFFER *lplpDsb)
{
    PCMWAVEFORMAT pcmwf;
    DSBUFFERDESC dsbdesc;
    HRESULT hr;
    // Set up wave format structure.
    memset(&pcmwf, 0, sizeof(PCMWAVEFORMAT));
    pcmwf.wf.wFormatTag = WAVE_FORMAT_PCM;
    pcmwf.wf.nChannels = 2;
    pcmwf.wf.nSamplesPerSec = 22050;
    pcmwf.wf.nBlockAlign = 4;
    pcmwf.wf.nAvgBytesPerSec =
        pcmwf.wf.nSamplesPerSec * pcmwf.wf.nBlockAlign;
    pcmwf.wBitsPerSample = 16;
    // Set up DSBUFFERDESC structure.
    memset(&dsbdesc, 0, sizeof(DSBUFFERDESC)); // Zero it out.
    dsbdesc.dwSize = sizeof(DSBUFFERDESC);
    // Need default controls (pan, volume, frequency).
    dsbdesc.dwFlags = DSBCAPS_CTRLDEFAULT;
    // 3-second buffer.
    dsbdesc.dwBufferBytes = 3 * pcmwf.wf.nAvgBytesPerSec;
    dsbdesc.lpwfxFormat = (LPWAVEFORMATEX)&pcmwf;
    // Create buffer.
    hr = lpDirectSound->lpVtbl->CreateSoundBuffer(lpDirectSound,
        &dsbdesc, lplpDsb, NULL);
    if SUCCEEDED(hr)
    {
        // Valid interface is in *lplpDsb.
        return TRUE;
    }
    else
    {
        // Failed.
        *lplpDsb = NULL;
        return FALSE;
    }
}

Your application should create buffers for the most important sounds first, and then create buffers for other sounds in descending order of importance. DirectSound allocates hardware resources to the first buffer that can take advantage of them.

If your application must explicitly locate buffers in hardware or software, you can specify either the DSBCAPS_LOCHARDWARE or DSBCAPS_LOCSOFTWARE flag in the DSBUFFERDESC structure. If the DSBCAPS_LOCHARDWARE flag is specified and there is insufficient hardware memory or mixing capacity, the buffer creation request fails.

You can ascertain the location of an existing buffer by using the IDirectSoundBuffer::GetCaps method and checking the dwFlags member of the DSBCAPS structure for either the DSBCAPS_LOCHARDWARE or DSBCAPS_LOCSOFTWARE flags. One or the other is always specified.

When you create a sound buffer, you can indicate that a buffer is static by specifying the DSBCAPS_STATIC flag. If you do not specify this flag, the buffer is a streaming buffer. For more information, see Static and Streaming Sound Buffers.

DirectSoundBuffer objects are owned by the DirectSound object that created them. When the DirectSound object is released, all buffers created by that object also will be released and should not be referenced.


Buffer Control Options

When creating a sound buffer, your application must specify the control options needed for that buffer. This is done with the dwFlags member of the DSBUFFERDESC structure, which can contain one or more DSBCAPS_CTRL* flags. The following controls are available:

  • 3-D properties
  • Frequency
  • Pan
  • Volume
  • Position notification

To obtain the best performance on all sound cards, your application should specify only control options it will use.

DirectSound uses the control options in determining whether hardware resources can be allocated to sound buffers. For example, a device might support hardware buffers but provide no pan control on those buffers. In this case, DirectSound would use hardware acceleration only if the DSBCAPS_CTRLPAN flag was not specified.

If your application attempts to use a control that a buffer lacks, the method call fails. For example, if you attempt to change the volume by using the IDirectSoundBuffer::SetVolume method, the method can succeed only if the DSBCAPS_CTRLVOLUME flag was specified when the buffer was created. Otherwise the method fails and returns the DSERR_CONTROLUNAVAIL error code.


Access to the Primary Buffer

For applications that require specialized mixing or other effects not supported by secondary buffers, DirectSound allows direct access to the primary buffer.

When you obtain write access to a primary sound buffer, other DirectSound features become unavailable. Secondary buffers are not mixed and, consequently, hardware-accelerated mixing is unavailable.

Most applications should use secondary buffers instead of directly accessing the primary buffer. Applications can write to a secondary buffer easily because the larger buffer size provides more time to write the next block of data, thereby minimizing the risk of gaps in the audio. Even if an application has simple audio requirements, such as using one stream of audio data that does not require mixing, it will achieve better performance by using a secondary buffer to play its audio data.

You cannot specify the size of the primary buffer, and you must accept the returned size after the buffer is created. A primary buffer is typically very small, so if your application writes directly to this kind of buffer, it must write blocks of data at short intervals to prevent the previously written data from being replayed.

You create an accessible primary buffer by specifying the DSBCAPS_PRIMARYBUFFER flag in the DSBUFFERDESC structure passed to the IDirectSound::CreateSoundBuffer method. If you want to write to the buffer, the cooperative level must be DSSCL_WRITEPRIMARY.

You cannot obtain write access to a primary buffer unless it exists in hardware. To determine whether this is the case, call the IDirectSoundBuffer::GetCaps method and check for the DSBCAPS_LOCHARDWARE flag in the dwFlags member of the DSBCAPS structure that is returned. If you attempt to lock a primary buffer that is emulated in software, the call will fail.

Primary sound buffers must be played with looping. Ensure that the DSBPLAY_LOOPING flag is set.

The following example shows how to obtain write access to the primary buffer:

BOOL AppCreateWritePrimaryBuffer(
    LPDIRECTSOUND lpDirectSound,
    LPDIRECTSOUNDBUFFER *lplpDsb,
    LPDWORD lpdwBufferSize,
    HWND hwnd)
{
    DSBUFFERDESC dsbdesc;
    DSBCAPS dsbcaps;
    HRESULT hr;
    WAVEFORMATEX wf;

    // Set up wave format structure.
    memset(&wf, 0, sizeof(WAVEFORMATEX));
    wf.wFormatTag = WAVE_FORMAT_PCM;
    wf.nChannels = 2;
    wf.nSamplesPerSec = 22050;
    wf.nBlockAlign = 4;
    wf.nAvgBytesPerSec =
        wf.nSamplesPerSec * wf.nBlockAlign;
    wf.wBitsPerSample = 16;

    // Set up DSBUFFERDESC structure.
    memset(&dsbdesc, 0, sizeof(DSBUFFERDESC));
    dsbdesc.dwSize = sizeof(DSBUFFERDESC);
    dsbdesc.dwFlags = DSBCAPS_PRIMARYBUFFER;
    // Buffer size is determined by sound hardware.
    dsbdesc.dwBufferBytes = 0;
    dsbdesc.lpwfxFormat = NULL; // Must be NULL for primary buffers.

    // Obtain write-primary cooperative level.
    hr = lpDirectSound->lpVtbl->SetCooperativeLevel(lpDirectSound,
        hwnd, DSSCL_WRITEPRIMARY);
    if SUCCEEDED(hr)
    {
        // Try to create buffer.
        hr = lpDirectSound->lpVtbl->CreateSoundBuffer(lpDirectSound,
            &dsbdesc, lplpDsb, NULL);
        if SUCCEEDED(hr)
        {
            // Set primary buffer to desired format.
            hr = (*lplpDsb)->lpVtbl->SetFormat(*lplpDsb, &wf);
            if SUCCEEDED(hr)
            {
                // If you want to know the buffer size, call GetCaps.
                    dsbcaps.dwSize = sizeof(DSBCAPS);
                (*lplpDsb)->lpVtbl->GetCaps(*lplpDsb, &dsbcaps);
                *lpdwBufferSize = dsbcaps.dwBufferBytes;
                return TRUE;
            }
        }
    }
    // Failure.
    *lplpDsb = NULL;
    *lpdwBufferSize = 0;
    return FALSE;
}

You may also create a primary buffer object without write access, by specifying a cooperative level other than DSSCL_WRITEPRIMARY. One reason for doing this would be to call the IDirectSoundBuffer::Play method for the primary buffer, in order to eliminate problems associated with frequent short periods of silence. For more information, see Playing the Primary Buffer Continuously.

See also Custom Mixers.


Playing Sounds

Playing a sound consists of the following steps:

  1. Lock a portion of the secondary buffer using IDirectSoundBuffer::Lock. This method returns a pointer to the address where writing will begin, based on the offset from the beginning of the buffer that you pass in to the method.
  2. Write the audio data to the buffer.
  3. Unlock the buffer using IDirectSoundBuffer::Unlock.
  4. Send the sound to the primary buffer and from there to the output device using IDirectSoundBuffer::Play. If the buffer is a streaming buffer, it will continue playing in a loop as steps 1 to 3 are repeated.

Because streaming sound buffers usually play continually and are conceptually circular, DirectSound returns two write pointers when locking a sound buffer. For example, if you tried to lock 3,000 bytes beginning at the midpoint of a 4,000-byte buffer, the Lock method would return one pointer to the last 2,000 bytes of the buffer, and a second pointer to the first 1,000 bytes. The second pointer is NULL if the locked portion of the buffer does not wrap around.

Normally the buffer stops playing automatically when the end is reached. However, if the DSBPLAY_LOOPING flag was set in the dwFlags parameter to the Play method, the buffer plays repeatedly until the application calls the IDirectSoundBuffer::Stop method.

For streaming sound buffers, your application is responsible for ensuring that each block of data is written to the buffer ahead of the current play position. (For more on the play position, see Current Play and Write Positions.) Applications should write at least 1 second ahead of the current play position to minimize the possibility of gaps in the audio output during playback.

The following C example writes data to a sound buffer, starting at the offset into the buffer passed in dwOffset:

BOOL AppWriteDataToBuffer(
    LPDIRECTSOUNDBUFFER lpDsb,  // the DirectSound buffer
    DWORD dwOffset,             // our own write cursor
    LPBYTE lpbSoundData,        // start of our data
    DWORD dwSoundBytes)         // size of block to copy
{
    LPVOID  lpvPtr1;
    DWORD   dwBytes1;
    LPVOID  lpvPtr2;
    DWORD   dwBytes2;
    HRESULT hr;

    // Obtain memory address of write block. This will be in two parts
    // if the block wraps around.
    hr = lpDsb->lpVtbl->Lock(lpDsb, dwOffset, dwSoundBytes, &lpvPtr1,
        &dwBytes1, &lpvPtr2, &dwBytes2, 0);

    // If DSERR_BUFFERLOST is returned, restore and retry lock.
    if (DSERR_BUFFERLOST == hr)
    {
        lpDsb->lpVtbl->Restore(lpDsb);
        hr = lpDsb->lpVtbl->Lock(lpDsb, dwOffset, dwSoundBytes,
            &lpvPtr1, &dwAudio1, &lpvPtr2, &dwAudio2, 0);
    }
    if SUCCEEDED(hr)
    {
        // Write to pointers.
        CopyMemory(lpvPtr1, lpbSoundData, dwBytes1);
        if (NULL != lpvPtr2)
        {
            CopyMemory(lpvPtr2, lpbSoundData+dwBytes1, dwBytes2);
        }
        // Release the data back to DirectSound.
        hr = lpDsb->lpVtbl->Unlock(lpDsb, lpvPtr1, dwBytes1, lpvPtr2,
            dwBytes2);
        if SUCCEEDED(hr)
        {
            // Success.
            return TRUE;
        }
    }
    // Lock, Unlock, or Restore failed.
    return FALSE;
}


Playback Controls

To retrieve and set the volume at which a buffer is played, your application can use the IDirectSoundBuffer::GetVolume and IDirectSoundBuffer::SetVolume methods. Setting the volume on the primary sound buffer changes the waveform-audio volume of the sound card.

Similarly, by calling the IDirectSoundBuffer::GetFrequency and IDirectSoundBuffer::SetFrequency methods, you can retrieve and set the frequency at which audio samples play. You cannot change the frequency of the primary buffer.

To retrieve and set the pan, you can call the IDirectSoundBuffer::GetPan and IDirectSoundBuffer::SetPan methods. You cannot change the pan of the primary buffer.

In order to use any of these controls, you must have set the appropriate flags when creating the buffer. See Buffer Control Options.


Current Play and Write Positions

DirectSound maintains two pointers into the buffer: the current play position (sometimes called the play cursor) and the current write position (or write cursor). These positions are byte offsets into the buffer, not absolute memory addresses.

The IDirectSoundBuffer::Play method always starts playing at the buffer's current play position. When a buffer is created, the play position is set to zero. As a sound is played, the play position moves and always points to the next byte of data to be output. When the buffer is stopped, the play position remains at the next byte of data.

The current write position is the point after which it is safe to write data into the buffer. The block between the current play position and the current write position is already committed to be played, and cannot be changed safely.

Visualize the buffer as a clock face, with data written to it in a clockwise direction. The play position and the write position are like two hands sweeping around the face at the same speed, the write position always keeping a little ahead of the play position. If the play position points to the 1 and the write position points to the 2, it is only safe to write data after the 2. Data between the 1 and the 2 may already have been queued for playback by DirectSound and should not be touched.

Note The write position moves with the play position, not with data written to the buffer. If you're streaming data, you are responsible for maintaining your own pointer into the buffer to indicate where the next block of data should be written.

Also note that the dwWriteCursor parameter to the IDirectSoundBuffer::Lock method is not the current write position; it is the offset within the buffer where you actually intend to begin writing data. (If you do want to begin writing at the current write position, you specify DSBLOCK_FROMWRITECURSOR in the dwFlags parameter. In this case the dwWriteCursor parameter is ignored.)

An application can retrieve the current play and write positions by calling the IDirectSoundBuffer::GetCurrentPosition method. The IDirectSoundBuffer::SetCurrentPosition method lets you set the current play position, but the current write position cannot be changed.

To ensure that the current play position is reported as accurately as possible, you should always specify the DSBCAPS_GETCURRENTPOSITION2 flag when creating a secondary buffer. For more information, see DSBUFFERDESC.


Play Buffer Notification

When streaming audio, you may want your application to be notified when the current play position reaches a certain point in the buffer, or when playback is stopped. With the IDirectSoundNotify::SetNotificationPositions method you can set any number of points within the buffer where events are to be signaled. You cannot do this while the buffer is playing.

First you have to obtain a pointer to the IDirectSoundNotify interface. You can do this by using the buffer object's QueryInterface method, as in the following C++ example:

// LPDIRECTSOUNDBUFFER lpDsbSecondary;
// The buffer has been initialized already.

LPDIRECTSOUNDNOTIFY lpDsNotify;  // pointer to the interface

HRESULT hr = lpDsbSecondary->QueryInterface(IID_IDirectSoundNotify,
                                            (LPVOID *)&lpDsNotify);
if SUCCEEDED(hr)
{
    // Go ahead and use lpDsNotify->SetNotificationPositions.
}

Note The IDirectSoundNotify interface is associated with the object that obtained the pointer, in this case the secondary buffer. The methods of the new interface will automatically apply to that buffer.

Now create an event object with the Win32® CreateEvent function. You put the handle to this event in the hEventNotify member of a DSBPOSITIONNOTIFY structure, and in the dwOffset member of that structure you specify the offset within the buffer where you want the event to be signaled. Then you pass the address of the structure—or of an array of structures, if you want to set more than one notification position—to the IDirectSoundNotify::SetNotificationPositions method.

The following example sets a single notification position. The event will be signaled when playback stops, either because it was not looping and the end of the buffer has been reached, or because the application called the IDirectSoundBuffer::Stop method.

DSBPOSITIONNOTIFY PositionNotify;

PositionNotify.Offset = DSBPN_OFFSETSTOP;
PositionNotify.hEventNotify = hMyEvent;
// hMyEvent is the handle returned by CreateEvent()

lpDsNotify->SetNotificationPositions(1, &PositionNotify);


Mixing Sounds

It is easy to mix multiple streams with DirectSound. You simply create secondary sound buffers, obtaining an IDirectSoundBuffer interface for each sound. You then play the buffers simultaneously. DirectSound takes care of the mixing in the primary sound buffer and plays the result.

The DirectSound mixer can obtain the best results from hardware acceleration if your application correctly specifies the DSBCAPS_STATIC flag for static buffers. This flag should be specified for any static buffers that will be reused. DirectSound downloads these buffers to the sound hardware memory, where available, and consequently does not incur any processing overhead in mixing these buffers. The most important static sound buffers should be created first to give them first priority for hardware acceleration.

The DirectSound mixer produces the best sound quality if all your application's sounds use the same wave format and the hardware output format is matched to the format of the sounds. If this is done, the mixer need not perform any format conversion.

Your application can change the hardware output format by creating a primary sound buffer and calling the IDirectSoundBuffer::SetFormat method. Note that this primary buffer is for control purposes only; creating it is not the same as obtaining write access to the primary buffer as described under Access to the Primary Buffer, and you do not need the DSSCL_WRITEPRIMARY cooperative level. However, you do need a cooperative level of DSSCL_PRIORITY or higher in order to call the SetFormat method. DirectSound will restore the hardware format to the format specified in the last call every time the application gains the input focus.


Custom Mixers

Most applications will use the DirectSound mixer; it should be sufficient for almost all mixing needs and it automatically takes advantage of any available hardware acceleration. However, if an application requires some other functionality that DirectSound does not provide, it can obtain write access to the primary sound buffer and mix streams directly into it.

To implement a custom mixer, the application must first set the DSSCL_WRITEPRIMARY cooperative level and then create a primary sound buffer. (See Access to the Primary Buffer.) It can then lock the buffer, write data to it, unlock it, and play it just like any other buffer. (See Playing Sounds.) Note however that the DSBPLAY_LOOPING flag must be specified or the IDirectSoundBuffer::Play call will fail.

The following example illustrates how an application might implement a custom mixer. The AppMixIntoPrimaryBuffer sample function would have to be called at regular intervals, frequently enough to prevent the sound device from repeating blocks of data. The CustomMixer function is an application-defined function that mixes several streams together, as specified in the application-defined AppStreamInfo structure, and writes the result to the specified pointer.

BOOL AppMixIntoPrimaryBuffer(
        LPAPPSTREAMINFO lpAppStreamInfo,
        LPDIRECTSOUNDBUFFER lpDsbPrimary,
        DWORD dwDataBytes,
        DWORD dwOldPos,
        LPDWORD lpdwNewPos)
{
    LPVOID lpvPtr1;
    DWORD dwBytes1;
    LPVOID lpvPtr2;
    DWORD dwBytes2;
    HRESULT hr;
    // Obtain write pointer.
    hr = lpDsbPrimary->lpVtbl->Lock(lpDsbPrimary,
                                    dwOldPos, dwDataBytes,
                                    &lpvPtr1, &dwBytes1,
                                    &lpvPtr2, &dwBytes2, 0);
    // If DSERR_BUFFERLOST is returned, restore and retry lock.
    if (DSERR_BUFFERLOST == hr)
    {
        lpDsbPrimary->lpVtbl->Restore(lpDsbPrimary);
        hr = lpDsbPrimary->lpVtbl->Lock(lpDsbPrimary,
                                        dwOldPos, dwDataBytes,
                                        &lpvPtr1, &dwBytes1,
                                        &lpvPtr2, &dwBytes2, 0);
    }
    if SUCCEEDED(hr)
    {
        // Mix data into the returned pointers.
        CustomMixer(lpAppStreamInfo, lpvPtr1, dwBytes1);
        *lpdwNewPos = dwOldPos + dwBytes1;
        if (NULL != lpvPtr2)
        {
            CustomMixer(lpAppStreamInfo, lpvPtr2, dwBytes2);
            *lpdwNewPos = dwBytes2; // Because it wrapped around.
        }
        // Release the data back to DirectSound.
        hr = lpDsbPrimary->lpVtbl->Unlock(lpDsbPrimary,
                                          lpvPtr1, dwBytes1,
                                          lpvPtr2, dwBytes2);
        if SUCCEEDED(hr)
        {
            return TRUE;
        }
    }
    // Lock or Unlock failed.
    return FALSE;
}


Buffer Management

The IDirectSoundBuffer::GetCaps method retrieves the capabilities of the DirectSoundBuffer object.

Your application can use the IDirectSoundBuffer::GetStatus method to determine if the current sound buffer is playing or if it has stopped.

You can use the IDirectSoundBuffer::GetFormat method to retrieve information about the format of the sound data in the buffer. You also can use the IDirectSoundBuffer::GetFormat and IDirectSoundBuffer::SetFormat methods to retrieve and set the format of the sound data in the primary sound buffer.

Note After a secondary sound buffer is created, its format is fixed. If you need a secondary buffer that uses another format, you must create a new sound buffer with this format.

Memory for a sound buffer can be lost in certain situations: for example, when buffers are located in sound card memory and another application gains control of the hardware resources. Loss can also occur when an application with the write-primary cooperative level moves to the foreground; in this case, DirectSound makes all other sound buffers lost so that the foreground application can write directly to the primary buffer.

The DSERR_BUFFERLOST error code is returned when the IDirectSoundBuffer::Lock or IDirectSoundBuffer::Play method is called for a lost buffer. When the application that caused the loss either lowers its cooperative level from write-primary or moves to the background, other applications can attempt to reallocate the buffer memory by calling the IDirectSoundBuffer::Restore method. If successful, this method restores the buffer memory and all other settings for the buffer, such as volume and pan settings. However, a restored buffer may not contain valid sound data, so the owning application should rewrite the data to the buffer.


Compressed Wave Formats

DirectSound does not currently support compressed wave formats. Applications should use the audio compression manager (ACM) functions, provided with the Win32 APIs in the Platform SDK, to convert compressed audio to pulse-code modulation (PCM) format before writing the data to a sound buffer. In fact, by locking a pointer to the sound-buffer memory and passing this pointer to the ACM, the data can be decoded directly to the sound buffer for maximum efficiency.


DirectSound in 3-D

DirectSound enables an application to change the apparent position and orientation of a sound source or listener, and also to suggest the relative velocity of the source and listener by using Doppler shift.

The following topics cover some general aspects of 3-D sound:

  • Integration with Direct3D
  • Mono and Stereo Sources
  • Perception of Sound Positions

Information on how to use 3-D sound in an application is found in the following sections:

  • DirectSound 3-D Buffers
  • DirectSound 3-D Listeners


Integration with Direct3D

The IDirectSound3DBuffer and IDirectSound3DListener interfaces are designed to work together with Direct3D®. The positioning information used by Direct3D to arrange objects in a virtual environment can also be used to arrange sound sources. The D3DVECTOR and D3DVALUE types that are familiar to Direct3D programmers are also used in the IDirectSound3DBuffer and IDirectSound3DListener interfaces. The same left-handed coordinate system used by Direct3D is employed by DirectSound. (For information about coordinate systems, see 3-D Coordinate Systems, in the Direct3D overview material.)

You can use the system callback mechanism of Direct3D to simplify the implementation of 3-D sound in your application. For example, you could use the D3DRMFRAMEMOVECALLBACK application-defined function to monitor the movement of a frame in an application and change the sonic environment only when a certain condition has been reached.

In DirectSound, distances are normally measured in meters. If your application does not use the meter as its unit of measure for 3-D graphics, you can set a distance factor, which is a floating-point value representing meters per application-specified distance unit. For example, if your application uses feet, it could specify a DirectSound distance factor of .3048, which is the number of meters in a foot.


Mono and Stereo Sources

Stereo sound sources are not particularly useful in the 3-D sound environments of DirectSound, because DirectSound creates its own stereo output from a monaural input. If an application uses stereo sound buffers, the left and right values for each sample are averaged before the 3-D processing is applied.

Applications should supply monaural sound sources when using the 3-D capabilities of DirectSound. Although the system can convert a stereo source into mono, there is no reason to supply stereo, and the conversion step wastes time.


Perception of Sound Positions

In the real world, the perception of a sound's position in space is influenced by a number of factors, including the following:

  • Volume. The farther an object is from the listener, the quieter it sounds. This phenomenon is known as rolloff.
  • Interaural intensity difference. A sound coming from the listener's right will sound louder in the right ear than in the left. This effect is familiar to anyone who has listened to a stereo sound system.
  • Interaural time difference. A sound emitted by a source to the listener's right will arrive at the right ear slightly before it arrives at the left ear. (The duration of this offset is approximately a millisecond.)
  • Muffling. The orientation of the ears ensures that sounds coming from behind the listener are slightly muffled compared with sounds coming from in front. In addition, if a sound is coming from the right, the sound reaching the left ear will be muffled by the mass of the listener's head as well as by the orientation of the left ear.

Although these are not the only cues people use to discern the position of sound, they are the main ones, and they are the factors that have been implemented in the positioning system of DirectSound. Hardware optimized for 3-D sound can support other cues as well, such as the effect of the earlobes on the pitch and timing of sounds arriving from different directions. The mathematics behind this effect are known as the head-related transfer function.

One of the most important sound-positioning cues, however, is still the apparent visual position of the sound source. If a projectile appears as a dot in the distance and grows to the size of an intercontinental missile before it roars past the viewer's head, the listener does not need subtle acoustical cues in order to sense the position and velocity of the sound source.


DirectSound 3-D Buffers

A 3-D sound buffer is created and managed like any other sound buffer, and all the methods of the IDirectSoundBuffer interface are available. However, in order to set 3-D parameters you need to obtain the IDirectSound3DBuffer interface for the buffer. This interface is supported only by sound buffers created with the DSBCAPS_CTRL3D flag.

This section describes how your applications can manage buffers with the IDirectSound3DBuffer interface methods. The following topics are discussed:

  • Obtaining the IDirectSound3DBuffer Interface
  • Batch Parameters for IDirectSound3DBuffer
  • Minimum and Maximum Distances
  • Processing Mode
  • Buffer Position and Velocity
  • Sound Cones


Obtaining the IDirectSound3DBuffer Interface

To obtain a pointer to an IDirectSound3DBuffer interface, you must first create a secondary 3-D sound buffer. Do this by using the IDirectSound::CreateSoundBuffer method, specifying the DSBCAPS_CTRL3D flag in the dwFlags member of the DSBUFFERDESC structure parameter. Then, use the IDirectSoundBuffer::QueryInterface method on the resulting buffer to obtain a pointer to an IDirectSound3DBuffer interface for that buffer.

The following example calls the QueryInterface method with the C++ syntax:

// LPDIRECTSOUNDBUFFER lpDsbSecondary;
// The buffer has been created with DSBCAPS_CTRL3D.
LPDIRECTSOUND3DBUFFER lpDs3dBuffer;

HRESULT hr = lpDsbSecondary->QueryInterface(IID_IDirectSound3DBuffer,
                                            (LPVOID *)&lpDs3dBuffer);
if SUCCEEDED(hr)
{
    // Set 3-D parameters of this sound.
    .
    .
    .
}

Note Pan control conflicts with 3-D processing. If both DSBCAPS_CTRL3D and DSBCAPS_CTRLPAN are specified when the buffer is created, DirectSound returns an error.


Batch Parameters for IDirectSound3DBuffer

Applications can retrieve or set a 3-D sound buffer's parameters individually or in batches. To set individual values, your application can use the applicable IDirectSound3DBuffer interface method. However, applications often must set or retrieve all the values at once. You can do this with the IDirectSound3DBuffer::GetAllParameters and IDirectSound3DBuffer::SetAllParameters methods.


Minimum and Maximum Distances

As a listener approaches a sound source, the sound gets louder: the volume doubles when the distance is halved. Past a certain point, however, it is not reasonable for the volume to continue to increase. This is the minimum distance for the sound source.

The minimum distance is especially useful when an application must compensate for the difference in absolute volume levels of different sounds. Although a jet engine is much louder than a bee, for example, for practical reasons these sounds must be recorded at similar absolute volumes. An application might use a minimum distance of 100 meters for the jet engine and 2 centimeters for the bee. With these settings, the jet engine would be at half volume when the listener was 200 meters away, but the bee would be at half volume when the listener was 4 centimeters away.

The default minimum distance for a sound buffer, DS3D_DEFAULTMINDISTANCE, is currently defined as 1 unit. Unless you change this value, the sound will be only half as loud when it is 2 meters away from the user, a quarter as loud at 4 meters, and so on. For most sounds you will probably want to set a larger minimum distance.

The maximum distance for a sound source is the distance beyond which the sound does not get any quieter. The default maximum distance for a DirectSound 3-D buffer (DS3D_DEFAULTMAXDISTANCE) is a huge number, meaning that in most cases the attenuation will continue to be calculated even when the sound ceases to be audible. In order to avoid unnecessary processing, applications should set a reasonable maximum distance and include the DSBCAPS_MUTE3DATMAXDISTANCE flag when creating the buffer.

The maximum distance can also be used to prevent a sound from becoming inaudible. For example, if you have set the minimum distance for a sound at 100 meters, that sound might become effectively inaudible at 1,000 meters or less. By setting the maximum distance at 800 meters you would ensure that the sound always had at least one-eighth of its maximum volume regardless of the distance. In this case, of course, you would not set the DSBCAPS_MUTE3DATMAXDISTANCE flag.

The following illustration shows the concepts of minimum and maximum distance.

An application sets and retrieves the minimum distance value by using the IDirectSound3DBuffer::SetMinDistance and IDirectSound3DBuffer::GetMinDistance methods. Similarly, it can set and retrieve the maximum distance value by using the IDirectSound3DBuffer::SetMaxDistance and IDirectSound3DBuffer::GetMaxDistance methods.

By default, distance values are expressed in meters. See Distance Factor.

To adjust the effect of distance on volume for all sound buffers, you can change the Rolloff Factor.


Processing Mode

Sound buffers have three processing modes: normal, head-relative, and disabled.

In normal mode, the sound source is positioned and oriented absolutely in world space. This is the default mode.

In head-relative mode, the buffer is automatically repositioned in world space as the listener moves and turns. Values set and retrieved through methods such as IDirectSound3DBuffer::SetPosition, IDirectSound3DBuffer::SetVelocity, and IDirectSound3DBuffer::GetConeOrientation are all relative to the current position, velocity, and orientation of the listener.

In disabled mode, 3-D sound processing is disabled and the sound seems to originate from the center of the listener's head.

An application sets the mode for a 3-D sound buffer by using the IDirectSound3DBuffer::SetMode method.


Buffer Position and Velocity

An application can set and retrieve a sound source's position in 3-D space by using the IDirectSound3DBuffer::SetPosition and IDirectSound3DBuffer::GetPosition methods. A position is expressed as a vector, relative to either world space or the listener, depending on the processing mode.

To set or retrieve the velocity value that DirectSound uses to calculate Doppler-shift effects for a listener, you use the IDirectSound3DBuffer::SetVelocity and IDirectSound3DBuffer::GetVelocity methods. Velocity is measured in distance units per second—by default, meters per second.

Note that velocity is completely independent of the actual position or movement of a buffer. It is entirely up to the application to set the appropriate velocity for a buffer.


Sound Cones

A sound with no orientation is a point source; the amplitude of the sound at a given distance is the same in all directions. A sound with an orientation is a sound cone.

In DirectSound, sound cones are made up of an inside cone and an outside cone. Within the inside cone, the volume of the sound is just what it would be if there were no cone; in other words, there is no attenuation from the normal volume. (Of course, normal volume is not necessarily maximum volume. It has already been modified by the basic volume of the buffer — as set by the IDirectSoundBuffer::SetVolume method — as well as by the distance from the listener, the listener's orientation, the rolloff factor, and the buffer's minimum distance value.) Outside the outside cone, the normal volume is attenuated by a specified number of decibels, as set by the application. The angle between the inside and outside cones is a zone of transition from the inside volume to the outside volume.

The following illustration shows the concept of sound cones.

Technically, any 3-D sound buffer in DirectSound is a sound cone, but by default a buffer behaves like an omnidirectional sound source, because the outside volume is 0 (that is, there is no attenuation), and the inside and outside cone angles are 360 degrees. Until the application changes these values, the sound will not have any apparent orientation.

Designing sound cones properly can add dramatic effects to your application. For example, you could position a sound source in the center of a room, setting its orientation toward an open door in a hallway. Then set the angle of the inside cone so that it extends to the width of the doorway, make the outside cone a bit wider, and set the outside cone volume to inaudible. A listener moving along the hallway will begin to hear the sound when near the doorway, and the sound will be loudest as the listener passes in front of the open door.

An application sets or retrieves the angles that define sound cones by using the IDirectSound3DBuffer::SetConeAngles and IDirectSound3DBuffer::GetConeAngles methods. The outside cone angle must always be equal to or greater than the inside cone angle.

To set or retrieve the orientation of sound cones, an application can use the IDirectSound3DBuffer::SetConeOrientation and IDirectSound3DBuffer::GetConeOrientation methods.

An application sets and retrieves the outside cone volume by using the IDirectSound3DBuffer::SetConeOutsideVolume and IDirectSound3DBuffer::GetConeOutsideVolume methods. The outside cone volume is expressed in hundredths of decibels and is a negative value, because it represents attenuation from the default volume of 0.


DirectSound 3-D Listeners

A sound is only a sound when it is heard. The 3-D sound effects in a DirectSound application are affected not only by the position, orientation, and velocity of the sound buffer, but also by the position, orientation, and velocity of the listener.

The IDirectSound3DListener interface controls the listener's position, orientation, and apparent velocity in 3-D space. It also controls the general parameters of the acoustic environment, such as the amount of Doppler shift and the rate of volume attenuation over distance.

This section describes how your application can obtain a pointer to an IDirectSound3DListener interface and manage listener parameters by using interface methods. The following topics are discussed:

  • Obtaining the IDirectSound3DListener Interface
  • Batch Parameters for IDirectSound3DListener
  • Deferred Settings
  • Distance Factor
  • Listener Orientation
  • Listener Position and Velocity
  • Doppler Factor
  • Rolloff Factor


Obtaining the IDirectSound3DListener Interface

To obtain a pointer to an IDirectSound3DListener interface, you must first create a primary 3-D sound buffer. Do this by using the IDirectSound::CreateSoundBuffer method, specifying the DSBCAPS_CTRL3D and DSBCAPS_PRIMARYBUFFER flags in the dwFlags member of the accompanying DSBUFFERDESC structure. Then, use the IDirectSoundBuffer::QueryInterface method on the resulting buffer to obtain a pointer to an IDirectSound3DListener interface for that buffer, as shown in the following example with C++ syntax:

/* In this example, it is assumed that lpds is a valid
   pointer to a DirectSound object */

DSBUFFERDESC        dsbd;
LPDIRECTSOUNDBUFFER lpdsbPrimary;

ZeroMemory(&dsbd, sizeof(DSBUFFERDESC));
dsbd.dwSize = sizeof(DSBUFFERDESC);
dsbd.dwFlags = DSBCAPS_CTRL3D | DSBCAPS_PRIMARYBUFFER;
if SUCCEEDED(lpds->CreateSoundBuffer(&dsbd, &lpdsbPrimary, NULL))
{
    // Get listener interface
    if FAILED(lpdsbPrimary->QueryInterface(IID_IDirectSound3DListener,
            (LPVOID *)&lp3DListener))
    {
    lpdsbPrimary->Release();
    }
}


Batch Parameters for IDirectSound3DListener

Applications can retrieve or set a 3-D listener object's parameters individually or in batches. To set individual values, your application can use the applicable IDirectSound3DListener interface method. However, applications often must set or retrieve all the values that describe the listener at once. An application can perform these batch parameter manipulations in a single call by using the IDirectSound3DListener::GetAllParameters and IDirectSound3DListener::SetAllParameters methods.


Deferred Settings

Every change to 3-D sound buffer and listener settings causes DirectSound to remix, at the expense of CPU cycles. To minimize the performance impact of changing 3-D settings, use the DS3D_DEFERRED flag in the dwApply parameter of any of the IDirectSound3DListener or IDirectSound3DBuffer methods that change 3-D settings. Then call the IDirectSound3DListener::CommitDeferredSettings method to execute all of the deferred commands at once.

Note Any deferred settings are overwritten if your application calls the same setting method with the DS3D_IMMEDIATE flag before it calls CommitDeferredSettings. For example, if you set the listener velocity to (1.0, 0.0, 0.0) with the DS3D_DEFERRED flag and then set it to (2.0, 0.0, 0.0) with the DS3D_IMMEDIATE flag, the velocity will be (2.0, 0.0, 0.0). Then, if your application calls the CommitDeferredSettings method, the velocity will not change.


Distance Factor

DirectSound uses meters as the default unit of distance measurements. If your application does not use meters, it can set a distance factor, which is the number of meters in a vector unit.

After you have set the distance factor for a listener, use your application's own distance units in calls to any methods that apply to that listener. Suppose, for example, that the basic unit of measurement in your application is the foot. You call the IDirectSound3DListener::SetDistanceFactor method, specifying 0.3048 as the flDistanceFactor parameter. (This value is the number of meters in a foot.) From then on, you continue using feet in parameters to method calls, and they are automatically converted to meters.

You can retrieve the current distance factor set for a listener by using the IDirectSound3DListener::GetDistanceFactor method.

The distance factor mainly affects Doppler shift (by changing the actual velocity represented by n units per second). It does not directly affect rolloff, because the rate of attenuation over distance is based on the minimum distance in units. If you set the minimum distance for a given sound at 2 units, the volume will be halved at a distance of 4 units, whether those units are in feet, meters, or any other measure. For more information, see Minimum and Maximum Distances.


Listener Orientation

Listener orientation is defined by the relationship between two vectors that share an origin at the center of the listener's head: the top and front vectors. The top vector points straight up through the top of the head, and the front vector points forward through the listener's face at right angles to the top vector, as in the following illustration.

An application can set and retrieve the listener's orientation by using the IDirectSound3DListener::SetOrientation and IDirectSound3DListener::GetOrientation methods. By default, the front vector is (0, 0, 1.0), and the top vector is (0, 1.0, 0).

The two vectors must always be at right angles to one another. If necessary, DirectSound will adjust the front vector so that it is at right angles to the top vector.


Listener Position and Velocity

An application can set and retrieve a listener's position in 3-D space by using the IDirectSound3DListener::SetPosition and IDirectSound3DListener::GetPosition methods.

To set or retrieve the velocity value that DirectSound uses to calculate Doppler-shift effects for a listener, use the IDirectSound3DListener::SetVelocity and IDirectSound3DListener::GetVelocity methods. Velocity is measured in distance units per second—by default, meters per second.

As with buffers, a listener's position and its velocity are completely independent. It is entirely up to the application to set an appropriate velocity for the listener.


Doppler Factor

DirectSound automatically creates Doppler shift effects for any buffer or listener that has a velocity. Effects are cumulative: if the listener and the sound buffer are both moving, the system automatically calculates the relative velocity and adjusts the Doppler effect accordingly.

In order to have realistic Doppler shift effects in your application, you must calculate the speed of any object that is moving and set the appropriate velocity for that sound source or listener. You are free to exaggerate or lessen this value in a particular case in order to create special effects. You can also globally increase or decrease Doppler shift by changing the Doppler factor.

The Doppler factor can range from DS3D_MINDOPPLERFACTOR to DS3D_MAXDOPPLERFACTOR, currently defined in Dsound.h as 0.0 and 10.0 respectively. A value of 0 means no Doppler shift is applied to a sound. Every other value represents a multiple of the real-world Doppler shift. In other words, a value of 1 (or DS3D_DEFAULTDOPPLERFACTOR) means the Doppler shift that would be experienced in the real world is applied to the sound; a value of 2 means twice the real-world Doppler shift; and so on.

The Doppler factor can be set and retrieved by using the IDirectSound3DListener::SetDopplerFactor and IDirectSound3DListener::GetDopplerFactor methods.


Rolloff Factor

Rolloff is the amount of attenuation that is applied to sounds, based on the listener's distance from the sound source. DirectSound can ignore rolloff, exaggerate it, or give it the same effect as in the real world, depending on a variable called the rolloff factor.

The rolloff factor can range from DS3D_MINROLLOFFFACTOR to DS3D_MAXROLLOFFFACTOR, currently defined in Dsound.h as 0.0 and 10.0 respectively. A value of DS3D_MINROLLOFFFACTOR means no rolloff is applied to a sound. Every other value represents a multiple of the real-world rolloff. In other words, a value of 1 (DS3D_DEFAULTROLLOFFFACTOR) means the rolloff that would be experienced in the real world is applied to the sound; a value of 2 means twice the real-world rolloff, and so on.

You set and retrieve the rolloff factor by using the IDirectSound3DListener::SetRolloffFactor and IDirectSound3DListener::GetRolloffFactor methods.

To change the rolloff for an individual sound buffer, you can set the minimum distance for the buffer. For more information, see Minimum and Maximum Distances.


DirectSoundCapture

DirectSoundCapture provides an interface for capturing digital audio data from an input source. To use it you must create an instance of the IDirectSoundCapture interface, then use its methods to create a single capture buffer. The actual capturing is done with the methods of the buffer object.

This section covers the following topics:

  • Enumeration of Capture Devices
  • Creating the DirectSoundCapture Object
  • Capture Device Capabilities
  • Creating a Capture Buffer
  • Capture Buffer Information
  • Capture Buffer Notification
  • Capturing Sounds


Enumeration of Capture Devices

For an application that is simply going to capture sounds through the user's preferred capture device, you don't need to enumerate the available devices. When you create the DirectSoundCapture object with NULL as the device identifier, the interface will automatically be associated with the default device if one is present. (If no device driver is present, the call to the DirectSoundCaptureCreate function fails.)

However, if you are looking for a particular kind of device or wish to offer the user a choice of devices, you must enumerate the devices available on the system.

Enumeration serves three purposes:

  • Reports what hardware is available
  • Supplies a GUID for each device
  • Allows you to initialize DirectSoundCapture for each device as it is enumerated, so that you can check the capabilities of the device

To enumerate devices you must first set up a callback function that will be called each time DirectSound finds a device. You can do anything you want within this function, and you can give it any name, but you must declare it in the same form as DSEnumCallback, a prototype in this documentation. The callback function must return TRUE if enumeration is to continue, or FALSE otherwise (for instance, after finding a device with the capabilities you need).

For a sample callback function, see Enumeration of Sound Devices. Note that a GUID for each device is obtained as one of the parameters to this function.

The enumeration is set in motion by using the DirectSoundCaptureEnumerate function:

DWORD pv;  // Any 32-bit value.

HRESULT hr = DirectSoundCaptureEnumerate(
        (LPDSENUMCALLBACK)DSEnumProc,
        &pv)


Creating the DirectSoundCapture Object

You create the DirectSoundCapture object by calling the DirectSoundCaptureCreate function, which returns a pointer to an IDirectSoundCapture COM interface.

The lpGUID parameter to DirectSoundCaptureCreate can be a GUID obtained by enumeration, or it can be NULL for the preferred capture device. In most cases you will pass NULL.

You can also use the CoCreateInstance function to create the object. The procedure is similar to that for the DirectSound object; see Creating the DirectSound Object. If you use CoCreateInstance, then the object is created for the default capture device selected by the user on the multimedia control panel.

If you want DirectSound and DirectSoundCapture objects to coexist, then you should create and initialize the DirectSound object before creating and initializing the DirectSoundCapture object.

Some audio devices aren't configured for full duplex audio by default. If you have problems with creating and initializing both a DirectSound object and a DirectSoundCapture object, you should check your audio device to ensure that two DMA channels are enabled.


Capture Device Capabilities

To retrieve the capabilities of a capture device, call the IDirectSoundCapture::GetCaps method. The parameter to this method is a pointer to the DSCCAPS structure. As with other such structures, you have to initialize the dwSize member before passing it.

On return, the structure contains the number of channels the device supports as well as a combination of values for supported formats, equivalent to the values in the WAVEINCAPS structure used in the Win32 waveform audio functions.


Creating a Capture Buffer

You create a capture buffer by calling the IDirectSoundCapture::CreateCaptureBuffer method of the DirectSoundCapture object.

One of the parameters to the method is a DSCBUFFERDESC structure that describes the characteristics of the desired buffer. The last member of this structure is a WAVEFORMATEX structure, which must be initialized with the details of the desired wave format. For more information on this structure, see Sound Data.

Note that if your application is using DirectSound as well as DirectSoundCapture, capture buffer creation can fail when the format of the capture buffer is not the same as that of the primary buffer. The reason is that some cards have only a single clock and cannot support capture and playback at two different frequencies.

The following example sets up a capture buffer that will hold 1 second of data:

/* In this example it is assumed that pDSC is a valid pointer to
   a DirectSoundCapture object. */

DSCBUFFERDESC              dscbd;
LPDIRECTSOUNDCAPTUREBUFFER pDSCB;
WAVEFORMATEX               wfx =
    {WAVE_FORMAT_PCM, 2, 44100, 176400, 4, 16, 0};
    // wFormatTag, nChannels, nSamplesPerSec, mAvgBytesPerSec,
    // nBlockAlign, wBitsPerSample, cbSize
dscbd.dwSize = sizeof(DSCBUFFERDESC);
dscbd.dwFlags = 0;
dscbd.dwBufferBytes = wfx.nAvgBytesPerSec;
dscbd.dwReserved = 0;
dscbd.lpwfxFormat = &wfx;

pDSCB = NULL;

HRESULT hr = pDSC->CreateCaptureBuffer(&dscbd,
        &pDSCB, NULL);


Capture Buffer Information

Use the IDirectSoundCaptureBuffer::GetCaps method to retrieve the size of a capture buffer. Be sure to initialize the dwSize member of the DSCBCAPS structure before passing it as a parameter. You can also retrieve information about the format of the data in the buffer, as set when the buffer was created. Call the IDirectSoundCaptureBuffer::GetFormat method, which returns the format information in a WAVEFORMATEX structure. For more information on this structure, see Sound Data.

Note that your application can allow for extra format information in the WAVEFORMATEX structure by first calling the GetFormat method with NULL as the lpwfxFormat parameter. In this case the DWORD pointed to by the lpdwSizeWritten parameter will receive the size of the structure needed to receive complete format information.

To find out what a capture buffer is currently doing, call the IDirectSoundCaptureBuffer::GetStatus method. This method fills a DWORD variable with a combination of flags that indicate whether the buffer is busy capturing, and if so, whether it is looping; that is, whether the DSCBSTART_LOOPING flag was set in the last call to IDirectSoundCaptureBuffer::Start.

Finally, the IDirectSoundCaptureBuffer::GetCurrentPosition method returns the current read and capture positions within the buffer. The read position is the end of the data that has been captured into the buffer at this point. The capture position is the end of the block of data that is currently being copied from the hardware. You can safely copy data from the buffer only up to the read position.


Capture Buffer Notification

You may want your application to be notified when the current read position reaches a certain point in the buffer, or when it reaches the end. The current read position is the point up to which it is safe to read data from the buffer. With the IDirectSoundNotify::SetNotificationPositions method you can set any number of points within the buffer where events are to be signaled.

First you have to obtain a pointer to the IDirectSoundNotify interface. You can do this with the capture buffer's QueryInterface method, as shown in the example under Play Buffer Notification.

Next create an event object with the Win32 CreateEvent function. You put the handle to this event in the hEventNotify member of a DSBPOSITIONNOTIFY structure, and in the dwOffset member of that structure you specify the offset within the buffer where you want the event to be signaled. Then you pass the address of the structure — or array of structures, if you want to set more than one notification position — to the IDirectSoundNotify::SetNotificationPositions method.

The following example sets up three notification positions in a one-second buffer. One event will be signaled when the read position nears the halfway point in the buffer, another will be signaled when it nears the end of the buffer, and the third will be signaled when capture stops.

#define cEvents  3

/* In this example it is assumed that the following variables have
   been properly initialized, and that wfx was included in the buffer
   description when the buffer was created.

   LPDIRECTSOUNDNOTIFY  lpDsNotify;
   WAVEFORMATEX          wfx;
*/

HANDLE             rghEvent[cEvents] = {0};
DSBPOSITIONNOTIFY  rgdsbpn[cEvents];
HRESULT            hr;
int                i;

// Create the events
for (i = 0; i < cEvents; ++i)
{
    rghEvent[i] = CreateEvent(NULL, TRUE, FALSE, NULL);
    if (NULL == rghEvent[i])
    {
        hr = GetLastError();
        goto Error;
    }
}

// Describe notifications.

rgdsbpn[0].dwOffset = (wfx.nAvgBytesPerSec/2) -1;
rgdsbpn[0].hEventNotify = rghEvent[0];

rgdsbpn[1].dwOffset = wfx.nAvgBytesPerSec - 1;
rgdsbpn[1].hEventNotify = rghEvent[1];

rgdsbpn[2].dwOffset = DSBPN_OFFSETSTOP;
rgdsbpn[2].hEventNotify = rghEvent[2];

// Create notifications.

hr = lpDsNotify->SetNotificationPositions(cEvents, rgdsbpn);


Capturing Sounds

Capturing a sound consists of the following steps:

  1. Start the buffer by calling the IDirectSoundCaptureBuffer::Start method. Audio data from the input device begins filling the buffer from the beginning.
  2. Wait until the desired amount of data is available. For one method of determining when the capture position reaches a certain point, see Capture Buffer Notification.
  3. When sufficient data is available, lock a portion of the capture buffer by calling the IDirectSoundCaptureBuffer::Lock method.

    To make sure you are not attempting to lock a portion of memory that is about to be used for capture, you can first obtain the current read position by calling IDirectSoundCaptureBuffer::GetCurrentPosition. For an explanation of the read position, see Capture Buffer Information.

    As parameters to the Lock method, you pass the size and offset of the block of memory you want to read. The method returns a pointer to the address where the memory block begins, and the size of the block. If the block wraps around from the end of the buffer to the beginning, two pointers are returned, one for each section of the block. The second pointer is NULL if the locked portion of the buffer does not wrap around.

  4. Copy the data from the buffer, using the addresses and block sizes returned by the Lock method.
  5. Unlock the buffer with the IDirectSoundCaptureBuffer::Unlock method.
  6. Repeat steps 2 to 5 until you are ready to stop capturing data. Then call the IDirectSoundCaptureBuffer::Stop method.

Normally the buffer stops capturing automatically when the capture position reaches the end of the buffer. However, if the DSCBSTART_LOOPING flag was set in the dwFlags parameter to the IDirectSoundCaptureBuffer::Start method, the capture will continue until the application calls the IDirectSoundCaptureBuffer::Stop method.


DirectSound Property Sets

Through the IKsPropertySet interface, DirectSound is able to support extended services offered by sound cards and their associated drivers.

Properties are arranged in sets. A GUID identifies a set, and a ULONG identifies a particular property within the set. For example, a hardware vendor might design a card capable of reverberation effects and define a property set DSPROPSETID_ReverbProps containing properties such as DSPROPERTY_REVERBPROPS_HALL and DSPROPERTY_REVERBPROPS_STADIUM.

Typically, the property identifiers are defined using a C language enumeration starting at ordinal zero.

Individual properties may also have associated parameters. The IKsPropertySet interface specification intentionally leaves these parameters undefined, allowing the designer of the property set to use them in a way most beneficial to the properties within the set being designed. The precise meaning of the parameters is defined with the definition of the properties.

To make use of extended properties on sound cards, you must first determine whether the driver supports the IKsPropertySet interface, and obtain a pointer to the interface if it is supported. You can do this by calling the QueryInterface method of an existing interface on a DirectSound3DBuffer object.

HRESULT hr = lpDirectSound3DBuffer->QueryInterface(
        IID_IKsPropertySet,
        (void**)&lpKsPropertySet));

In the example, lpDirectSound3DBuffer is a pointer to the buffer's interface and lpKsPropertySet receives the address of the IKsPropertySet interface if one is found. IID_IKsPropertySet is a GUID defined in Dsound.h.

The call will succeed only if the buffer is hardware-accelerated and the underlying driver supports property sets. If it does succeed, you can now look for a particular property using the IKsPropertySet::QuerySupport method. The value of the PropertySetId parameter is a GUID defined by the hardware vendor.

Once you've determined that support for a particular property exists, you can change the state of the property by using the IKsPropertySet::Set method and determine its present state by using the IKsPropertySet::Get method. The state of the property is set or returned in the pPropertyData parameter.

Additional property parameters may also be passed to the object in a structure pointed to by the pPropertyParams parameter to the IKsPropertySet::Set method. The exact way in which this parameter is to be used is defined in the hardware vendor's specifications for the property set, but typically it would be used to define the instance of the property set. In practice, the pPropertyParams parameter is rarely used.

Let's take a somewhat whimsical example. Suppose a sound card has the ability to play a set of songs in the voices of several famous tenors. The driver developer creates a property set, DSPROPSETID_Song, containing properties like DSPROPERTY_SONG_IRISH_EYES and DSPROPERTY_SONG_O_SOLE_MIO. The property set applies to all of the tenors, and the driver developer has specified that pPropertyParams defines the tenor instance. Now you, the application developer, want to make Caruso sing one of the songs:

/* It is assumed that the hardware vendor has also defined
   CARUSO and START in a header file. */

DWORD dwTenor = CARUSO;
BOOL  StartOrStop = START;

HRESULT hr = lpKsPropertySet->Set(
        DSPROPSETID_Song,
        DSPROPERTY_SONG_IRISH_EYES,
        &dwTenor,
        sizeof(dwTenor),
        &StartOrStop,
        sizeof(StartOrStop));


Optimizing DirectSound Performance

This section offers some miscellaneous tips for improving the performance of DirectSound. The following topics are covered:

  • Matching Buffer Formats
  • Playing the Primary Buffer Continuously
  • Using Hardware Mixing
  • Minimizing Control Changes
  • CPU Considerations for 3-D Buffers


Matching Buffer Formats

The DirectSound mixer converts the data from each secondary buffer into the format of the primary buffer. This conversion is done on the fly as data is mixed into the primary buffer, and costs CPU cycles. You can eliminate this overhead by ensuring that your secondary buffers and primary buffer have the same format. Normally this means setting the primary buffer format to the format of the wave files used for data.

Because of the way DirectSound does format conversion, you only need to match the sample rate and number of channels. It doesn't matter if there is a difference in sample size (8-bit or 16-bit).


Playing the Primary Buffer Continuously

When there are no sounds playing, DirectSound stops the mixer engine and halts DMA (direct memory access) activity. If your application has frequent short intervals of silence, the overhead of starting and stopping the mixer each time a sound is played may be worse than the DMA overhead if you kept the mixer active. Also, some sound hardware or drivers may produce unwanted audible artifacts from frequent starting and stopping of playback. If your application is playing audio almost continuously with only short breaks of silence, you can force the mixer engine to remain active by calling the IDirectSoundBuffer::Play method for the primary buffer. The mixer will continue to run silently.

To resume the default behavior of stopping the mixer engine when there are no sounds playing, call the IDirectSoundBuffer::Stop method for the primary buffer.

For more information, see Access to the Primary Buffer


Using Hardware Mixing

Most sound cards support some level of hardware mixing if there is a DirectSound driver for the card. The following tips will allow you to make the most of hardware mixing:

  • Use static buffers for sounds that you want to be mixed in hardware. DirectSound will attempt to use hardware mixing on static buffers.
  • Create sound buffers first for the sounds you use the most. There is a limit to the number of buffers that can be mixed by hardware.
  • At run time, use the IDirectSound::GetCaps method to determine what formats are supported by the sound-accelerator hardware and use only those formats if possible.
  • To create a static buffer, specify the DSBCAPS_STATIC flag in the dwFlags member of the DSBUFFERDESC structure when you create a secondary buffer. You can also specify the DSBCAPS_LOCHARDWARE flag to force hardware mixing for a buffer, however, if you do this and resources for hardware mixing are not available, the IDirectSound::CreateSoundBuffer method will fail.


Minimizing Control Changes

Performance is affected when you change the pan, volume, or frequency on a secondary buffer. To prevent interruptions in sound output, the DirectSound mixer must mix ahead from 20 to 100 or more milliseconds. Whenever you make a control change, the mixer has to flush its mix-ahead buffer and remix with the changed sound.

It's a good idea to minimize the number of control changes you send. Try reducing the frequency of calls to routines that use the IDirectSoundBuffer::SetVolume, IDirectSoundBuffer::SetPan, and IDirectSoundBuffer::SetFrequency methods. For example, if you have a routine that moves a sound from the left to the right speaker in synchronization with animation frames, try calling the SetPan method only every second or third frame.

Note 3-D control changes (orientation, position, velocity, Doppler factor, and so on) also cause DirectSound to remix its mix-ahead buffer. However, you can group a number of 3-D control changes together and cause only a single remix. See Deferred Settings.


CPU Considerations for 3-D Buffers

Software-emulated 3-D buffers are computationally expensive. For example, each buffer can consume about 6 percent of the processing time of a Pentium 90. You should take this into consideration when deciding when and how to use 3-D buffers in your applications.

Use as few 3-D sounds as you can, and don't use 3-D on sounds that won't really benefit from the effect. Design your application so that it's easy to enable and disable 3-D effects on each sound. You can call the IDirectSound3DBuffer::SetMode method with the DS3DMODE_DISABLE flag to disable 3-D processing on any 3-D sound buffer.

DirectSound provides a means for hardware manufacturers to provide acceleration of 3-D audio buffers. On these audio cards the host CPU consumption will not be a consideration.


Using Wave Files

The DirectSound and DirectSoundCapture APIs do not include methods for handling wave files. However, the source code for several of the sample applications includes a handy file, Wave.c, which contains functions for opening and creating a wave file, reading and writing the file headers, and streaming data to or from the file.

Wave files are in the Resource Interchange File Format (RIFF), which consists of a variable number of "chunks" containing either header information (for example, the wave format of sound samples) or data (the samples themselves). The Win32 API supplies functions for opening and closing RIFF files, seeking chunks, and so on. These functions, whose names all start with "mmio," are used by the wrapper functions in the Wave.c file.

More information about using the wrapper functions is given in the following two topics:

  • Reading from a Wave File
  • Writing to a Wave File


Reading from a Wave File

In order to use the wrapper functions in Wave.c, you must declare the following four variables:

WAVEFORMATEX  *pwfx;          // Wave format info
HMMIO         hmmio;          // File handle
MMCKINFO      mmckinfoData;   // Chunk info
MMCKINFO      mmckinfoParent; // Parent chunk info

The first step in reading a wave file is to call the WaveOpenFile function. This gets a handle to the file, verifies that it is in RIFF format, and gets information about the wave format. The parameters are the filename and the addresses of three of the variables you have declared:

if (WaveOpenFile(lpzFileName, &hmmio, &pwfx, &mmckinfoParent) != 0)
{
    // Failure
}

Note that the wrapper functions all return zero if successful.

The next step is to call the WaveStartDataRead function, causing the file pointer to descend to the data chunk. This function also fills in the MMCKINFO structure for the data chunk, so that you know how much data is available:

if (WaveStartDataRead(&hmmio, &mmckinfoData, &mmckinfoParent) != 0)
    {
    // Failure
    }

The application can now begin copying data from the file to a secondary sound buffer. Normally you don't create the sound buffer until you have obtained the size of the data chunk and the format of the wave. The following code creates a static buffer just large enough to hold all the data in the file.

/* It is assumed that lpds in a valid pointer
   to the DirectSound object. */

LPDIRECTSOUNDBUFFER  lpdsbStatic;
DSBUFFERDESC         dsbdesc;

memset(&dsbdesc, 0, sizeof(DSBUFFERDESC));
dsbdesc.dwSize = sizeof(DSBUFFERDESC);
dsbdesc.dwFlags = DSBCAPS_STATIC;
dsbdesc.dwBufferBytes = mmckinfoData.cksize;
dsbdesc.lpwfxFormat = pwfx;

if FAILED(lpds->CreateSoundBuffer(&dsbdesc, &lpdsbStatic, NULL))
{
    WaveCloseReadFile(&hmmio, &pwfx);
    return FALSE;
}

Because in this case the application is not streaming the data but simply filling a static buffer, the entire buffer is locked from the beginning. There is no wraparound, so only a single pointer and byte count are required.

LPVOID lpvAudio1;
DWORD  dwBytes1;

if FAILED(lpdsbStatic->Lock(
        0,              // Offset of lock start
        0,              // Size of lock; ignored in this case
        &lpvAudio1,     // Address of lock start
        &dwBytes1,      // Number of bytes locked
        NULL,           // Wraparound start; not used
        NULL,           // Wraparound size; not used
        DSBLOCK_ENTIREBUFFER))  // Flag
{
    // Error handling
    WaveCloseReadFile(&hmmio, &pwfx);
    .
    .
    .
}

The WaveReadFile function in Wave.c copies the data from the file to the buffer pointer and returns zero if successful.

UINT cbBytesRead;

if (WaveReadFile(
        hmmio,              // file handle
        dwBytes1,           // no. of bytes to read
        (BYTE *) lpvAudio1, // destination
        &mmckinfoData,      // file chunk info
        &cbBytesRead))      // actual no. of bytes read
{
    // Handle failure on non-zero return
    WaveCloseReadFile(&hmmio, &pwfx);
    .
    .
    .
}

Finally, the application unlocks the buffer and closes the wave file:

lpdsbStatic->Unlock(lpvAudio1, dwBytes1, NULL, 0);
WaveCloseReadFile(&hmmio, &pwfx);

For a streaming buffer, you would typically call WaveReadFile at regular intervals determined by the current play position. (See Play Buffer Notification.) If the locked portion of the buffer wrapped around, of course, you would call WaveReadFile once for each segment of the lock.


Writing to a Wave File

To prepare for writing to a wave file, the application must first declare four variables to be passed to the functions in Wave.c:

WAVEFORMATEX  wfx;            // Wave format info
HMMIO         hmmio;          // File handle
MMCKINFO      mmckinfoData;   // Chunk info
MMCKINFO      mmckinfoParent; // Parent chunk (file) info

You must also initialize the WAVEFORMATEX structure with the format of the capture buffer.

Now you call the WaveCreateFile function, passing in the desired filename and the addresses of the global variables. The function creates the file and writes some header information. Like other functions in Wave.c, WaveCreateFile returns zero if successful.

if (WaveCreateFile(pszFileName, &hmmio, &wfx,
        &mmckinfoData, &mmckinfoParent))
{
    // Failure
}

Next, call the WaveStartDataWrite function, which initializes the data chunk.

if (WaveStartDataWrite(&hmmio, &mmckinfoData, &mmioinfo))
{
     // Failure
}

The file is now ready to receive data. The following fragment illustrates how data might be copied from a capture buffer to a file.

/* It is assumed that the following variables contain
   valid assignments:
LPDIRECTSOUNDCAPTUREBUFFER lpdscb;    // Capture buffer
DSCBUFFERDESC    dscbDesc;            // Capture buffer description
DWORD            dwReadCursor;        // Internal cursor in buffer
DWORD            dwNumBytes;          // Bytes available
DWORD            dwTotalBytesWritten; // Running total in file
*/

LPBYTE pbInput1, pbInput2; // Pointers to data in buffer
DWORD  cbInput1, cbInput2; // Count of bytes in locked portion
UINT   BytesWritten;       // Count of bytes written to file

if FAILED(hr = lpdscb->Lock(dwReadCursor, dwNumBytes,
                      (LPVOID *)&pbInput1, &cbInput1,
                      (LPVOID *)&pbInput2, &cbInput2, 0))
{
    // Failure
}
else
{
    if (WaveWriteFile(hmmio, cbInput1, pbInput1, &mmckinfoData,
                    &dwBytesWritten, &mmioinfo))
    {
        // Failure
    }
    else dwTotalBytesWritten += BytesWritten;
    if (pbInput2 != NULL)
    {
        if (WaveWriteFile(hmmio, cbInput2, pbInput2, &mmckinfoData,
                    &BytesWritten, &mmioinfo))
        {
            // Failure
        }
        else dwTotalBytesWritten += BytesWritten;

    }
    lpdscb->Unlock(pbInput1, cbInput1, pbInput2, cbInput2);

    // Increment internal cursor, compensating for wrap around
    dwReadCursor += dwNumBytes;
    while (dwReadCursor >= dscbDesc.dwBufferBytes)
                dwMyReadCursor -= dscbDesc.dwBufferBytes;

}

When you are finished capturing data, you close the file:

WaveCloseWriteFile(&hmmio, &mmckinfoData,
        &mmckinfoParent, &mmioinfo,
        dwTotalBytesWritten / (wfx.wBitsPerSample / 8));

The WaveCloseWriteFile function calculates the total number of samples in the file and writes this number to the data chunk header.


Reading Wave Data from a Resource

The DirectSound API does not include methods for reading a wave from a resource. However, there are helper functions in Dsutil3d.c, which you will find with the source code for the DS3DView Sample.

To store wave sounds in an executable or DLL, import your wave files as resources and give them string names. Note that Dsutil3d.c expects these resources to be of type "WAV." If you are using Microsoft® Visual C++®, imported wave files are turned into resources of type "WAVE." You must either change this nomenclature to "WAV" by editing the resource file, or else modify the assignment of c_szWAV in Dsutil3d.c so that the FindResource function is looking for "WAVE" resources.

You may also want to modify Dsutil3d.c so that the DSLoadSoundBuffer function sets only the appropriate control flags.

To create a static buffer and load the sound into it, simply pass the IDirectSound interface pointer and the name of the resource to the DSLoadSoundBuffer function. If successful, the function returns a pointer to the buffer. Here's a sample call, where lpds is the pointer to the IDirectSound interface:

#include "dsutil.h"

LPDIRECTSOUNDBUFFER  lpdsbFootstep;

lpdsbFootstep = DSLoadSoundBuffer(lpds, "FOOTSTEP");
if (lpdsbFootstep == NULL)
{
    // Failure
}


DirectSound Tutorials

This section contains tutorials that provide step-by-step instructions for implementing basic DirectSound functionality.

  • Tutorial 1: Sound Playback

    The first tutorial shows how to set up the DirectSound system, create a secondary buffer, and play data from a wave file.

  • Tutorial 2: Sound Capture

    The second tutorial shows how to create a DirectSoundCapture object and a capture buffer, and how to write data to a wave file.


Tutorial 1: Sound Playback

This tutorial shows how to create a simple DirectSound application that will play a wave file of any size.

The functions for opening, reading, and closing wave files are in Wave.c, a module that is found with the DSShow3D sample application in the DirectX SDK. In order to implement the techniques shown in the tutorial, you must add Wave.c and Wave.h to your project and link to Winmm.lib. You must also add Debug.c and Debug.h from the same sample directory, or else edit the calls to the ASSERT macro in Wave.c to call the standard assert function.

The method calls in this tutorial are made through the macros defined in Dsound.h, which are valid for both C and C++.

The tutorial is broken down into the following steps:

  • Step 1: Setting Up DirectSound
  • Step 2: Opening the Wave File
  • Step 3: Creating the Secondary Buffer
  • Step 4: Setting Up Play Notification
  • Step 5: Handling the Play Notifications
  • Step 6: Streaming Data from the Wave File
  • Step 7: Shutting Down DirectSound


Step 1: Setting Up DirectSound

The tutorial requires the following definitions and global variables:

#define NUMEVENTS 2

LPDIRECTSOUND               lpds;
DSBUFFERDESC                dsbdesc;
LPDIRECTSOUNDBUFFER         lpdsb;
LPDIRECTSOUNDBUFFER         lpdsbPrimary;
LPDIRECTSOUNDNOTIFY         lpdsNotify;
WAVEFORMATEX                *pwfx;
HMMIO                       hmmio;
MMCKINFO                    mmckinfoData, mmckinfoParent;
DSBPOSITIONNOTIFY           rgdsbpn[NUMEVENTS];
HANDLE                      rghEvent[NUMEVENTS];

The first step is to create the DirectSound object, establish a cooperative level, and set the primary buffer format. All this is done in the InitDSound function shown in the following code.

The function takes two parameters: the main window handle and a pointer to the GUID of the sound device. In most cases you will pass NULL as the second parameter, indicating the default device, but you may obtain a GUID by device enumeration.

BOOL InitDSound(HWND hwnd, GUID *pguid)
{
   // Create DirectSound

    if FAILED(DirectSoundCreate(pguid, &lpds, NULL))
        return FALSE;

    // Set co-op level

    if FAILED(IDirectSound_SetCooperativeLevel(
            lpds, hwnd, DSSCL_PRIORITY))
        return FALSE;

You have set the priority cooperative level in order to be able to set the format of the primary buffer. If you don't change the default format, output will be in the 8-bit, 22 kHz format regardless of the format of the input. Setting the primary buffer to a higher format can do no harm, because even if the secondary buffers are in a lower format, the samples will be converted automatically by DirectSound. Note also that there's no danger of the call to IDirectSoundBuffer::SetFormat failing because the hardware doesn't support the higher format. DirectSound will simply set the closest available format.

To set the format of the primary buffer, you first describe it in the global DSBUFFERDESC structure, then pass this description to the IDirectSound::CreateSoundBuffer method.

    // Obtain primary buffer

    ZeroMemory(&dsbdesc, sizeof(DSBUFFERDESC));
    dsbdesc.dwSize = sizeof(DSBUFFERDESC);
    dsbdesc.dwFlags = DSBCAPS_PRIMARYBUFFER;
    if FAILED(lpds->CreateSoundBuffer(&dsbdesc, &lpdsbPrimary, NULL))
        return FALSE;

Once you have a primary buffer object, you describe the desired wave format and pass the description to the IDirectSoundBuffer::SetFormat method:

    // Set primary buffer format

    WAVEFORMATEX wfx;
    memset(&wfx, 0, sizeof(WAVEFORMATEX));
    wfx.wFormatTag = WAVE_FORMAT_PCM;
    wfx.nChannels = 2;
    wfx.nSamplesPerSec = 44100;
    wfx.wBitsPerSample = 16;
    wfx.nBlockAlign = wfx.wBitsPerSample / 8 * wfx.nChannels;
    wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;

    hr = lpdsbPrimary->SetFormat(&wfx);

    return TRUE;
}  // InitDSound()


Step 2: Opening the Wave File

The sample program is a general-purpose wave-file reader that does not expect sound data in a particular format. That being the case, it's necessary to put off creating the secondary sound buffer until the format of the data is known.

The steps in opening the file and creating the secondary buffer are grouped in the SetupStreamBuffer function. This function first performs any necessary cleanup from the last time a sound was played:

BOOL SetupStreamBuffer(LPSTR lpzFileName)
{
    // Close any open file and release interfaces

    WaveCloseReadFile(&hmmio, &pwfx);  // Function in Wave.c

    if (lpdsNotify != NULL)
    {
        lpdsNotify->Release();
        lpdsNotify = NULL;
    }

    if (lpdsb != NULL)
    {
        lpdsb->Release();
        lpdsb = NULL;
    }

The function now opens a wave file, gets the format, and advances the file pointer to the beginning of the sound data. It does this by using two functions in Wave.c.

    if (WaveOpenFile(lpzFileName, &hmmio, &pwfx,
            &mmckinfoParent) != 0)
        return FALSE;
    if (WaveStartDataRead(&hmmio, &mmckinfoData,
            &mmckinfoParent) != 0)
        return FALSE;

The WaveOpenFile function initializes three of the global variables declared at the beginning of the tutorial: a file handle, a pointer to a WAVEFORMATEX structure, and the MMCKINFO structure for the parent chunk (that is, information about the file as a whole).

The file handle and chunk information are then passed to the WaveStartDataRead function, which returns information about the data chunk in mmckinfoData. You would be interested in this structure if you were creating a static buffer just big enough to accommodate all the data bytes. In this tutorial, though, you're creating a streaming buffer, so you don't need to know the size of the data chunk.


Step 3: Creating the Secondary Buffer

Still inside the SetupStreamBuffer function, you now create a secondary sound buffer in the same format as the wave file. The process is similar for that you used in Step 1 to create a primary buffer. First you describe the buffer in the global DSBUFFERDESC structure, then you pass this description to the IDirectSound::CreateSoundBuffer method.

    memset(&dsbdesc, 0, sizeof(DSBUFFERDESC));
    dsbdesc.dwSize = sizeof(DSBUFFERDESC);
    dsbdesc.dwFlags =
            DSBCAPS_GETCURRENTPOSITION2   // Always a good idea
            | DSBCAPS_GLOBALFOCUS         // Allows background playing
            | DSBCAPS_CTRLPOSITIONNOTIFY; // Needed for notification

    // The size of the buffer is arbitrary, but should be at least
    // two seconds, to keep data writes well ahead of the play
    // position.

    dsbdesc.dwBufferBytes = pwfx->nAvgBytesPerSec * 2;
    dsbdesc.lpwfxFormat = pwfx;

    if FAILED(IDirectSound_CreateSoundBuffer(
            lpds, &dsbdesc, &lpdsb, NULL))
    {
        WaveCloseReadFile(&hmmio, &pwfx);
        return FALSE;
    }


Step 4: Setting Up Play Notification

Now that you've successfully created a streaming buffer, you ask to be notified whenever the current play position reaches certain points in the buffer, so you'll know when it's time to stream more data. In the example, those positions will be set at the beginning and halfway mark of the buffer.

First you create the required number of events and store their handles in the rghEvent array:

    for (int i = 0; i < NUMEVENTS; i++)
    {
        rghEvent[i] = CreateEvent(NULL, FALSE, FALSE, NULL);
        if (NULL == rghEvent[i]) return FALSE;
    }

Next, you initialize the array of DSBPOSITIONNOTIFY structures, each of which associates a position in the buffer with an event handle:

    rgdsbpn[0].dwOffset = 0;
    rgdsbpn[0].hEventNotify = rghEvent[0];
    rgdsbpn[1].dwOffset = (dsbdesc.dwBufferBytes/2);
    rgdsbpn[1].hEventNotify = rghEvent[1];

Then you get the IDirectSoundNotify interface from the secondary buffer and pass the DSBPOSITIONNOTIFY array to the SetNotificationPositions method:

    if FAILED(IDirectSoundBuffer_QueryInterface(lpdsb,
            IID_IDirectSoundNotify, (VOID **)&lpdsNotify))
        return FALSE;

    if FAILED(IDirectSoundNotify_SetNotificationPositions(
             lpdsNotify, NUMEVENTS, rgdsbpn))
    {
        IDirectSoundNotify_Release(lpdsNotify);
        return FALSE;
    }

That completes the setup of the streaming buffer. Because you've already opened the wave file and are ready to start streaming data, you can set the buffer in motion here. You want it to continue running till the complete sound has been played, so you set the DSBPLAY_LOOPING flag.

    IDirectSoundBuffer_Play(lpdsb, 0, 0, DSBPLAY_LOOPING);

    return TRUE;
} // end of SetupStreamBuffer()


Step 5: Handling the Play Notifications

Notifications are received in the form of signaled events in the message loop within the WinMain function. The following fragment illustrates how the loop might be written in order to intercept signaled events as well as standard messages:

BOOL Done = FALSE;
while (!Done)
{
    DWORD dwEvt = MsgWaitForMultipleObjects(
            NUMEVENTS,      // How many possible events
            rghEvent,       // Location of handles
            FALSE,          // Wait for all?
            INFINITE,       // How long to wait
            QS_ALLINPUT);   // Any message is an event

    // WAIT_OBJECT_0 == 0 but is properly treated as an arbitrary
    // index value assigned to the first event, therefore we subtract
    // it from dwEvt to get the zero-based index of the event.

    dwEvt -= WAIT_OBJECT_0;

    // If the event was set by the buffer, there's input
    // to process.

    if (dwEvt < NUMEVENTS)
    {
        StreamToBuffer(dwEvt); // copy data to output stream
    }

    // If it's the last event, it's a message

    else if (dwEvt == NUMEVENTS)
    {
        while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
        {
            if (msg.message == WM_QUIT)
            {
                Done = TRUE;
            }
            else
            {
                TranslateMessage(&msg);
                DispatchMessage(&msg);
            }
        }
    }  // end message processing
} // while (!Done)


Step 6: Streaming Data from the Wave File

The purpose of the notifications you set up and handled in the previous two steps is to alert you whenever half the data in the buffer has been played. As soon as the current play position passes the beginning or halfway point of the buffer, you write data into the segment of the buffer that has just been played. (When the buffer starts, you immediately receive a notification and write to the second half of the buffer.) Because the buffer holds 2 seconds' worth of data, your data write begins almost 1 second ahead of the current play position, which should allow ample time for the process to be completed before the play position reaches the new data.

In the WinMain function, whenever an event was signaled you passed the index of that event to the StreamToBuffer function. This index corresponds to the index of the notification position in the DSBPOSITIONNOTIFY array.

Here is the first part of the StreamToBuffer function:

BOOL StreamToBuffer(DWORD dwPos)
{
    LONG            lNumToWrite;
    DWORD           dwStartOfs;
    VOID            *lpvPtr1, *lpvPtr2;
    DWORD           dwBytes1, dwBytes2;
    UINT            cbBytesRead;
    static DWORD    dwStopNextTime = 0xFFFF;

    if (dwStopNextTime == dwPos)   // All data has been played
    {
        lpdsb->Stop();
        dwStopNextTime = 0xFFFF;
        return TRUE;
    }

    if (dwStopNextTime != 0xFFFF)  // No more to stream, but keep
                                 // playing to end of data
        return TRUE;

The dwStopNextTime variable is a flag to indicate that the end of the file has been reached; this is set later in the function. If it is nonzero, there is no more data to be streamed. If the value of dwStopNextTime equals the index of the notification being handled, then you know that the current play position has returned to where it was when the end of the file was reached; that is, the last segment of data you copied to the buffer has been played. In this case, it's time to stop the buffer so it doesn't keep playing old data.

The next part of the StreamToBuffer function determines the offset within the buffer where you will start copying the new data. Although the buffer in this tutorial has only two notification positions, the code is designed to work with any number. Remember, dwPos is the index of the notification position that has just been passed by the current play position. You are going to write to the segment of the buffer that starts at the previous notification position.

    if (dwPos == 0)
        dwStartOfs = rgdsbpn[NUMEVENTS - 1].dwOffset;
    else
        dwStartOfs = rgdsbpn[dwPos-1].dwOffset;

Now you determine the size of this segment of the buffer:

    lNumToWrite = (LONG) rgdsbpn[dwPos].dwOffset - dwStartOfs;
    if (lNumToWrite < 0) lNumToWrite += dsbdesc.dwBufferBytes;

You now have all the information you need to lock the buffer in preparation for the data write.

    IDirectSoundBuffer_Lock(lpdsb,
                     dwStartOfs,       // Offset of lock start
                     lNumToWrite,      // Number of bytes to lock
                     &lpvPtr1,         // Address of lock start
                     &dwBytes1,        // Count of bytes locked
                     &lpvPtr2,         // Address of wrap around
                     &dwBytes2,        // Count of wrap around bytes
                     0);               // Flags

In this example the lock will never wrap around, so you need to do only a single data copy from the file. You get the data by calling the WaveReadFile function in Wave.c:

    WaveReadFile(hmmio,                // File handle
                 dwBytes1,             // Number of bytes to get
                 (BYTE *) lpvPtr1,     // Destination
                 &mmckinfoData,        // File chunk info
                 &cbBytesRead);        // Actual bytes read

Now determine if the end of the file has been reached. If it has, close it, write silence to the rest of this segment (because it will play all the way through before the buffer is stopped), and set the dwStopNextTime flag.

    if (cbBytesRead < dwBytes1)        // Reached end of file
    {
        WaveCloseReadFile(&hmmio, &pwfx);
        FillMemory((PBYTE)lpvPtr1 + cbBytesRead,
                dwBytes1 - cbBytesRead,
                (dsbdesc.lpwfxFormat->wBitsPerSample==8) ? 128 : 0);
        dwStopNextTime = dwPos;
    }

Finally, unlock the buffer and return to the message loop:

    IDirectSoundBuffer_Unlock(lpdsb,
            lpvPtr1, dwBytes1, lpvPtr2, dwBytes2);

    return TRUE;
} // end StreamToBuffer()


Step 7: Shutting Down DirectSound

Before closing, your application needs to close any open wave file and release the DirectSoundNotify and DirectSound objects. Note that because you queried for the IDirectSoundNotify interface from a DirectSoundBuffer object, you must release the DirectSoundNotify object before releasing DirectSound. Releasing DirectSound automatically releases any existing buffers.

The following function does all the necessary cleanup:

void DSExit(void)
{
    WaveCloseReadFile(&hmmio, &pwfx);
    if (lpdsNotify)
        lpdsNotify->Release();
    if (lpds)
        lpds->Release();
}


Tutorial 2: Sound Capture

This tutorial shows how to implement DirectSoundCapture to capture a sound (typically from the microphone input) and write it to a wave file.

The functions for creating, writing, and closing wave files are in Wave.c, a module found with the DSShow3D sample application in the DirectX SDK. In order to implement the techniques shown in the tutorial, you must add Wave.c and Wave.h to your project and link to Winmm.lib. You must also add Debug.c and Debug.h from the same sample directory, or else edit the calls to the ASSERT macro in Wave.c to call the standard assert function.

The method calls in this tutorial are made through the macros defined in Dsound.h, which are valid for both C and C++.

The tutorial is broken down into the following steps:

  • Step 1: Setting Up DirectSoundCapture
  • Step 2: Setting the Capture Format
  • Step 3: Creating the Capture Buffer
  • Step 4: Setting Up Capture Notification
  • Step 5: Creating the Wave File
  • Step 6: Handling the Capture Notifications
  • Step 7: Streaming Data to the Wave File
  • Step 8: Stopping Capture
  • Step 9: Shutting Down DirectSoundCapture


Step 1: Setting Up DirectSoundCapture

The tutorial requires the following definitions and global declarations:

#define NUMCAPTUREEVENTS 2

LPDIRECTSOUNDCAPTURE        lpdsc;
LPDIRECTSOUNDCAPTUREBUFFER  lpdscb;
LPDIRECTSOUNDNOTIFY         lpdsNotify;
DSCBUFFERDESC               dscbDesc;
HANDLE                      rghEvent[NUMCAPTUREEVENTS];
DSBPOSITIONNOTIFY           rgdscbpn[NUMCAPTUREEVENTS];
WAVEFORMATEX                wfx =
                       {WAVE_FORMAT_PCM, 1, 22050, 44100, 2, 16, 0};
HMMIO                       hmmio;
MMCKINFO                    mmckinfoData, mmckinfoParent;
MMIOINFO                    mmioinfo;
DWORD                       dwTotalBytesWritten;

It is not necessary to create a DirectSound object in order to use DirectSoundCapture. However, if your application will be playing back sound as well as recording it, you should create DirectSound first.

In this tutorial, all the initialization of the capture system takes place in a function called InitDSoundCapture, which takes no parameters. The first step is to create the DirectSoundCapture object. You associate the object with the default capture device by passing NULL as the first parameter to the DirectSoundCaptureCreate function.

BOOL InitDSoundCapture(void)
{

    if FAILED(DirectSoundCaptureCreate(NULL, &lpdsc, NULL))
        return FALSE;


Step 2: Setting the Capture Format

After creating DirectSoundCapture, you should choose a wave format that is supported by the user's device. One way to do this is to start with the highest format and attempt to create a capture buffer in each format until the creation method succeeds. (For an example of how to step through the various formats, see Fdaudio.cpp in the Fdfilter sample program.) In this tutorial you simply check the capabilities of the device to see whether the default 16-bit format (defined in the declaration of the WAVEFORMATEX structure) is supported; if it is not, you select an 8-bit format that is supported by all devices.

The following code is within the InitDSoundCapture function:

    DSCCAPS dsccaps;

    dsccaps.dwSize = sizeof(DSCCAPS);
    if FAILED(IDirectSoundCapture_GetCaps(lpdsc, &dsccaps))
        return FALSE;

    if ((dsccaps.dwFormats & WAVE_FORMAT_2M16) == 0)
    {
        wfx.nSamplesPerSec = 11025;
        wfx.nAvgBytesPerSec = 11025;
        wfx.nBlockAlign = 1;
        wfx.wBitsPerSample = 8;
    }

Remember that if you are also using DirectSound playback in your application, you must select a capture format that is compatible with the format of the primary buffer. For more information, see Creating a Capture Buffer.


Step 3: Creating the Capture Buffer

Once you have ensured that the WAVEFORMATEX structure is valid for the user's device, you can go ahead and create a capture buffer in that format.

    dscbDesc.dwSize = sizeof(DSCBUFFERDESC);
    dscbDesc.dwFlags = 0;
    // Buffer will hold one second's worth of audio
    dscbDesc.dwBufferBytes = wfx.nAvgBytesPerSec;
    dscbDesc.dwReserved = 0;
    dscbDesc.lpwfxFormat = &wfx;

    if FAILED(IDirectSoundCapture_CreateCaptureBuffer(lpdsc,
            &dscbDesc, &lpdscb, NULL))
        return FALSE;

You now have a pointer to the buffer object in lpdscb.


Step 4: Setting Up Capture Notification

As the final initialization step in the InitDSoundCapture function, you will set up notification positions in the capture buffer so that the application knows when it's time to stream more data to the file. In the example, these positions are set at the beginning and halfway mark of the buffer.

First you create the required number of events and store their handles in the rghEvent array:

    for (int i = 0; i < NUMCAPTUREEVENTS; i++)
    {
        rghEvent[i] = CreateEvent(NULL, FALSE, FALSE, NULL);
        if (NULL == rghEvent[i]) return FALSE;
    }

Next, you initialize the array of DSBPOSITIONNOTIFY structures, each of which associates a position in the buffer with an event handle:

    rgdscbpn[0].dwOffset = 0;
    rgdscbpn[0].hEventNotify = rghEvent[0];
    rgdscbpn[1].dwOffset = dscbDesc.dwBufferBytes/2;
    rgdscbpn[1].hEventNotify = rghEvent[1];

Finally, you get the IDirectSoundNotify interface from the capture buffer and pass the DSBPOSITIONNOTIFY array to the SetNotificationPositions method:

    if FAILED(IDirectSoundCaptureBuffer_QueryInterface(lpdscb,
            IID_IDirectSoundNotify, (VOID **)&lpdsNotify))
        return FALSE;

    if FAILED(IDirectSoundNotify_SetNotificationPositions(lpdsNotify,
            NUMCAPTUREEVENTS, rgdscbpn))
    {
        IDirectSoundNotify_Release(lpdsNotify);
        return FALSE;
    }

    return TRUE;
}  // end InitDSoundCapture()

Note that if you need to set up notifications for both a capture buffer and a secondary (output) buffer, the event handles have to be stored in the same rghEvent array. When you receive the notifications in the message loop, you can distinguish between the two types of events by the index number.


Step 5: Creating the Wave File

At this point it is presumed that you have obtained a valid filename and are ready to start saving sound data in a wave file. The process is initiated in the following function:

BOOL StartWrite(TCHAR *pszFileName)
{
    if (WaveCreateFile(pszFileName, &hmmio, &wfx,
            &mmckinfoData, &mmckinfoParent))
      return FALSE;

    if (WaveStartDataWrite(&hmmio, &mmckinfoData, &mmioinfo))
    {
        WaveCloseWriteFile(&hmmio, &mmckinfoData,
                &mmckinfoParent, &mmioinfo,
                dwTotalBytesWritten / (wfx.wBitsPerSample / 8));
        DeleteFile(pszFileName);
        return FALSE;
    }
    if FAILED(IDirectSoundCaptureBuffer_Start(lpdscb,
            DSCBSTART_LOOPING))
    {
        WaveCloseWriteFile(&hmmio, &mmckinfoData,
                &mmckinfoParent, &mmioinfo, 0);
        DeleteFile(pszFileName);
        return FALSE;
    }

    dwTotalBytesWritten = 0;

    return TRUE;
}

This function first calls the WaveCreateFile function in Wave.c, in order to create a RIFF file and write the header for the wave format. It then calls the WaveStartDataWrite function, which advances the file pointer to the data chunk. Finally, it starts the capture buffer. In half a second your application will be notified that data is available, and you must be ready to copy it to the file.

Note also the initialization of dwTotalBytesWritten. This value is going to be needed for the data chunk header after capture is complete.


Step 6: Handling the Capture Notifications

You receive capture notifications as events in the message loop, just as with playback notifications. Here is a sample loop:

BOOL Done = FALSE;
while (!Done)
{
    DWORD dwEvt = MsgWaitForMultipleObjects(
            NUMCAPTUREEVENTS,  // How many possible events
            rghEvent,          // Location of handles
            FALSE,             // Wait for all?
            INFINITE,          // How long to wait
            QS_ALLINPUT);      // Any message is an event

    dwEvt -= WAIT_OBJECT_0;

    // If the event was set by the buffer, there's input
    // to process.

    if (dwEvt < NUMCAPTUREEVENTS)
    {
        StreamToFile();
    }

    // If it's the last event, it's a message

    else if (dwEvt == NUMCAPTUREEVENTS)
    {
        while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
        {
            if (msg.message == WM_QUIT)
            {
                Done = TRUE;
            }
            else
            {
                TranslateMessage(&msg);
                DispatchMessage(&msg);
            }
        }
    }  // end message processing
} // while (!Done)

As already noted, if you are receiving notifications from both a capture buffer and a secondary (output) buffer, you need to distinguish between the two types of events by the index value in dwEvt. For example, events 0 and 1 might be playback notifications, and events 2 and 3 might be capture notifications.


Step 7: Streaming Data to the Wave File

In the first tutorial you saw how to identify the segment of the buffer that was safe to write to by checking the offset of the notification position. This technique would work equally well with the capture buffer in the present tutorial, but this time you'll do things a bit differently.

In the previous step you saw how the StreamToFile function was called in response to a notification event. Unlike the StreamToBuffer function in the previous tutorial, this function does not take the event index as a parameter.

BOOL StreamToFile(void)
{
    DWORD               dwReadPos;
    DWORD               dwNumBytes;
    LPBYTE              pbInput1, pbInput2;
    DWORD               cbInput1, cbInput2;
    static DWORD        dwMyReadCursor = 0;
    UINT                dwBytesWritten;

Note the static declaration of dwMyReadCursor. This is the offset of the next byte of data you want to read; in other words, the byte just beyond the last one read on the previous pass through this function.

The first thing the function does is find the current read position. Remember, this position marks the leading edge of the data that is safe to read. It is not necessarily the same as the notification position, because it has likely advanced since the event was signaled.

    IDirectSoundCaptureBuffer_GetCurrentPosition(lpdscb,
            NULL, &dwReadPos);

The function then subtracts your internal read cursor from the current read position (after allowing for wraparound) in order to determine how many bytes of new data are available:

    if (dwReadPos < dwMyReadCursor)
            dwReadPos += dscbDesc.dwBufferBytes;
    dwNumBytes = dwReadPos - dwMyReadCursor;

You then lock the buffer and do the copy. Because the segment of data you've identified as available is not exactly demarcated by the notification positions at the beginning and midpoint of the buffer, the locked portion of the buffer might wrap around, in which case two separate copy operations are required:

    if FAILED(IDirectSoundCaptureBuffer_Lock(lpdscb,
            dwMyReadCursor, dwNumBytes,
            (LPVOID *)&pbInput1, &cbInput1,
            (LPVOID *)&pbInput2, &cbInput2, 0))
        OutputDebugString("Capture lock failure");

    else
        {
        if (WaveWriteFile(hmmio, cbInput1, pbInput1, &mmckinfoData,
                        &dwBytesWritten, &mmioinfo))
          OutputDebugString("Failure writing data to file\n");
        dwTotalBytesWritten += dwBytesWritten;

        // Wraparound
        if (pbInput2 != NULL)
        {
            if (WaveWriteFile(hmmio, cbInput2, pbInput2,
                    &mmckinfoData, &dwBytesWritten, &mmioinfo))
              OutputDebugString("Failure writing data to file\n");
            dwTotalBytesWritten += dwBytesWritten;
        }

        IDirectSoundCaptureBuffer_Unlock(lpdscb,
                pbInput1, cbInput1,
                pbInput2, cbInput2);
    }

The WaveWriteFile function returns 0 if successful and also fills dwBytesWritten with the number of bytes actually copied to the file. This value is added to the cumulative total, which will be needed when the file is closed.

Finally, update the internal read cursor, compensating for wraparound, and return to the message loop:

    dwMyReadCursor += dwNumBytes;
    if (dwMyReadCursor >= dscbDesc.dwBufferBytes)
                dwMyReadCursor -= dscbDesc.dwBufferBytes;

    return TRUE;
} // end StreamToFile()


Step 8: Stopping Capture

When it's time to stop recording, call the following function:

BOOL StopWrite()
{
    IDirectSoundCaptureBuffer_Stop(lpdscb);
    StreamToFile();
    WaveCloseWriteFile(&hmmio, &mmckinfoData,
            &mmckinfoParent, &mmioinfo,
            dwTotalBytesWritten / (wfx.wBitsPerSample / 8));
    return TRUE;
}

This function stops the capture buffer, calls the StreamToFile function one more time in order to save all the data up to the current read position, and closes the file. The WaveCloseWriteFile function in Wave.c also updates the header of the data chunk by writing the total number of samples.


Step 9: Shutting Down DirectSoundCapture

Before closing the application you must shut down the capture system. This is a simple matter of releasing all the objects. You must release the IDirectSoundNotify interface before releasing the capture buffer.

void CleanupDSoundCapture(void)
{
    if (lpdsNotify)
        IDirectSoundNotify_Release(lpdsNotify);
    if (lpdscb)
        IDirectSoundCaptureBuffer_Release(lpdscb);
    if (lpdsc)
        IDirectSoundCapture_Release(lpdsc);
}


DirectSound Reference

This section contains reference information for the API elements that DirectSound provides. Reference material is divided into the following categories.

  • Interfaces
  • Functions
  • Callback Function
  • Structures
  • Return Values


Interfaces

This section contains references for methods of the following DirectSound interfaces:

  • IDirectSound
  • IDirectSound3DBuffer
  • IDirectSound3DListener
  • IDirectSoundBuffer
  • IDirectSoundCapture
  • IDirectSoundCaptureBuffer
  • IDirectSoundNotify
  • IKsPropertySet


IDirectSound

Applications use the methods of the IDirectSound interface to create DirectSound objects and set up the environment. This section is a reference to the methods of this interface.

The interface is obtained by using the DirectSoundCreate function.

The methods of the IDirectSound interface can be organized into the following groups:

Initialization | Initialize
 | SetCooperativeLevel
Buffer creation | CreateSoundBuffer
 | DuplicateSoundBuffer
Device capabilities | GetCaps
Memory management | Compact
Speaker configuration | GetSpeakerConfig
 | SetSpeakerConfig

The IDirectSound interface, like all COM interfaces, inherits the IUnknown interface methods. The IUnknown interface supports the following three methods:

IUnknown | AddRef
 | QueryInterface
 | Release

The LPDIRECTSOUND type is defined as a pointer to the IDirectSound interface:

typedef struct IDirectSound    *LPDIRECTSOUND;

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.
Import Library: Use dsound.lib.


IDirectSound::Compact

The IDirectSound::Compact method moves the unused portions of on-board sound memory, if any, to a contiguous block so that the largest portion of free memory will be available.

HRESULT Compact();

Parameters

None.

Return Values

If the method succeeds, the return value is DS_OK.

If the method fails, the return value may be one of the following error values:

DSERR_INVALIDPARAM
DSERR_PRIOLEVELNEEDED
DSERR_UNINITIALIZED

Remarks

The application's DirectSound object must have at least the DSSCL_PRIORITY cooperative level. See IDirectSound::SetCooperativeLevel.

This method will fail if any operations are in progress.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.
Import Library: Use dsound.lib.


IDirectSound::CreateSoundBuffer

The IDirectSound::CreateSoundBuffer method creates a DirectSoundBuffer object to hold a sequence of audio samples.

HRESULT CreateSoundBuffer(
  LPCDSBUFFERDESC lpcDSBufferDesc,
  LPLPDIRECTSOUNDBUFFER lplpDirectSoundBuffer,
  IUnknown FAR * pUnkOuter
);

Parameters

lpcDSBufferDesc
Address of a DSBUFFERDESC structure that contains the description of the sound buffer to be created.
lplpDirectSoundBuffer
Address of a pointer to the new DirectSoundBuffer object, or NULL if the buffer cannot be created.
pUnkOuter
Controlling unknown of the aggregate. Its value must be NULL.

Return Values

If the method succeeds, the return value is DS_OK.

If the method fails, the return value may be one of the following error values:

DSERR_ALLOCATED
DSERR_CONTROLUNAVAIL
DSERR_BADFORMAT
DSERR_INVALIDPARAM
DSERR_NOAGGREGATION
DSERR_OUTOFMEMORY
DSERR_UNINITIALIZED
DSERR_UNSUPPORTED

Remarks

Before it can play any sound buffers, the application must specify a cooperative level for a DirectSound object by using the IDirectSound::SetCooperativeLevel method.

The lpDSBufferDesc parameter points to a structure that describes the type of buffer desired, including format, size, and capabilities. The application must specify the needed capabilities, or they will not be available. For example, if the application creates a DirectSoundBuffer object without specifying the DSBCAPS_CTRLFREQUENCY flag, any call to IDirectSoundBuffer::SetFrequency will fail.

The DSBCAPS_STATIC flag can also be specified, in which case DirectSound stores the buffer in on-board memory, if available, to take advantage of hardware mixing. To force the buffer to use either hardware or software mixing, use the DSBCAPS_LOCHARDWARE or DSBCAPS_LOCSOFTWARE flag.

To find out if the buffer was created in hardware or software, call the IDirectSoundBuffer:GetCaps method and check for the DBSCAPS_LOCHARDWARE or DSBCAPS_LOCSOFTWARE flag in the dwFlags member of the returned DSBCAPS structure.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.
Import Library: Use dsound.lib.

See Also

DSBUFFERDESC, IDirectSound::DuplicateSoundBuffer, IDirectSound::SetCooperativeLevel, IDirectSoundBuffer, IDirectSoundBuffer::GetFormat, IDirectSoundBuffer::GetVolume, IDirectSoundBuffer::Lock, IDirectSoundBuffer::Play, IDirectSoundBuffer::SetFormat, IDirectSoundBuffer::SetFrequency


IDirectSound::DuplicateSoundBuffer

The IDirectSound::DuplicateSoundBuffer method creates a new DirectSoundBuffer object that uses the same buffer memory as the original object.

HRESULT DuplicateSoundBuffer(
  LPDIRECTSOUNDBUFFER lpDsbOriginal,
  LPLPDIRECTSOUNDBUFFER lplpDsbDuplicate
);

Parameters

lpDsbOriginal
Address of the DirectSoundBuffer object to be duplicated.
lplpDsbDuplicate
Address of a pointer to the new DirectSoundBuffer object.

Return Values

If the method succeeds, the return value is DS_OK.

If the method fails, the return value may be one of the following error values:

DSERR_ALLOCATED
DSERR_INVALIDCALL
DSERR_INVALIDPARAM
DSERR_OUTOFMEMORY
DSERR_UNINITIALIZED

Remarks

The new object can be used just like the original.

Initially, the duplicate buffer will have the same parameters as the original buffer. However, the application can change the parameters of each buffer independently, and each can be played or stopped without affecting the other.

If data in the buffer is changed through one object, the change will be reflected in the other object because the buffer memory is shared.

The buffer memory will be released when the last object referencing it is released.

Applications cannot assume that an attempt to duplicate a sound buffer will always succeed. In particular, DirectSound will not create a software duplicate of a hardware buffer.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.
Import Library: Use dsound.lib.

See Also

IDirectSound::CreateSoundBuffer


IDirectSound::GetCaps

The IDirectSound::GetCaps method retrieves the capabilities of the hardware device that is represented by the DirectSound object.

HRESULT GetCaps(
  LPDSCAPS lpDSCaps
);

Parameters

lpDSCaps
Address of the DSCAPS structure to contain the capabilities of this sound device.

Return Values

If the method succeeds, the return value is DS_OK.

If the method fails, the return value may be one of the following error values:

DSERR_GENERIC
DSERR_INVALIDPARAM
DSERR_UNINITIALIZED

Remarks

Information retrieved in the DSCAPS structure describes the maximum capabilities of the sound device and those currently available, such as the number of hardware mixing channels and the amount of on-board sound memory. You can use this information to fine-tune performance and optimize resource allocation.

Because of resource-sharing requirements, the maximum capabilities in one area might be available only at the cost of another area. For example, the maximum number of hardware-mixed streaming sound buffers might be available only if there are no hardware static sound buffers.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.
Import Library: Use dsound.lib.

See Also

DirectSoundCreate


IDirectSound::GetSpeakerConfig

The IDirectSound::GetSpeakerConfig method retrieves the speaker configuration.

HRESULT GetSpeakerConfig(
  LPDWORD lpdwSpeakerConfig
);

Parameters

lpdwSpeakerConfig
Address of the speaker configuration for this DirectSound object. The speaker configuration is specified with one of the following values:
DSSPEAKER_HEADPHONE
The audio is played through headphones.
DSSPEAKER_MONO
The audio is played through a single speaker.
DSSPEAKER_QUAD
The audio is played through quadraphonic speakers.
DSSPEAKER_STEREO
The audio is played through stereo speakers (default value).
DSSPEAKER_SURROUND
The audio is played through surround speakers.

DSSPEAKER_STEREO can be combined with one of the following values:

DSSPEAKER_GEOMETRY_WIDE
The speakers are directed over an arc of 20 degrees.
DSSPEAKER_GEOMETRY_NARROW
The speakers are directed over an arc of 10 degrees.
DSSPEAKER_GEOMETRY_MIN
The speakers are directed over an arc of 5 degrees.
DSSPEAKER_GEOMETRY_MAX
The speakers are directed over an arc of 180 degrees.

Return Values

If the method succeeds, the return value is DS_OK.

If the method fails, the return value may be one of the following error values:

DSERR_INVALIDPARAM
DSERR_UNINITIALIZED

Remarks

The value returned at lpdwSpeakerConfig may be a packed DWORD containing both configuration and geometry information. Use the DSSPEAKER_CONFIG and DSSPEAKER_GEOMETRY macros to unpack the DWORD, as in the following example:

if (DSSPEAKER_CONFIG(dwSpeakerConfig) == DSSPEAKER_STEREO)
    {
    if (DSSPEAKER_GEOMETRY(dwSpeakerConfig) ==
                      DSSPEAKER_GEOMETRY_WIDE)
       {...}
    }

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.
Import Library: Use dsound.lib.

See Also

IDirectSound::SetSpeakerConfig, Speaker Configuration


IDirectSound::Initialize

The IDirectSound::Initialize method initializes the DirectSound object that was created by using the CoCreateInstance function.

HRESULT Initialize(
  LPGUID lpGuid
);

Parameters

lpGuid
Address of the globally unique identifier (GUID) specifying the sound driver to which this DirectSound object binds. Pass NULL to select the primary sound driver.

Return Values

If the method succeeds, the return value is DS_OK.

If the method fails, the return value may be one of the following error values:

DSERR_ALREADYINITIALIZED
DSERR_GENERIC
DSERR_INVALIDPARAM
DSERR_NODRIVER

Remarks

This method is provided for compliance with the Component Object Model (COM) protocol. If the DirectSoundCreate function was used to create the DirectSound object, this method returns DSERR_ALREADYINITIALIZED. If IDirectSound::Initialize is not called when using CoCreateInstance to create the DirectSound object, any method called afterward returns DSERR_UNINITIALIZED.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.
Import Library: Use dsound.lib.

See Also

DirectSoundCreate


IDirectSound::SetCooperativeLevel

The IDirectSound::SetCooperativeLevel method sets the cooperative level of the application for this sound device.

HRESULT SetCooperativeLevel(
  HWND hwnd,
  DWORD dwLevel
);

Parameters

hwnd
Window handle to the application. See Remarks.
dwLevel
Requested priority level. Specify one of the following values:
DSSCL_EXCLUSIVE
Sets the application to the exclusive level. When it has the input focus, the application will be the only one audible (sounds from applications with the DSBCAPS_GLOBALFOCUS flag set will be muted). With this level, it also has all the privileges of the DSSCL_PRIORITY level. DirectSound will restore the hardware format, as specified by the most recent call to the IDirectSoundBuffer::SetFormat method, once the application gains the input focus. (Note that DirectSound will always restore the wave format no matter what priority level is set.)
DSSCL_NORMAL
Sets the application to a fully cooperative status. This level has the smoothest multitasking and resource-sharing behavior, but because it does not allow the primary buffer format to change, output is restricted to the default 8-bit format.
DSSCL_PRIORITY
Sets the application to the priority level. Applications with this cooperative level can call the IDirectSoundBuffer::SetFormat and IDirectSound::Compact methods.
DSSCL_WRITEPRIMARY
This is the highest priority level. The application has write access to the primary sound buffers. No secondary sound buffers can be played. This level cannot be set if the DirectSound driver is being emulated for the device; that is, if the IDirectSound::GetCaps method returns the DSCAPS_EMULDRIVER flag in the DSCAPS structure.

Return Values

If the method succeeds, the return value is DS_OK.

If the method fails, the return value may be one of the following error values:

DSERR_ALLOCATED
DSERR_INVALIDPARAM
DSERR_UNINITIALIZED
DSERR_UNSUPPORTED

Remarks

The application must set the cooperative level by calling this method before its buffers can be played. The recommended cooperative level is DSSCL_PRIORITY; use other priority levels when necessary. For additional information, see Cooperative Levels.

The hwnd parameter should be the top-level application window handle. If you are also using DirectDraw, it must be the same handle passed to the IDirectDraw4::SetCooperativeLevel method.

If your application cannot easily supply a window handle, you can obtain one by using the following code:

HWND hWnd = GetForegroundWindow();
if (hWnd == NULL)
{
    hWnd = GetDesktopWindow();
}

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.
Import Library: Use dsound.lib.

See Also

IDirectSound::Compact, IDirectSoundBuffer::GetFormat, IDirectSoundBuffer::GetVolume, IDirectSoundBuffer::Lock, IDirectSoundBuffer::Play, IDirectSoundBuffer::Restore, IDirectSoundBuffer::SetFormat


IDirectSound::SetSpeakerConfig

The IDirectSound::SetSpeakerConfig method specifies the speaker configuration of the DirectSound object.

HRESULT SetSpeakerConfig(
  DWORD dwSpeakerConfig
);

Parameters

dwSpeakerConfig
Speaker configuration of the specified DirectSound object. This parameter can be one of the following values:
DSSPEAKER_HEADPHONE
The speakers are headphones.
DSSPEAKER_MONO
The speakers are monaural.
DSSPEAKER_QUAD
The speakers are quadraphonic.
DSSPEAKER_STEREO
The speakers are stereo (default value).
DSSPEAKER_SURROUND
The speakers are surround sound.
DSSPEAKER_STEREO may be combined with one of the following values:
DSSPEAKER_GEOMETRY_WIDE
The speakers are directed over an arc of 20 degrees.
DSSPEAKER_GEOMETRY_NARROW
The speakers are directed over an arc of 10 degrees.
DSSPEAKER_GEOMETRY_MIN
The speakers are directed over an arc of 5 degrees.
DSSPEAKER_GEOMETRY_MAX
The speakers are directed over an arc of 180 degrees.

Return Values

If the method succeeds, the return value is DS_OK.

If the method fails, the return value may be one of the following error values:

DSERR_INVALIDPARAM
DSERR_UNINITIALIZED

Remarks

If a geometry value is to be used, it must be packed in a DWORD along with the DSSPEAKER_STEREO flag. This can be done by using the DSSPEAKER_COMBINED macro, as in the following C++ example:

lpds->SetSpeakerConfig(DSSPEAKER_COMBINED(
    DSSPEAKER_STEREO, DSSPEAKER_GEOMETRY_WIDE));

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.
Import Library: Use dsound.lib.

See Also

IDirectSound::GetSpeakerConfig, Speaker Configuration


IDirectSound3DBuffer

Applications use the methods of the IDirectSound3DBuffer interface to retrieve and set parameters that describe the position, orientation, and environment of a sound buffer in 3-D space. This section is a reference to the methods of this interface. For a conceptual overview, see DirectSound 3-D Buffers.

The IDirectSound3DBuffer is obtaining by using the IDirectSoundBuffer::QueryInterface method. For more information, see Obtaining the IDirectSound3DBuffer Interface.

The methods of the IDirectSound3DBuffer interface can be organized into the following groups:

Batch parameter manipulation | GetAllParameters
 | SetAllParameters
Distance | GetMaxDistance
 | GetMinDistance
 | SetMaxDistance
 | SetMinDistance
Operation mode | GetMode
 | SetMode
Position | GetPosition
 | SetPosition
Sound projection cones | GetConeAngles
 | GetConeOrientation
 | GetConeOutsideVolume
 | SetConeAngles
 | SetConeOrientation
 | SetConeOutsideVolume
Velocity | GetVelocity
 | SetVelocity

The IDirectSound3DBuffer interface, like all COM interfaces, inherits the IUnknown interface methods. The IUnknown interface supports the following three methods:

IUnknown | AddRef
 | QueryInterface
 | Release

The LPDIRECTSOUND3DBUFFER type is defined as a pointer to the IDirectSound3DBuffer interface:

typedef struct IDirectSound3DBuffer    *LPDIRECTSOUND3DBUFFER;

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.
Import Library: Use dsound.lib.


IDirectSound3DBuffer::GetAllParameters

The IDirectSound3DBuffer::GetAllParameters method retrieves information that describes the 3-D characteristics of a sound buffer at a given point in time.

HRESULT GetAllParameters(
  LPDS3DBUFFER lpDs3dBuffer
);

Parameters

lpDs3dBuffer
Address of a DS3DBUFFER structure that will contain the information describing the 3-D characteristics of the sound buffer.

Return Values

If the method succeeds, the return value is DS_OK.

If the method fails, the return value may be DSERR_INVALIDPARAM.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.
Import Library: Use dsound.lib.


IDirectSound3DBuffer::GetConeAngles

The IDirectSound3DBuffer::GetConeAngles method retrieves the inside and outside angles of the sound projection cone for this sound buffer.

HRESULT GetConeAngles(
  LPDWORD lpdwInsideConeAngle,
  LPDWORD lpdwOutsideConeAngle
);

Parameters

lpdwInsideConeAngle and lpdwOutsideConeAngle
Addresses of variables that will contain the inside and outside angles of the sound projection cone, in degrees.

Return Values

If the method succeeds, the return value is DS_OK.

If the method fails, the return value may be DSERR_INVALIDPARAM.

Remarks

The minimum, maximum, and default cone angles are defined in Dsound.h as DS3D_MINCONEANGLE, DS3D_MAXCONEANGLE, and DS3D_DEFAULTCONEANGLE.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.
Import Library: Use dsound.lib.


IDirectSound3DBuffer::GetConeOrientation

The IDirectSound3DBuffer::GetConeOrientation method retrieves the orientation of the sound projection cone for this sound buffer.

HRESULT GetConeOrientation(
  LPD3DVECTOR lpvOrientation
);

Parameters

lpvOrientation
Address of a D3DVECTOR structure that will contain the current orientation of the sound projection cone. The vector information represents the center of the sound cone.

Return Values

If the method succeeds, the return value is DS_OK.

If the method fails, the return value may be DSERR_INVALIDPARAM.

Remarks

The values returned are not necessarily the same as those set by using the IDirectSound3DBuffer::SetConeOrientation method. DirectSound adjusts orientation vectors so that they are have a magnitude of less than or equal to 1.0.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.
Import Library: Use dsound.lib.

See Also

IDirectSound3DBuffer::SetConeOrientation, IDirectSound3DBuffer::SetConeAngles, IDirectSound3DBuffer::SetConeOutsideVolume


IDirectSound3DBuffer::GetConeOutsideVolume

The IDirectSound3DBuffer::GetConeOutsideVolume method retrieves the current cone outside volume for this sound buffer.

HRESULT GetConeOutsideVolume(
  LPLONG lplConeOutsideVolume
);

Parameters

lplConeOutsideVolume
Address of a variable that will contain the current cone outside volume for this buffer.

Return Values

If the method succeeds, the return value is DS_OK.

If the method fails, the return value may be DSERR_INVALIDPARAM.

Remarks

Volume levels are represented by attenuation. Allowable values are between DSBVOLUME_MAX (no attenuation) and DSBVOLUME_MIN (silence). The default value is DS3D_DEFAULTCONEOUTSIDEVOLUME (no attenuation). These values are defined in Dsound.h. Currently DirectSound does not support amplification.

For additional information about the concept of outside volume, see Sound Cones.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.
Import Library: Use dsound.lib.

See Also

IDirectSoundBuffer::SetVolume


IDirectSound3DBuffer::GetMaxDistance

The IDirectSound3DBuffer::GetMaxDistance method retrieves the current maximum distance for this sound buffer.

HRESULT GetMaxDistance(
  LPD3DVALUE lpflMaxDistance
);

Parameters

lpflMaxDistance
Address of a variable that will contain the current maximum distance setting.

Return Values

If the method succeeds, the return value is DS_OK.

If the method fails, the return value may be DSERR_INVALIDPARAM.

Remarks

The default maximum distance, defined as DS3D_DEFAULTMAXDISTANCE, is effectively infinite.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.
Import Library: Use dsound.lib.

See Also

IDirectSound3DBuffer::GetMinDistance, IDirectSound3DBuffer::SetMaxDistance


IDirectSound3DBuffer::GetMinDistance

The IDirectSound3DBuffer::GetMinDistance method retrieves the current minimum distance for this sound buffer.

HRESULT GetMinDistance(
  LPD3DVALUE lpflMinDistance
);

Parameters

lpflMinDistance
Address of a variable that will contain the current minimum distance setting.

Return Values

If the method succeeds, the return value is DS_OK.

If the method fails, the return value may be DSERR_INVALIDPARAM.

Remarks

By default, the minimum distance value is DS3D_DEFAULTMINDISTANCE, currently defined as 1.0 (corresponding to 1.0 meter at the default distance factor of 1.0 meters per unit).

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.
Import Library: Use dsound.lib.

See Also

IDirectSound3DBuffer::SetMinDistance, IDirectSound3DBuffer::GetMaxDistance


IDirectSound3DBuffer::GetMode

The IDirectSound3DBuffer::GetMode method retrieves the current operation mode for 3-D sound processing.

HRESULT GetMode(
  LPDWORD lpdwMode
);

Parameters

lpdwMode
Address of a variable that will contain the current mode setting. This value will be one of the following:
DS3DMODE_DISABLE
Processing of 3-D sound is disabled. The sound seems to originate from the center of the listener's head.
DS3DMODE_HEADRELATIVE
Sound parameters (position, velocity, and orientation) are relative to the listener's parameters. In this mode, the absolute parameters of the sound are updated automatically as the listener's parameters change, so that the relative parameters remain constant.
DS3DMODE_NORMAL
Normal processing. This is the default mode.

Return Values

If the method succeeds, the return value is DS_OK.

If the method fails, the return value may be DSERR_INVALIDPARAM.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.
Import Library: Use dsound.lib.


IDirectSound3DBuffer::GetPosition

The IDirectSound3DBuffer::GetPosition method retrieves the sound buffer's current position, in distance units. By default, distance units are meters, but the units can be changed by using the IDirectSound3DListener::SetDistanceFactor method.

HRESULT GetPosition(
  LPD3DVECTOR lpvPosition
);

Parameters

lpvPosition
Address of a D3DVECTOR structure that will contain the current position of the sound buffer.

Return Values

If the method succeeds, the return value is DS_OK.

If the method fails, the return value may be DSERR_INVALIDPARAM.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.
Import Library: Use dsound.lib.


IDirectSound3DBuffer::GetVelocity

The IDirectSound3DBuffer::GetVelocity method retrieves the current velocity for this sound buffer. Velocity is measured in units per second. The default unit is one meter, but this can be changed by using the IDirectSound3DListener::SetDistanceFactor method.

HRESULT GetVelocity(
  LPD3DVECTOR lpvVelocity
);

Parameters

lpvVelocity
Address of a D3DVECTOR structure that will contain the sound buffer's current velocity.

Return Values

If the method succeeds, the return value is DS_OK.

If the method fails, the return value may be DSERR_INVALIDPARAM.

Remarks

Velocity is used for Doppler effects only. It does not actually move the buffer. For additional information, see Doppler Factor.

The default unit of measurement is meters per second, but this can be changed by using the IDirectSound3DListener::SetDistanceFactor method.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.
Import Library: Use dsound.lib.

See Also

IDirectSound3DBuffer::SetPosition, IDirectSound3DBuffer::SetVelocity


IDirectSound3DBuffer::SetAllParameters

The IDirectSound3DBuffer::SetAllParameters method sets all 3-D sound buffer parameters from a given DS3DBUFFER structure that describes all aspects of the sound buffer at a moment in time.

HRESULT SetAllParameters(
  LPCDS3DBUFFER lpcDs3dBuffer,
  DWORD dwApply
);

Parameters

lpcDs3dBuffer
Address of a DS3DBUFFER structure containing the information that describes the 3-D characteristics of the sound buffer.
dwApply
Value indicating when the setting should be applied. This value must be one of the following:
DS3D_DEFERRED | Settings are not applied until the application calls the IDirectSound3DListener::CommitDeferredSettings method. This allows the application to change several settings and generate a single recalculation.
DS3D_IMMEDIATE | Settings are applied immediately, causing the system to recalculate the 3-D coordinates for all 3-D sound buffers.

Return Values

If the method succeeds, the return value is DS_OK.

If the method fails, the return value may be DSERR_INVALIDPARAM.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.
Import Library: Use dsound.lib.


IDirectSound3DBuffer::SetConeAngles

The IDirectSound3DBuffer::SetConeAngles method sets the inside and outside angles of the sound projection cone for this sound buffer.

HRESULT SetConeAngles(
  DWORD dwInsideConeAngle,
  DWORD dwOutsideConeAngle,
  DWORD dwApply
);

Parameters

dwInsideConeAngle and dwOutsideConeAngle
Inside and outside angles of the sound projection cone, in degrees.
dwApply
Value indicating when the setting should be applied. This value must be one of the following:
DS3D_DEFERRED | Settings are not applied until the application calls the IDirectSound3DListener::CommitDeferredSettings method. This allows the application to change several settings and generate a single recalculation.
DS3D_IMMEDIATE | Settings are applied immediately, causing the system to recalculate the 3-D coordinates for all 3-D sound buffers.

Return Values

If the method succeeds, the return value is DS_OK.

If the method fails, the return value may be DSERR_INVALIDPARAM.

Remarks

The minimum, maximum, and default cone angles are defined in Dsound.h as DS3D_MINCONEANGLE, DS3D_MAXCONEANGLE, and DS3D_DEFAULTCONEANGLE. Each angle must be in the range of 0 degrees (no cone) to 360 degrees (the full sphere). The default value is 360.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.
Import Library: Use dsound.lib.

See Also

IIDirectSound3DBuffer::GetConeOutsideVolume, IDirectSound3DBuffer::SetConeOutsideVolume


IDirectSound3DBuffer::SetConeOrientation

The IDirectSound3DBuffer::SetConeOrientation method sets the orientation of the sound projection cone for this sound buffer. This method has no effect unless the cone angle and cone volume factor have also been set.

HRESULT SetConeOrientation(
  D3DVALUE x,
  D3DVALUE y,
  D3DVALUE z,
  DWORD dwApply
);

Parameters

x, y, and z
Values whose types are D3DVALUE and that represent the coordinates of the new sound cone orientation vector.
dwApply
Value indicating when the setting should be applied. This value must be one of the following:
DS3D_DEFERRED | Settings are not applied until the application calls the IDirectSound3DListener::CommitDeferredSettings method. This allows the application to change several settings and generate a single recalculation.
DS3D_IMMEDIATE | Settings are applied immediately, causing the system to recalculate the 3-D coordinates for all 3-D sound buffers.

Return Values

If the method succeeds, the return value is DS_OK.

If the method fails, the return value may be DSERR_INVALIDPARAM.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.
Import Library: Use dsound.lib.

See Also

IDirectSound3DBuffer::SetConeAngles, IDirectSound3DBuffer::SetConeOutsideVolume


IDirectSound3DBuffer::SetConeOutsideVolume

The IDirectSound3DBuffer::SetConeOutsideVolume method sets the current cone outside volume for this sound buffer.

HRESULT SetConeOutsideVolume(
  LONG lConeOutsideVolume,
  DWORD dwApply
);

Parameters

lConeOutsideVolume
Cone outside volume for this sound buffer, in hundredths of decibels. Allowable values are between DSBVOLUME_MAX (no attenuation) and DSBVOLUME_MIN (silence). These values are defined in Dsound.h.
dwApply
Value indicating when the setting should be applied. This value must be one of the following:
DS3D_DEFERRED | Settings are not applied until the application calls the IDirectSound3DListener::CommitDeferredSettings method. This allows the application to change several settings and generate a single recalculation.
DS3D_IMMEDIATE | Settings are applied immediately, causing the system to recalculate the 3-D coordinates for all 3-D sound buffers.

Return Values

If the method succeeds, the return value is DS_OK.

If the method fails, the return value may be DSERR_INVALIDPARAM.

Remarks

Volume levels are represented by attenuation. Allowable values are between DSBVOLUME_MAX (no attenuation) and DSBVOLUME_MIN (silence). The default value is DS3D_DEFAULTCONEOUTSIDEVOLUME (no attenuation). These values are defined in Dsound.h. Currently DirectSound does not support amplification.

For information about the concept of cone outside volume, see Sound Cones.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.
Import Library: Use dsound.lib.

See Also

IDirectSoundBuffer::SetVolume


IDirectSound3DBuffer::SetMaxDistance

The IDirectSound3DBuffer::SetMaxDistance method sets the current maximum distance value.

HRESULT SetMaxDistance(
  D3DVALUE flMaxDistance,
  DWORD dwApply
);

Parameters

flMaxDistance
New maximum distance value.
dwApply
Value indicating when the setting should be applied. This value must be one of the following:
DS3D_DEFERRED | Settings are not applied until the application calls the IDirectSound3DListener::CommitDeferredSettings method. This allows the application to change several settings and generate a single recalculation.
DS3D_IMMEDIATE | Settings are applied immediately, causing the system to recalculate the 3-D coordinates for all 3-D sound buffers.

Return Values

If the method succeeds, the return value is DS_OK.

If the method fails, the return value may be DSERR_INVALIDPARAM.

Remarks

The default maximum distance, defined as DS3D_DEFAULTMAXDISTANCE, is effectively infinite.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.
Import Library: Use dsound.lib.

See Also

IDirectSound3DBuffer::GetMaxDistance, IDirectSound3DBuffer::SetMinDistance


IDirectSound3DBuffer::SetMinDistance

The IDirectSound3DBuffer::SetMinDistance method sets the current minimum distance value.

HRESULT SetMinDistance(
  D3DVALUE flMinDistance,
  DWORD dwApply
);

Parameters

flMinDistance
New minimum distance value.
dwApply
Value indicating when the setting should be applied. This value must be one of the following:
DS3D_DEFERRED
Settings are not applied until the application calls the IDirectSound3DListener::CommitDeferredSettings method. This allows the application to change several settings and generate a single recalculation.
DS3D_IMMEDIATE
Settings are applied immediately, causing the system to recalculate the 3-D coordinates for all 3-D sound buffers.

Return Values

If the method succeeds, the return value is DS_OK.

If the method fails, the return value may be DSERR_INVALIDPARAM.

Remarks

By default, the minimum distance value is DS3D_DEFAULTMINDISTANCE, currently defined as 1.0 (corresponding to 1.0 meter at the default distance factor of 1.0 meters per unit).

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.
Import Library: Use dsound.lib.

See Also

IDirectSound3DBuffer::SetMaxDistance


IDirectSound3DBuffer::SetMode

The IDirectSound3DBuffer::SetMode method sets the operation mode for 3-D sound processing.

HRESULT SetMode(
  DWORD dwMode,
  DWORD dwApply
);

Parameters

dwMode
Flag specifying the 3-D sound processing mode to be set:
DS3DMODE_DISABLE
Processing of 3-D sound is disabled. The sound seems to originate from the center of the listener's head.
DS3DMODE_HEADRELATIVE
Sound parameters (position, velocity, and orientation) are relative to the listener's parameters. In this mode, the absolute parameters of the sound are updated automatically as the listener's parameters change, so that the relative parameters remain constant.
DS3DMODE_NORMAL
Normal processing. This is the default mode.
dwApply
Value indicating when the setting should be applied. This value must be one of the following:
DS3D_DEFERRED
Settings are not applied until the application calls the IDirectSound3DListener::CommitDeferredSettings method. This allows the application to change several settings and generate a single recalculation.
DS3D_IMMEDIATE
Settings are applied immediately, causing the system to recalculate the 3-D coordinates for all 3-D sound buffers.

Return Values

If the method succeeds, the return value is DS_OK.

If the method fails, the return value may be DSERR_INVALIDPARAM.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.
Import Library: Use dsound.lib.


IDirectSound3DBuffer::SetPosition

The IDirectSound3DBuffer::SetPosition method sets the sound buffer's current position, in distance units. By default, distance units are meters, but the units can be changed by using the IDirectSound3DListener::SetDistanceFactor method.

HRESULT SetPosition(
  D3DVALUE x,
  D3DVALUE y,
  D3DVALUE z,
  DWORD dwApply
);

Parameters

x, y, and z
Values whose types are D3DVALUE and that represent the coordinates of the new position vector. Note that DirectSound may adjust these values to prevent floating-point overflow.
dwApply
Value indicating when the setting should be applied. This value must be one of the following:
DS3D_DEFERRED
Settings are not applied until the application calls the IDirectSound3DListener::CommitDeferredSettings method. This allows the application to change several settings and generate a single recalculation.
DS3D_IMMEDIATE
Settings are applied immediately, causing the system to recalculate the 3-D coordinates for all 3-D sound buffers.

Return Values

If the method succeeds, the return value is DS_OK.

If the method fails, the return value may be DSERR_INVALIDPARAM.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.
Import Library: Use dsound.lib.


IDirectSound3DBuffer::SetVelocity

The IDirectSound3DBuffer::SetVelocity method sets the sound buffer's current velocity.

HRESULT SetVelocity(
  D3DVALUE x,
  D3DVALUE y,
  D3DVALUE z,
  DWORD dwApply
);

Parameters

x, y, and z
Values whose types are D3DVALUE and that represent the coordinates of the new velocity vector. Note that DirectSound may adjust these values to prevent floating-point overflow.
dwApply
Value indicating when the setting should be applied. This value must be one of the following:
DS3D_DEFERRED
Settings are not applied until the application calls the IDirectSound3DListener::CommitDeferredSettings method. This allows the application to change several settings and generate a single recalculation.
DS3D_IMMEDIATE
Settings are applied immediately, causing the system to recalculate the 3-D coordinates for all 3-D sound buffers.

Return Values

If the method succeeds, the return value is DS_OK.

If the method fails, the return value may be DSERR_INVALIDPARAM.

Remarks

Velocity is used for Doppler effects only. It does not actually move the buffer. For additional information, see Doppler Factor.

The default unit of measurement is meters per second, but this can be changed by using the IDirectSound3DListener::SetDistanceFactor method.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.
Import Library: Use dsound.lib.

See Also

IDirectSound3DBuffer::SetPosition, IDirectSound3DBuffer::GetVelocity


IDirectSound3DListener

Applications use the methods of the IDirectSound3DListener interface to retrieve and set parameters that describe a listener's position, orientation, and listening environment in 3-D space. This section is a reference to the methods of this interface. For a conceptual overview, see DirectSound 3-D Listeners.

The interface is obtained by using the IDirectSoundBuffer::QueryInterface method. For more information, see Obtaining the IDirectSound3DListener Interface.

The methods of the IDirectSound3DListener interface can be organized into the following groups:

Batch parameters | GetAllParameters
 | SetAllParameters
Deferred settings | CommitDeferredSettings
Distance factor | GetDistanceFactor
 | SetDistanceFactor
Doppler factor | GetDopplerFactor
 | SetDopplerFactor
Orientation | GetOrientation
 | SetOrientation
Position | GetPosition
 | SetPosition
Rolloff factor | GetRolloffFactor
 | SetRolloffFactor
Velocity | GetVelocity
 | SetVelocity

The IDirectSound3DListener interface, like all COM interfaces, inherits the IUnknown interface methods. The IUnknown interface supports the following three methods:

IUnknown | AddRef
 | QueryInterface
 | Release

The LPDIRECTSOUND3DLISTENER type is defined as a pointer to the IDirectSound3DListener interface:

typedef struct IDirectSound3DListener    *LPDIRECTSOUND3DLISTENER;

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.
Import Library: Use dsound.lib.


IDirectSound3DListener::CommitDeferredSettings

The IDirectSound3DListener::CommitDeferredSettings method commits any deferred settings made since the last call to this method.

HRESULT CommitDeferredSettings();

Parameters

None.

Return Values

If the method succeeds, the return value is DS_OK.

If the method fails, the return value may be DSERR_INVALIDPARAM.

Remarks

For additional information about using deferred settings to maximize efficiency, see Deferred Settings.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.
Import Library: Use dsound.lib.


IDirectSound3DListener::GetAllParameters

The IDirectSound3DListener::GetAllParameters method retrieves information that describes the current state of the 3-D world and listener.

HRESULT GetAllParameters(
  LPDS3DLISTENER lpListener
);

Parameters

lpListener
Address of a DS3DLISTENER structure that will contain the current state of the 3-D world and listener.

Return Values

If the method succeeds, the return value is DS_OK.

If the method fails, the return value may be DSERR_INVALIDPARAM.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.
Import Library: Use dsound.lib.

See Also

IDirectSound3DListener::SetAllParameters


IDirectSound3DListener::GetDistanceFactor

The IDirectSound3DListener::GetDistanceFactor method retrieves the current distance factor.

HRESULT GetDistanceFactor(
  LPD3DVALUE lpflDistanceFactor
);

Parameters

lpflDistanceFactor
Address of a variable whose type is D3DVALUE and that will contain the current distance factor value.

Return Values

If the method succeeds, the return value is DS_OK.

If the method fails, the return value may be DSERR_INVALIDPARAM.

Remarks

For additional information about distance factors, see Distance Factor.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.
Import Library: Use dsound.lib.

See Also

IDirectSound3DListener::SetDistanceFactor


IDirectSound3DListener::GetDopplerFactor

The IDirectSound3DListener::GetDopplerFactor method retrieves the current Doppler effect factor.

HRESULT GetDopplerFactor(
  LPD3DVALUE lpflDopplerFactor
);

Parameters

lpflDopplerFactor
Address of a variable whose type is D3DVALUE and that will contain the current Doppler factor value.

Return Values

If the method succeeds, the return value is DS_OK.

If the method fails, the return value may be DSERR_INVALIDPARAM.

Remarks

The Doppler factor has a range of DS3D_MINDOPPLERFACTOR (no Doppler effects) to DS3D_MAXDOPPLERFACTOR (as currently defined, 10 times the Doppler effects found in the real world). The default value is DS3D_DEFAULTDOPPLERFACTOR (1.0). For additional information, see Doppler Factor.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.
Import Library: Use dsound.lib.

See Also

IDirectSound3DListener::SetDopplerFactor


IDirectSound3DListener::GetOrientation

The IDirectSound3DListener::GetOrientation method retrieves the listener's current orientation in vectors: a front vector and a top vector.

HRESULT GetOrientation(
  LPD3DVECTOR lpvOrientFront,
  LPD3DVECTOR lpvOrientTop
);

Parameters

lpvOrientFront
Address of a D3DVECTOR structure that will contain the listener's front orientation vector.
lpvOrientTop
Address of a D3DVECTOR structure that will contain the listener's top orientation vector.

Return Values

If the method succeeds, the return value is DS_OK.

If the method fails, the return value may be DSERR_INVALIDPARAM.

Remarks

The front vector points in the direction of the listener's nose, and the top vector points out the top of the listener's head. By default, the front vector is (0,0,1.0) and the top vector is (0,1.0,0).

The values returned are not necessarily the same as those set by using the IDirectSound3DListener::SetOrientation method. DirectSound adjusts orientation vectors so that they are at right angles and have a magnitude of less than or equal to 1.0.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.
Import Library: Use dsound.lib.

See Also

IDirectSound3DListener::SetOrientation


IDirectSound3DListener::GetPosition

The IDirectSound3DListener::GetPosition method retrieves the listener's current position in distance units. By default, these units are meters, but this can be changed by calling the IDirectSound3DListener::SetDistanceFactor method.

HRESULT GetPosition(
  LPD3DVECTOR lpvPosition
);

Parameters

lpvPosition
Address of a D3DVECTOR structure that will contain the listener's position vector.

Return Values

If the method succeeds, the return value is DS_OK.

If the method fails, the return value may be DSERR_INVALIDPARAM.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.
Import Library: Use dsound.lib.

See Also

IDirectSound3DListener::SetPosition


IDirectSound3DListener::GetRolloffFactor

The IDirectSound3DListener::GetRolloffFactor method retrieves the current rolloff factor.

HRESULT GetRolloffFactor(
  LPD3DVALUE lpflRolloffFactor
);

Parameters

lpflRolloffFactor
Address of a variable whose type is D3DVALUE and that will contain the current rolloff factor value.

Return Values

If the method succeeds, the return value is DS_OK.

If the method fails, the return value may be DSERR_INVALIDPARAM.

Remarks

The rolloff factor has a range of DS3D_MINROLLOFFFACTOR (no rolloff) to DS3D_MAXROLLOFFFACTOR (as currently defined, 10 times the rolloff found in the real world). The default value is DS3D_DEFAULTROLLOFFFACTOR (1.0). For additional information, see Rolloff Factor.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.
Import Library: Use dsound.lib.

See Also

IDirectSound3DListener::SetRolloffFactor


IDirectSound3DListener::GetVelocity

The IDirectSound3DListener::GetVelocity method retrieves the listener's current velocity.

HRESULT GetVelocity(
  LPD3DVECTOR lpvVelocity
);

Parameters

lpvVelocity
Address of a D3DVECTOR structure that will contain the listener's current velocity.

Return Values

If the method succeeds, the return value is DS_OK.

If the method fails, the return value may be DSERR_INVALIDPARAM.

Remarks

Velocity is used only for Doppler effects. It does not actually move the listener. To change the listener's position, use the IDirectSound3DListener::SetPosition method. The default velocity is (0,0,0).

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.
Import Library: Use dsound.lib.

See Also

IDirectSound3DListener::SetVelocity


IDirectSound3DListener::SetAllParameters

The IDirectSound3DListener::SetAllParameters method sets all 3-D listener parameters from a given DS3DLISTENER structure that describes all aspects of the 3-D listener at a moment in time.

HRESULT SetAllParameters(
  LPCDS3DLISTENER lpcListener,
  DWORD dwApply
);

Parameters

lpcListener
Address of a DS3DLISTENER structure that contains information describing all current 3-D listener parameters.
dwApply
Value indicating when the setting should be applied. This value must be one of the following:
DS3D_DEFERRED
Settings are not applied until the application calls the IDirectSound3DListener::CommitDeferredSettings method. This allows the application to change several settings and generate a single recalculation.
DS3D_IMMEDIATE
Settings are applied immediately, causing the system to recalculate the 3-D coordinates for all 3-D sound buffers.

Return Values

If the method succeeds, the return value is DS_OK.

If the method fails, the return value may be DSERR_INVALIDPARAM.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.
Import Library: Use dsound.lib.

See Also

IDirectSound3DListener::GetAllParameters


IDirectSound3DListener::SetDistanceFactor

The IDirectSound3DListener::SetDistanceFactor method sets the current distance factor.

HRESULT SetDistanceFactor(
  D3DVALUE flDistanceFactor,
  DWORD dwApply
);

Parameters

flDistanceFactor
New distance factor.
dwApply
Value indicating when the setting should be applied. This value must be one of the following:
DS3D_DEFERRED
Settings are not applied until the application calls the IDirectSound3DListener::CommitDeferredSettings method. This allows the application to change several settings and generate a single recalculation.
DS3D_IMMEDIATE
Settings are applied immediately, causing the system to recalculate the 3-D coordinates for all 3-D sound buffers.

Return Values

If the method succeeds, the return value is DS_OK.

If the method fails, the return value may be DSERR_INVALIDPARAM.

Remarks

For additional information about distance factors, see Distance Factor.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.
Import Library: Use dsound.lib.

See Also

IDirectSound3DListener::GetDistanceFactor


IDirectSound3DListener::SetDopplerFactor

The IDirectSound3DListener::SetDopplerFactor method sets the current Doppler effect factor.

HRESULT SetDopplerFactor(
  D3DVALUE flDopplerFactor,
  DWORD dwApply
);

Parameters

flDopplerFactor
New Doppler factor value.
dwApply
Value indicating when the setting should be applied. This value must be one of the following:
DS3D_DEFERRED
Settings are not applied until the application calls the IDirectSound3DListener::CommitDeferredSettings method. This allows the application to change several settings and generate a single recalculation.
DS3D_IMMEDIATE
Settings are applied immediately, causing the system to recalculate the 3-D coordinates for all 3-D sound buffers.

Return Values

If the method succeeds, the return value is DS_OK.

If the method fails, the return value may be DSERR_INVALIDPARAM.

Remarks

The Doppler factor has a range of DS3D_MINDOPPLERFACTOR (no Doppler effects) to DS3D_MAXDOPPLERFACTOR (as currently defined, 10 times the Doppler effects found in the real world). The default value is DS3D_DEFAULTDOPPLERFACTOR (1.0). For additional information, see Doppler Factor.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.
Import Library: Use dsound.lib.

See Also

IDirectSound3DListener::GetDopplerFactor


IDirectSound3DListener::SetOrientation

The IDirectSound3DListener::SetOrientation method sets the listener's current orientation in terms of two vectors: a front vector and a top vector.

HRESULT SetOrientation(
  D3DVALUE xFront,
  D3DVALUE yFront,
  D3DVALUE zFront,
  D3DVALUE xTop,
  D3DVALUE yTop,
  D3DVALUE zTop,
  DWORD dwApply
);

Parameters

xFront, yFront, and zFront
Values whose types are D3DVALUE and that represent the coordinates of the front orientation vector.
xTop, yTop, and zTop
Values whose types are D3DVALUE and that represent the coordinates of the top orientation vector.
dwApply
Value indicating when the setting should be applied. This value must be one of the following:
DS3D_DEFERRED
Settings are not applied until the application calls the IDirectSound3DListener::CommitDeferredSettings method. This allows the application to change several settings and generate a single recalculation.
DS3D_IMMEDIATE
Settings are applied immediately, causing the system to recalculate the 3-D coordinates for all 3-D sound buffers.

Return Values

If the method succeeds, the return value is DS_OK.

If the method fails, the return value may be DSERR_INVALIDPARAM.

Remarks

The front vector points in the direction of the listener's nose, and the top vector points out the top of the listener's head. By default, the front vector is (0,0,1.0) and the top vector is (0,1.0,0).

The top vector must be at right angles to the front vector. If necessary, DirectSound adjusts the front vector after setting the top vector.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.
Import Library: Use dsound.lib.

See Also

IDirectSound3DListener::GetOrientation


IDirectSound3DListener::SetPosition

The IDirectSound3DListener::SetPosition method sets the listener's current position, in distance units. By default, these units are meters, but this can be changed by calling the IDirectSound3DListener::SetDistanceFactor method.

HRESULT SetPosition(
  D3DVALUE x,
  D3DVALUE y,
  D3DVALUE z,
  DWORD dwApply
);

Parameters

x, y, and z
Values whose types are D3DVALUE and that represent the coordinates of the listener's new position vector. Note that DirectSound may adjust these values to prevent floating-point overflow.
dwApply
Value indicating when the setting should be applied. This value must be one of the following:
DS3D_DEFERRED
Settings are not applied until the application calls the IDirectSound3DListener::CommitDeferredSettings method. This allows the application to change several settings and generate a single recalculation.
DS3D_IMMEDIATE
Settings are applied immediately, causing the system to recalculate the 3-D coordinates for all 3-D sound buffers.

Return Values

If the method succeeds, the return value is DS_OK.

If the method fails, the return value may be DSERR_INVALIDPARAM.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.
Import Library: Use dsound.lib.

See Also

IDirectSound3DListener::GetPosition


IDirectSound3DListener::SetRolloffFactor

The IDirectSound3DListener::SetRolloffFactor method sets the rolloff factor.

HRESULT SetRolloffFactor(
  D3DVALUE flRolloffFactor,
  DWORD dwApply
);

Parameters

flRolloffFactor
New rolloff factor.
dwApply
Value indicating when the setting should be applied. This value must be one of the following:
DS3D_DEFERRED
Settings are not applied until the application calls the IDirectSound3DListener::CommitDeferredSettings method. This allows the application to change several settings and generate a single recalculation.
DS3D_IMMEDIATE
Settings are applied immediately, causing the system to recalculate the 3-D coordinates for all 3-D sound buffers.

Return Values

If the method succeeds, the return value is DS_OK.

If the method fails, the return value may be DSERR_INVALIDPARAM.

Remarks

The rolloff factor has a range of DS3D_MINROLLOFFFACTOR (no rolloff) to DS3D_MAXROLLOFFFACTOR (as currently defined, 10 times the rolloff found in the real world). The default value is DS3D_DEFAULTROLLOFFFACTOR (1.0). For additional information, see Rolloff Factor.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.
Import Library: Use dsound.lib.

See Also

IDirectSound3DListener::GetRolloffFactor


IDirectSound3DListener::SetVelocity

The IDirectSound3DListener::SetVelocity method sets the listener's velocity.

HRESULT SetVelocity(
  D3DVALUE x,
  D3DVALUE y,
  D3DVALUE z,
  DWORD dwApply
);

Parameters

x, y, and z
Values whose types are D3DVALUE and that represent the coordinates of the listener's new velocity vector. Note that DirectSound may adjust these values to prevent floating-point overflow.
dwApply
Value indicating when the setting should be applied. This value must be one of the following:
DS3D_DEFERRED
Settings are not applied until the application calls the IDirectSound3DListener::CommitDeferredSettings method. This allows the application to change several settings and generate a single recalculation.
DS3D_IMMEDIATE
Settings are applied immediately, causing the system to recalculate the 3-D coordinates for all 3-D sound buffers.

Return Values

If the method succeeds, the return value is DS_OK.

If the method fails, the return value may be DSERR_INVALIDPARAM.

Remarks

Velocity is used only for Doppler effects. It does not actually move the listener. To change the listener's position, use the IDirectSound3DListener::SetPosition method. The default velocity is (0,0,0).

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.
Import Library: Use dsound.lib.

See Also

IDirectSound3DListener::GetVelocity


IDirectSoundBuffer

Applications use the methods of the IDirectSoundBuffer interface to create DirectSoundBuffer objects and set up the environment.

The interface is obtained by using the IDirectSound::CreateSoundBuffer method.

The IDirectSoundBuffer methods can be organized into the following groups:

Information | GetCaps
 | GetFormat
 | GetStatus
 | SetFormat
Memory management | Initialize
 | Restore
Play management | GetCurrentPosition
 | Lock
 | Play
 | SetCurrentPosition
 | Stop
 | Unlock
Sound management | GetFrequency
 | GetPan
 | GetVolume
 | SetFrequency
 | SetPan
 | SetVolume

All COM interfaces inherit the IUnknown interface methods. This interface supports the following three methods:

IUnknown | AddRef
 | QueryInterface
 | Release

The LPDIRECTSOUNDBUFFER type is defined as a pointer to the IDirectSoundBuffer interface:

typedef struct IDirectSoundBuffer    *LPDIRECTSOUNDBUFFER;

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.
Import Library: Use dsound.lib.


IDirectSoundBuffer::GetCaps

The IDirectSoundBuffer::GetCaps method retrieves the capabilities of the DirectSoundBuffer object.

HRESULT GetCaps(
  LPDSBCAPS lpDSBufferCaps
);

Parameters

lpDSBufferCaps
Address of a DSBCAPS structure to contain the capabilities of this sound buffer.

Return Values

If the method succeeds, the return value is DS_OK.

If the method fails, the return value may be DSERR_INVALIDPARAM.

Remarks

The DSBCAPS structure contains similar information to the DSBUFFERDESC structure passed to the IDirectSound::CreateSoundBuffer method, with some additional information. This additional information can include the buffer's location, either in hardware or software, and some cost measures. Examples of cost measures include the time it takes to download to a hardware buffer and the processing overhead required to mix and play the buffer when it is in the system memory.

The flags specified in the dwFlags member of the DSBCAPS structure are the same flags used by the DSBUFFERDESC structure. The only difference is that in the DSBCAPS structure, either DSBCAPS_LOCHARDWARE or DSBCAPS_LOCSOFTWARE will be specified according to the location of the buffer memory. In the DSBUFFERDESC structure, these flags are optional and, depending on which flag is specified, force the buffer to be located in either hardware or software.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.
Import Library: Use dsound.lib.

See Also

DSBCAPS, DSBUFFERDESC, IDirectSoundBuffer, IDirectSound::CreateSoundBuffer


IDirectSoundBuffer::GetCurrentPosition

The IDirectSoundBuffer::GetCurrentPosition method retrieves the current position of the play and write cursors in the sound buffer.

HRESULT GetCurrentPosition(
  LPDWORD lpdwCurrentPlayCursor,
  LPDWORD lpdwCurrentWriteCursor
);

Parameters

lpdwCurrentPlayCursor
Address of a variable to contain the current play position in the DirectSoundBuffer object. This position is an offset within the sound buffer and is specified in bytes. This parameter can be NULL if the current play position is not wanted.
lpdwCurrentWriteCursor
Address of a variable to contain the current write position in the DirectSoundBuffer object. This position is an offset within the sound buffer and is specified in bytes. This parameter can be NULL if the current write position is not wanted.

Return Values

If the method succeeds, the return value is DS_OK.

If the method fails, the return value may be one of the following error values:

DSERR_INVALIDPARAM
DSERR_PRIOLEVELNEEDED

Remarks

The write cursor indicates the position at which it is safe to write new data to the buffer. The write cursor always leads the play cursor, typically by about 15 milliseconds' worth of audio data. For more information, see Current Play and Write Positions.

It is always safe to change data that is behind the position indicated by the lpdwCurrentPlayCursor parameter.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.
Import Library: Use dsound.lib.

See Also

IDirectSoundBuffer, IDirectSoundBuffer::SetCurrentPosition


IDirectSoundBuffer::GetFormat

The IDirectSoundBuffer::GetFormat method retrieves a description of the format of the sound data in the buffer, or the buffer size needed to retrieve the format description.

HRESULT GetFormat(
  LPWAVEFORMATEX lpwfxFormat,
  DWORD dwSizeAllocated,
  LPDWORD lpdwSizeWritten
);

Parameters

lpwfxFormat
Address of the WAVEFORMATEX structure to contain a description of the sound data in the buffer. To retrieve the buffer size needed to contain the format description, specify NULL. In this case the DWORD pointed to by the lpdwSizeWritten parameter will receive the size of the structure needed to receive complete format information.
dwSizeAllocated
Size, in bytes, of the WAVEFORMATEX structure. DirectSound writes, at most, dwSizeAllocated bytes to that pointer; if the WAVEFORMATEX structure requires more memory, it is truncated.
lpdwSizeWritten
Address of a variable to contain the number of bytes written to the WAVEFORMATEX structure. This parameter can be NULL.

Return Values

If the method succeeds, the return value is DS_OK.

If the method fails, the return value may be DSERR_INVALIDPARAM.

Remarks

The WAVEFORMATEX structure can have a variable length that depends on the details of the format. Before retrieving the format description, the application should query the DirectSoundBuffer object for the size of the format by calling this method and specifying NULL for the lpwfxFormat parameter. The size of the structure will be returned in the lpdwSizeWritten parameter. The application can then allocate sufficient memory and call IDirectSoundBuffer::GetFormat again to retrieve the format description.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.
Import Library: Use dsound.lib.

See Also

IDirectSoundBuffer, IDirectSoundBuffer::SetFormat


IDirectSoundBuffer::GetFrequency

The IDirectSoundBuffer::GetFrequency method retrieves the frequency, in samples per second, at which the buffer is playing.

HRESULT GetFrequency(
  LPDWORD lpdwFrequency
);

Parameters

lpdwFrequency
Address of the variable that represents the frequency at which the audio buffer is being played.

Return Values

If the method succeeds, the return value is DS_OK.

If the method fails, the return value may be one of the following error values:

DSERR_CONTROLUNAVAIL
DSERR_INVALIDPARAM
DSERR_PRIOLEVELNEEDED

Remarks

The frequency value will be in the range of DSBFREQUENCY_MIN to DSBFREQUENCY_MAX. These values are currently defined in Dsound.h as 100 and 100,000 respectively.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.
Import Library: Use dsound.lib.

See Also

IDirectSoundBuffer, IDirectSoundBuffer::SetFrequency


IDirectSoundBuffer::GetPan

The IDirectSoundBuffer::GetPan method retrieves a variable that represents the relative volume between the left and right audio channels.

HRESULT GetPan(
  LPLONG lplPan
);

Parameters

lplPan
Address of a variable to contain the relative mix between the left and right speakers.

Return Values

If the method succeeds, the return value is DS_OK.

If the method fails, the return value may be one of the following error values:

DSERR_CONTROLUNAVAIL
DSERR_INVALIDPARAM
DSERR_PRIOLEVELNEEDED

Remarks

The returned value is measured in hundredths of a decibel (dB), in the range of DSBPAN_LEFT to DSBPAN_RIGHT. These values are currently defined in Dsound.h as -10,000 and 10,000 respectively. The value DSBPAN_LEFT means the right channel is attenuated by 100 dB. The value DSBPAN_RIGHT means the left channel is attenuated by 100 dB. The neutral value is DSBPAN_CENTER, defined as zero. This value of 0 in the lplPan parameter means that both channels are at full volume (they are attenuated by 0 decibels). At any setting other than DSBPAN_CENTER, one of the channels is at full volume and the other is attenuated.

A pan of -2173 means that the left channel is at full volume and the right channel is attenuated by 21.73 dB. Similarly, a pan of 870 means that the left channel is attenuated by 8.7 dB and the right channel is at full volume. A pan of DSBPAN_LEFT means that the right channel is silent and the sound is all the way to the left, while a pan of DSBPAN_RIGHT means that the left channel is silent and the sound is all the way to the right.

The pan control acts cumulatively with the volume control.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.
Import Library: Use dsound.lib.

See Also

IDirectSoundBuffer, IDirectSoundBuffer::GetVolume, IDirectSoundBuffer::SetPan, IDirectSoundBuffer::SetVolume


IDirectSoundBuffer::GetStatus

The IDirectSoundBuffer::GetStatus method retrieves the current status of the sound buffer.

HRESULT GetStatus(
  LPDWORD lpdwStatus
);

Parameters

lpdwStatus
Address of a variable to contain the status of the sound buffer. The status can be a combination of the following flags:
DSBSTATUS_BUFFERLOST
The buffer is lost and must be restored before it can be played or locked.
DSBSTATUS_LOOPING
The buffer is being looped. If this value is not set, the buffer will stop when it reaches the end of the sound data. Note that if this value is set, the buffer must also be playing.
DSBSTATUS_PLAYING
The buffer is playing. If this value is not set, the buffer is stopped.

Return Values

If the method succeeds, the return value is DS_OK.

If the method fails, the return value may be DSERR_INVALIDPARAM.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.
Import Library: Use dsound.lib.

See Also

IDirectSoundBuffer


IDirectSoundBuffer::GetVolume

The IDirectSoundBuffer::GetVolume method retrieves the current volume for this sound buffer.

HRESULT GetVolume(
  LPLONG lplVolume
);

Parameters

lplVolume
Address of the variable to contain the volume associated with the specified DirectSound buffer.

Return Values

If the method succeeds, the return value is DS_OK.

If the method fails, the return value may be one of the following error values:

DSERR_CONTROLUNAVAIL
DSERR_INVALIDPARAM
DSERR_PRIOLEVELNEEDED

Remarks

The volume is specified in hundredths of decibels (dB). Allowable values are between DSBVOLUME_MAX (no attenuation) and DSBVOLUME_MIN (silence). These values are currently defined in Dsound.h as 0 and -10,000 respectively. The value DSBVOLUME_MAX represents the original, unadjusted volume of the stream. The value DSBVOLUME_MIN indicates an audio volume attenuated by 100 dB, which, for all practical purposes, is silence. Currently DirectSound does not support amplification.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.
Import Library: Use dsound.lib.

See Also

IDirectSoundBuffer, IDirectSoundBuffer::SetVolume


IDirectSoundBuffer::Initialize

The IDirectSoundBuffer::Initialize method initializes a DirectSoundBuffer object if it has not yet been initialized.

HRESULT Initialize(
  LPDIRECTSOUND lpDirectSound,
  LPCDSBUFFERDESC lpcDSBufferDesc
);

Parameters

lpDirectSound
Address of the DirectSound object associated with this DirectSoundBuffer object.
lpcDSBufferDesc
Address of a DSBUFFERDESC structure that contains the values used to initialize this sound buffer.

Return Values

If the method succeeds, the return value is DS_OK.

If the method fails, the return value may be one of the following error values.

DSERR_INVALIDPARAM
DSERR_ALREADYINITIALIZED

Remarks

Because the IDirectSound::CreateSoundBuffer method calls IDirectSoundBuffer::Initialize internally, it is not needed for the current release of DirectSound. This method is provided for future extensibility.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.
Import Library: Use dsound.lib.

See Also

DSBUFFERDESC, IDirectSound::CreateSoundBuffer, IDirectSoundBuffer


IDirectSoundBuffer::Lock

The IDirectSoundBuffer::Lock method obtains a valid write pointer to the sound buffer's audio data.

HRESULT Lock(
  DWORD dwWriteCursor,
  DWORD dwWriteBytes,
  LPVOID lplpvAudioPtr1,
  LPDWORD lpdwAudioBytes1,
  LPVOID lplpvAudioPtr2,
  LPDWORD lpdwAudioBytes2,
  DWORD dwFlags
);

Parameters

dwWriteCursor
Offset, in bytes, from the start of the buffer to where the lock begins. This parameter is ignored if DSBLOCK_FROMWRITECURSOR is specified in the dwFlags parameter.
dwWriteBytes
Size, in bytes, of the portion of the buffer to lock. Note that the sound buffer is conceptually circular.
lplpvAudioPtr1
Address of a pointer to contain the first block of the sound buffer to be locked.
lpdwAudioBytes1
Address of a variable to contain the number of bytes pointed to by the lplpvAudioPtr1 parameter. If this value is less than the dwWriteBytes parameter, lplpvAudioPtr2 will point to a second block of sound data.
lplpvAudioPtr2
Address of a pointer to contain the second block of the sound buffer to be locked. If the value of this parameter is NULL, the lplpvAudioPtr1 parameter points to the entire locked portion of the sound buffer.
lpdwAudioBytes2
Address of a variable to contain the number of bytes pointed to by the lplpvAudioPtr2 parameter. If lplpvAudioPtr2 is NULL, this value will be 0.
dwFlags
Flags modifying the lock event. The following flags are defined:
DSBLOCK_FROMWRITECURSOR
Locks from the current write position, making a call to IDirectSoundBuffer::GetCurrentPosition unnecessary. If this flag is specified, the dwWriteCursor parameter is ignored.
DSBLOCK_ENTIREBUFFER
Locks the entire buffer. The dwWriteBytes parameter is ignored.

Return Values

If the method succeeds, the return value is DS_OK.

If the method fails, the return value may be one of the following error values:

DSERR_BUFFERLOST
DSERR_INVALIDCALL
DSERR_INVALIDPARAM
DSERR_PRIOLEVELNEEDED

Remarks

This method accepts an offset and a byte count, and returns two write pointers and their associated sizes. Two pointers are required because sound buffers are circular. If the locked bytes do not wrap around the end of the buffer, the second pointer, lplpvAudioBytes2, will be NULL. However, if the bytes do wrap around, then the second pointer will point to the beginning of the buffer.

If the application passes NULL for the lplpvAudioPtr2 and lpdwAudioBytes2 parameters, DirectSound will not lock the wraparound portion of the buffer.

The application should write data to the pointers returned by the IDirectSoundBuffer::Lock method, and then call the IDirectSoundBuffer::Unlock method to release the buffer back to DirectSound. The sound buffer should not be locked for long periods of time; if it is, the play cursor will reach the locked bytes and configuration-dependent audio problems, possibly random noise, will result.

Warning This method returns a write pointer only. The application should not try to read sound data from this pointer; the data might not be valid even though the DirectSoundBuffer object contains valid sound data. For example, if the buffer is located in on-board memory, the pointer might be an address to a temporary buffer in main system memory. When IDirectSoundBuffer::Unlock is called, this temporary buffer will be transferred to the on-board memory.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.
Import Library: Use dsound.lib.

See Also

IDirectSoundBuffer, IDirectSoundBuffer::GetCurrentPosition, IDirectSoundBuffer::Unlock


IDirectSoundBuffer::Play

The IDirectSoundBuffer::Play method causes the sound buffer to play from the current position.

HRESULT Play(
  DWORD dwReserved1,
  DWORD dwReserved2,
  DWORD dwFlags
);

Parameters

dwReserved1
This parameter is reserved. Its value must be 0.
dwReserved2
This parameter is reserved. Its value must be 0.
dwFlags
Flags specifying how to play the buffer. The following flag is defined:
DSBPLAY_LOOPING
Once the end of the audio buffer is reached, play restarts at the beginning of the buffer. Play continues until explicitly stopped. This flag must be set when playing primary sound buffers.

Return Values

If the method succeeds, the return value is DS_OK.

If the method fails, the return value may be one of the following error values:

DSERR_BUFFERLOST
DSERR_INVALIDCALL
DSERR_INVALIDPARAM
DSERR_PRIOLEVELNEEDED

Remarks

This method will cause a secondary sound buffer to be mixed into the primary buffer and sent to the sound device. If this is the first buffer to play, it will implicitly create a primary buffer and start playing that buffer; the application need not explicitly direct the primary buffer to play.

If the buffer specified in the method is already playing, the call to the method will succeed and the buffer will continue to play. However, the flags defined in the most recent call supersede flags defined in previous calls.

Primary buffers must be played with the DSBPLAY_LOOPING flag set.

This method will cause primary sound buffers to start playing to the sound device. If the application is set to the DSSCL_WRITEPRIMARY cooperative level, this will cause the audio data in the primary buffer to be sent to the sound device. However, if the application is set to any other cooperative level, this method will ensure that the primary buffer is playing even when no secondary buffers are playing; in that case, silence will be played. This can reduce processing overhead when sounds are started and stopped in sequence, because the primary buffer will be playing continuously rather than stopping and starting between secondary buffers.

Note Before this method can be called on any sound buffer, the application should call the IDirectSound::SetCooperativeLevel method and specify a cooperative level, typically DSSCL_NORMAL. If IDirectSound::SetCooperativeLevel has not been called, the IDirectSoundBuffer::Play method returns with DS_OK, but no sound will be produced until IDirectSound::SetCooperativeLevel is called.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.
Import Library: Use dsound.lib.

See Also

IDirectSoundBuffer, IDirectSound::SetCooperativeLevel


IDirectSoundBuffer::Restore

The IDirectSoundBuffer::Restore method restores the memory allocation for a lost sound buffer for the specified DirectSoundBuffer object.

HRESULT Restore();

Parameters

None.

Return Values

If the method succeeds, the return value is DS_OK.

If the method fails, the return value may be one of the following error values:

DSERR_BUFFERLOST
DSERR_INVALIDCALL
DSERR_INVALIDPARAM
DSERR_PRIOLEVELNEEDED

Remarks

If the application does not have the input focus, IDirectSoundBuffer::Restore might not succeed. For example, if the application with the input focus has the DSSCL_WRITEPRIMARY cooperative level, no other application will be able to restore its buffers. Similarly, an application with the DSSCL_WRITEPRIMARY cooperative level must have the input focus to restore its primary sound buffer.

Once DirectSound restores the buffer memory, the application must rewrite the buffer with valid sound data. DirectSound cannot restore the contents of the memory, only the memory itself.

The application can receive notification that a buffer is lost when it specifies that buffer in a call to the IDirectSoundBuffer::Lock or IDirectSoundBuffer::Play method. These methods return DSERR_BUFFERLOST to indicate a lost buffer. The IDirectSoundBuffer::GetStatus method can also be used to retrieve the status of the sound buffer and test for the DSBSTATUS_BUFFERLOST flag.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.
Import Library: Use dsound.lib.

See Also

IDirectSoundBuffer, IDirectSoundBuffer::Lock, IDirectSoundBuffer::Play, IDirectSoundBuffer::GetStatus


IDirectSoundBuffer::SetCurrentPosition

The IDirectSoundBuffer::SetCurrentPosition method moves the current play position for secondary sound buffers.

HRESULT SetCurrentPosition(
  DWORD dwNewPosition
);

Parameters

dwNewPosition
New position, in bytes, from the beginning of the buffer that will be used when the sound buffer is played.

Return Values

If the method succeeds, the return value is DS_OK.

If the method fails, the return value may be one of the following error values:

DSERR_INVALIDCALL
DSERR_INVALIDPARAM
DSERR_PRIOLEVELNEEDED

Remarks

This method cannot be called on primary sound buffers.

If the buffer is playing, it will immediately move to the new position and continue. If it is not playing, it will begin from the new position the next time the IDirectSoundBuffer::Play method is called.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.
Import Library: Use dsound.lib.

See Also

IDirectSoundBuffer, IDirectSoundBuffer::GetCurrentPosition, IDirectSoundBuffer::Play


IDirectSoundBuffer::SetFormat

The IDirectSoundBuffer::SetFormat method sets the format of the primary sound buffer for the application. Whenever this application has the input focus, DirectSound will set the primary buffer to the specified format.

HRESULT SetFormat(
  LPCWAVEFORMATEX lpcfxFormat
);

Parameters

lpcfxFormat
Address of a WAVEFORMATEX structure that describes the new format for the primary sound buffer.

Return Values

If the method succeeds, the return value is DS_OK.

If the method fails, the return value may be one of the following error values:

DSERR_BADFORMAT
DSERR_INVALIDCALL
DSERR_INVALIDPARAM
DSERR_OUTOFMEMORY
DSERR_PRIOLEVELNEEDED
DSERR_UNSUPPORTED

Remarks

If this method is called on a primary buffer that is being accessed in write-primary cooperative level, the buffer must be stopped before IDirectSoundBuffer::SetFormat is called. If this method is being called on a primary buffer for a non-write-primary level, DirectSound will implicitly stop the primary buffer, change the format, and restart the primary; the application need not do this explicitly.

This method will succeed even if the hardware does not support the requested format. DirectSound will set the buffer to the closest supported format, then mix the sound in the requested format and convert it before sending it to the primary buffer. To determine whether this is happening, an application can call the IDirectSoundBuffer::GetFormat method for the primary buffer and compare the result with the format that was requested with the SetFormat method.

A call to this method also fails if the calling application has the DSSCL_NORMAL cooperative level.

This method is not valid for secondary sound buffers. If a secondary sound buffer requires a format change, the application should create a new DirectSoundBuffer object using the new format.

DirectSound supports PCM formats; it does not currently support compressed formats.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.
Import Library: Use dsound.lib.

See Also

IDirectSoundBuffer, IDirectSoundBuffer::GetFormat


IDirectSoundBuffer::SetFrequency

The IDirectSoundBuffer::SetFrequency method sets the frequency at which the audio samples are played.

HRESULT SetFrequency(
  DWORD dwFrequency
);

Parameters

dwFrequency
New frequency, in hertz (Hz), at which to play the audio samples. The value must be in the range DSBFREQUENCY_MIN to DSBFREQUENCY_MAX. These values are currently defined in Dsound.h as 100 and 100,000 respectively.

If the value is DSBFREQUENCY_ORIGINAL, the frequency is reset to the default value in the current buffer format. This format is specified in the IDirectSound::CreateSoundBuffer method.

Return Values

If the method succeeds, the return value is DS_OK.

If the method fails, the return value may be one of the following error values:

DSERR_CONTROLUNAVAIL
DSERR_GENERIC
DSERR_INVALIDPARAM
DSERR_PRIOLEVELNEEDED

Remarks

Increasing or decreasing the frequency changes the perceived pitch of the audio data. This method does not affect the format of the buffer.

This method is not valid for primary sound buffers.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.
Import Library: Use dsound.lib.

See Also

IDirectSoundBuffer, IDirectSound::CreateSoundBuffer, IDirectSoundBuffer::GetFrequency, IDirectSoundBuffer::Play, IDirectSoundBuffer::SetFormat


IDirectSoundBuffer::SetPan

The IDirectSoundBuffer::SetPan method specifies the relative volume between the left and right channels.

HRESULT SetPan(
  LONG lPan
);

Parameters

lPan
Relative volume between the left and right channels.

Return Values

If the method succeeds, the return value is DS_OK.

If the method fails, the return value may be one of the following error values:

DSERR_CONTROLUNAVAIL
DSERR_GENERIC
DSERR_INVALIDPARAM
DSERR_PRIOLEVELNEEDED

Remarks

The value in lPan is measured in hundredths of a decibel (dB), in the range of DSBPAN_LEFT to DSBPAN_RIGHT. These values are currently defined in Dsound.h as -10,000 and 10,000 respectively. The value DSBPAN_LEFT means the right channel is attenuated by 100 dB. The value DSBPAN_RIGHT means the left channel is attenuated by 100 dB. The neutral value is DSBPAN_CENTER, defined as zero. This value of 0 in the lplPan parameter means that both channels are at full volume (they are attenuated by 0 decibels). At any setting other than DSBPAN_CENTER, one of the channels is at full volume and the other is attenuated.

A pan of -2173 means that the left channel is at full volume and the right channel is attenuated by 21.73 dB. Similarly, a pan of 870 means that the left channel is attenuated by 8.7 dB and the right channel is at full volume. A pan of DSBPAN_LEFT means that the right channel is silent and the sound is all the way to the left, while a pan of DSBPAN_RIGHT means that the left channel is silent and the sound is all the way to the right.

The pan control acts cumulatively with the volume control.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.
Import Library: Use dsound.lib.

See Also

IDirectSoundBuffer, IDirectSoundBuffer::GetPan, IDirectSoundBuffer::GetVolume, IDirectSoundBuffer::SetVolume


IDirectSoundBuffer::SetVolume

The IDirectSoundBuffer::SetVolume method changes the volume of a sound buffer.

HRESULT SetVolume(
  LONG lVolume
);

Parameters

lVolume
New volume requested for this sound buffer.

Return Values

If the method succeeds, the return value is DS_OK.

If the method fails, the return value may be one of the following error values:

DSERR_CONTROLUNAVAIL
DSERR_GENERIC
DSERR_INVALIDPARAM
DSERR_PRIOLEVELNEEDED

Remarks

The volume is specified in hundredths of decibels (dB). Allowable values are between DSBVOLUME_MAX (no attenuation) and DSBVOLUME_MIN (silence). These values are currently defined in Dsound.h as 0 and -10,000 respectively. The value DSBVOLUME_MAX represents the original, unadjusted volume of the stream. The value DSBVOLUME_MIN indicates an audio volume attenuated by 100 dB, which, for all practical purposes, is silence. Currently DirectSound does not support amplification.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.
Import Library: Use dsound.lib.

See Also

IDirectSoundBuffer, IDirectSoundBuffer::GetPan, IDirectSoundBuffer::GetVolume, IDirectSoundBuffer::SetPan


IDirectSoundBuffer::Stop

The IDirectSoundBuffer::Stop method causes the sound buffer to stop playing.

HRESULT Stop();

Parameters

None.

Return Values

If the method succeeds, the return value is DS_OK.

If the method fails, the return value may be one of the following error values:

DSERR_INVALIDPARAM
DSERR_PRIOLEVELNEEDED

Remarks

For secondary sound buffers, IDirectSoundBuffer::Stop will set the current position of the buffer to the sample that follows the last sample played. This means that if the IDirectSoundBuffer::Play method is called on the buffer, it will continue playing where it left off.

For primary sound buffers, if an application has the DSSCL_WRITEPRIMARY level, this method will stop the buffer and reset the current position to 0 (the beginning of the buffer). This is necessary because the primary buffers on most sound cards can play only from the beginning of the buffer.

However, if IDirectSoundBuffer::Stop is called on a primary buffer and the application has a cooperative level other than DSSCL_WRITEPRIMARY, this method simply reverses the effects of IDirectSoundBuffer::Play. It configures the primary buffer to stop if no secondary buffers are playing. If other buffers are playing in this or other applications, the primary buffer will not actually stop until they are stopped. This method is useful because playing the primary buffer consumes processing overhead even if the buffer is playing sound data with the amplitude of 0 decibels.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.
Import Library: Use dsound.lib.

See Also

IDirectSoundBuffer, IDirectSoundBuffer::Play


IDirectSoundBuffer::Unlock

The IDirectSoundBuffer::Unlock method releases a locked sound buffer.

HRESULT Unlock(
  LPVOID lpvAudioPtr1,
  DWORD dwAudioBytes1,
  LPVOID lpvAudioPtr2,
  DWORD dwAudioBytes2
);

Parameters

lpvAudioPtr1
Address of the value retrieved in the lplpvAudioPtr1 parameter of the IDirectSoundBuffer::Lock method.
dwAudioBytes1
Number of bytes actually written to the lpvAudioPtr1 parameter. It should not exceed the number of bytes returned by the IDirectSoundBuffer::Lock method.
lpvAudioPtr2
Address of the value retrieved in the lplpvAudioPtr2 parameter of the IDirectSoundBuffer::Lock method.
dwAudioBytes2
Number of bytes actually written to the lpvAudioPtr2 parameter. It should not exceed the number of bytes returned by the IDirectSoundBuffer::Lock method.

Return Values

If the method succeeds, the return value is DS_OK.

If the method fails, the return value may be one of the following error values:

DSERR_INVALIDCALL
DSERR_INVALIDPARAM
DSERR_PRIOLEVELNEEDED

Remarks

An application must pass both pointers, lpvAudioPtr1 and lpvAudioPtr2, returned by the IDirectSoundBuffer::Lock method to ensure the correct pairing of IDirectSoundBuffer::Lock and IDirectSoundBuffer::Unlock. The second pointer is needed even if 0 bytes were written to the second pointer.

Applications must pass the number of bytes actually written to the two pointers in the parameters dwAudioBytes1 and dwAudioBytes2.

Make sure the sound buffer does not remain locked for long periods of time.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.
Import Library: Use dsound.lib.

See Also

IDirectSoundBuffer, IDirectSoundBuffer::GetCurrentPosition, IDirectSoundBuffer::Lock


IDirectSoundCapture

The methods of the IDirectSoundCapture interface are used to create sound capture buffers.

The interface is obtained by using the DirectSoundCaptureCreate function.

This reference section gives information on the following methods of the IDirectSoundCapture interface:

Creation | CreateCaptureBuffer
 | Initialize
Capabilities | GetCaps

Like all COM interfaces, the IDirectSoundCapture interface also inherits the IUnknown interface methods. The IUnknown interface supports the following three methods:

IUnknown | AddRef
 | QueryInterface
 | Release

The LPDIRECTSOUNDCAPTURE type is defined as a pointer to the IDirectSoundCapture interface:

typedef struct IDirectSoundCapture    *LPDIRECTSOUNDCAPTURE;

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.
Import Library: Use dsound.lib.


IDirectSoundCapture::CreateCaptureBuffer

The IDirectSoundCapture::CreateCaptureBuffer method creates a capture buffer.

Unlike DirectSound, which can mix several sounds into one sound for output, DirectSoundCapture cannot do the exact opposite and extract various sounds from one input sound. For the first version, DirectSoundCapture allows only one capture buffer to exist at any given time per capture device.

HRESULT CreateCaptureBuffer(
  LPDSCBUFFERDESC lpDSCBufferDesc,
  LPLPDIRECTSOUNDCAPTUREBUFFER lplpDirectSoundCaptureBuffer,
  LPUNKNOWN pUnkOuter
);

Parameters

lpDSCBufferDesc
Pointer to a DSCBUFFERDESC structure containing values for the capture buffer being created.
lplpDirectSoundCaptureBuffer
Address of the IDirectSoundCaptureBuffer interface pointer if successful.
pUnkOuter
Controlling IUnknown of the aggregate. Its value must be NULL.

Return Values

If the method succeeds, the return value is DS_OK.

If the method fails, the return value may be one of the following error values:

DSERR_INVALIDPARAM
DSERR_BADFORMAT
DSERR_GENERIC
DSERR_NODRIVER
DSERR_OUTOFMEMORY
DSERR_UNINITIALIZED

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.
Import Library: Use dsound.lib.


IDirectSoundCapture::GetCaps

The IDirectSoundCapture::GetCaps method obtains the capabilities of the capture device.

HRESULT GetCaps(
  LPDSCCAPS lpDSCCaps
);

Parameters

lpDSCCaps
Pointer to a DSCCAPS structure to be filled by the capture device. When the method is called, the dwSize member must specify the size of the structure in bytes.

Return Values

If the method succeeds, the return value is DS_OK.

If the method fails, the return value may be one of the following error values:

DSERR_INVALIDPARAM
DSERR_UNSUPPORTED
DSERR_NODRIVER
DSERR_OUTOFMEMORY
DSERR_UNINITIALIZED

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.
Import Library: Use dsound.lib.


IDirectSoundCapture::Initialize

When CoCreateInstance is used to create a DirectSoundCapture object, the object must be initialized with the IDirectSoundCapture::Initialize method. Calling this method is not required when the DirectSoundCaptureCreate function is used to create the object.

HRESULT Initialize(
  LPGUID lpGuid
);

Parameters

lpGuid
Address of the GUID specifying the sound driver to which the DirectSoundCapture object binds. Use NULL to select the primary sound driver.

Return Values

If the method succeeds, the return value is DS_OK.

If the method fails, the return value may be one of the following error values:

DSERR_INVALIDPARAM
DSERR_NODRIVER
DSERR_OUTOFMEMORY
DSERR_ALREADYINITIALIZED

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.
Import Library: Use dsound.lib.


IDirectSoundCaptureBuffer

The methods of the IDirectSoundCaptureBuffer interface are used to manipulate sound capture buffers.

The interface is obtained by calling the IDirectSoundCapture::CreateCaptureBuffer method.

The methods of the IDirectSoundCaptureBuffer interface may be grouped as follows:

Initialization | Initialize
Information | GetCaps
 | GetCurrentPosition
 | GetFormat
 | GetStatus
Capture management | Lock
 | Start
 | Stop
 | Unlock

Like all COM interfaces, the IDirectSoundCaptureBuffer interface also inherits the IUnknown interface methods. The IUnknown interface supports the following three methods:

IUnknown | AddRef
 | QueryInterface
 | Release

The LPDIRECTSOUNDCAPTUREBUFFER type is defined as a pointer to the IDirectSoundCaptureBuffer interface:

typedef struct IDirectSoundCaptureBuffer  *LPDIRECTSOUNDCAPTUREBUFFER;

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.
Import Library: Use dsound.lib.


IDirectSoundCaptureBuffer::GetCaps

The IDirectSoundCaptureBuffer::GetCaps method returns the capabilities of the buffer.

HRESULT GetCaps(
  LPDSCBCAPS lpDSCBCaps
);

Parameters

lpDSCBCaps
Pointer to a DSCBCAPS structure to be filled by the capture buffer. On input, the dwSize member must specify the size of the structure in bytes.

Return Values

If the method succeeds, the return value is DS_OK.

If the method fails, the return value may be one of the following error values:

DSERR_INVALIDPARAM
DSERR_UNSUPPORTED
DSERR_OUTOFMEMORY

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.
Import Library: Use dsound.lib.


IDirectSoundCaptureBuffer::GetCurrentPosition

The IDirectSoundCaptureBuffer::GetCurrentPosition method gets the current capture and read positions in the buffer.

The capture position is ahead of the read position. These positions are not always identical due to possible buffering of captured data either on the physical device or in the host. The data after the read position up to and including the capture position is not necessarily valid data.

HRESULT GetCurrentPosition(
  LPDWORD lpdwCapturePosition,
  LPDWORD lpdwReadPosition
);

Parameters

lpdwCapturePosition
Address of a variable to receive the current capture position in the DirectSoundCaptureBuffer object. This position is an offset within the capture buffer and is specified in bytes. The value can be NULL if the caller is not interested in this position information.
lpdwReadPosition
Address of a variable to receive the current position in the DirectSoundCaptureBuffer object at which it is safe to read data. This position is an offset within the capture buffer and is specified in bytes. The value can be NULL if the caller is not interested in this position information.

Return Values

If the method succeeds, the return value is DS_OK.

If the method fails, the return value may be one of the following error values:

DSERR_INVALIDPARAM
DSERR_NODRIVER
DSERR_OUTOFMEMORY

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.
Import Library: Use dsound.lib.


IDirectSoundCaptureBuffer::GetFormat

The IDirectSoundCaptureBuffer::GetFormat method retrieves the current format of the capture buffer.

HRESULT GetFormat(
  LPWAVEFORMATEX lpwfxFormat,
  DWORD dwSizeAllocated,
  LPDWORD lpdwSizeWritten
);

Parameters

lpwfxFormat
Address of the WAVEFORMATEX variable to contain a description of the sound data in the capture buffer. To retrieve the buffer size needed to contain the format description, specify NULL. In this case the DWORD pointed to by the lpdwSizeWritten parameter will receive the size of the structure needed to receive complete format information.
dwSizeAllocated
Size, in bytes, of the WAVEFORMATEX structure. DirectSoundCapture writes, at most, dwSizeAllocated bytes to the structure; if the structure requires more memory, it is truncated.
lpdwSizeWritten
Address of a variable to receive the number of bytes written to the WAVEFORMATEX structure. This parameter can be NULL.

Return Values

If the method succeeds, the return value is DS_OK.

If the method fails, the return value may be DSERR_INVALIDPARAM.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.
Import Library: Use dsound.lib.


IDirectSoundCaptureBuffer::GetStatus

The IDirectSoundCaptureBuffer::GetStatus method retrieves the current status of the capture buffer.

HRESULT GetStatus(
  DWORD *lpdwStatus
);

Parameters

lpdwStatus
Address of a variable to contain the status of the capture buffer. The status can be set to one or more of the following:

DSCBSTATUS_CAPTURING
DSCBSTATUS_LOOPING

Return Values

If the method succeeds, the return value is DS_OK.

If the method fails, the return value may be DSERR_INVALIDPARAM.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.
Import Library: Use dsound.lib.


IDirectSoundCaptureBuffer::Initialize

The IDirectSoundCaptureBuffer::Initialize method initializes a DirectSoundCaptureBuffer object if it has not yet been initialized.

HRESULT Initialize(
  LPDIRECTSOUNDCAPTURE lpDirectSoundCapture,
  LPCDSBUFFERDESC lpcDSBufferDesc
);

Parameters

lpDirectSoundCapture
Address of the DirectSoundCapture object associated with this DirectSoundCaptureBuffer object.
lpcDSBufferDesc
Address of a DSBUFFERDESC structure that contains the values used to initialize this sound buffer.

Return Values

If the method succeeds, the return value is DS_OK.

If the method fails, the return value may be one of the following error values:

DSERR_INVALIDPARAM
DSERR_ALREADYINITIALIZED

Remarks

Because the IDirectSoundCapture::CreateCaptureBuffer method calls the IDirectSoundCaptureBuffer::Initialize method internally, it is not needed for the current release of DirectSound. This method is provided for future extensibility.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.
Import Library: Use dsound.lib.

See Also

DSBUFFERDESC, IDirectSoundCapture::CreateCaptureBuffer


IDirectSoundCaptureBuffer::Lock

The IDirectSoundCaptureBuffer::Lock method locks the buffer. Locking the buffer returns pointers into the buffer, allowing the application to read or write audio data into that memory.

HRESULT Lock(
  DWORD dwReadCursor,
  DWORD dwReadBytes,
  LPVOID *lplpvAudioPtr1,
  LPDWORD lpdwAudioBytes1,
  LPVOID *lplpvAudioPtr2,
  LPDWORD lpdwAudioBytes2,
  DWORD dwFlags
);

Parameters

dwReadCursor
Offset, in bytes, from the start of the buffer to where the lock begins.
dwReadBytes
Size, in bytes, of the portion of the buffer to lock. Note that the capture buffer is conceptually circular.
lplpvAudioPtr1
Address of a pointer to contain the first block of the capture buffer to be locked.
lpdwAudioBytes1
Address of a variable to contain the number of bytes pointed to by the lplpvAudioPtr1 parameter. If this value is less than the dwReadBytes parameter, lplpvAudioPtr2 will point to a second block of data.
lplpvAudioPtr2
Address of a pointer to contain the second block of the capture buffer to be locked. If the value of this parameter is NULL, the lplpvAudioPtr1 parameter points to the entire locked portion of the capture buffer.
lpdwAudioBytes2
Address of a variable to contain the number of bytes pointed to by the lplpvAudioPtr2 parameter. If lplpvAudioPtr2 is NULL, this value will be 0.
dwFlags
Flags modifying the lock event. This value can be zero or the following flag:
DSCBLOCK_ENTIREBUFFER
The dwReadBytes parameter is to be ignored and the entire capture buffer is to be locked.

Return Values

If the method succeeds, the return value is DS_OK.

If the method fails, the return value may be one of the following values:

DSERR_INVALIDPARAM
DSERR_INVALIDCALL

Remarks

This method accepts an offset and a byte count, and returns two read pointers and their associated sizes. Two pointers are required because capture buffers are circular. If the locked bytes do not wrap around the end of the buffer, the second pointer, lplpvAudioBytes2, will be NULL. However, if the bytes do wrap around, then the second pointer will point to the beginning of the buffer.

If the application passes NULL for the lplpvAudioPtr2 and lpdwAudioBytes2 parameters, DirectSoundCapture will not lock the wraparound portion of the buffer.

The application should read data from the pointers returned by the IDirectSoundCaptureBuffer::Lock method and then call the IDirectSoundCaptureBuffer::Unlock method to release the buffer back to DirectSoundCapture. The sound buffer should not be locked for long periods of time; if it is, the capture cursor will reach the locked bytes and configuration-dependent audio problems may result.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.
Import Library: Use dsound.lib.


IDirectSoundCaptureBuffer::Start

The IDirectSoundCaptureBuffer::Start method puts the capture buffer into the capture state and begins capturing data into the buffer. If the capture buffer is already in the capture state then the method has no effect.

HRESULT Start(
  DWORD dwFlags
);

Parameters

dwFlags
Flags that specify the behavior for the capture buffer when capturing sound data. Flags specifying how to play the buffer. The following flag is defined:
DSCBSTART_LOOPING
Once the end of the buffer is reached, capture restarts at the beginning and continues until explicitly stopped.

Return Values

If the method succeeds, the return value is DS_OK.

If the method fails, the return value may be one of the following error values:

DSERR_INVALIDPARAM
DSERR_NODRIVER
DSERR_OUTOFMEMORY

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.
Import Library: Use dsound.lib.


IDirectSoundCaptureBuffer::Stop

The IDirectSoundCaptureBuffer::Stop method puts the capture buffer into the "stop" state and stops capturing data. If the capture buffer is already in the stop state then the method has no effect.

HRESULT Stop();

Parameters

None.

Return Values

If the method succeeds, the return value is DS_OK.

If the method fails, the return value may be one of the following error values:

DSERR_NODRIVER
DSERR_OUTOFMEMORY

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.
Import Library: Use dsound.lib.


IDirectSoundCaptureBuffer::Unlock

The IDirectSoundCaptureBuffer::Unlock method unlocks the buffer.

HRESULT Unlock(
  LPVOID lpvAudioPtr1,
  DWORD dwAudioBytes1,
  LPVOID lpvAudioPtr2,
  DWORD dwAudioBytes2
);

Parameters

lpvAudioPtr1
Address of the value retrieved in the lplpvAudioPtr1 parameter of the IDirectSoundCaptureBuffer::Lock method.
dwAudioBytes1
Number of bytes actually read from the lpvAudioPtr1 parameter. It should not exceed the number of bytes returned by the IDirectSoundCaptureBuffer::Lock method.
lpvAudioPtr2
Address of the value retrieved in the lplpvAudioPtr2 parameter of the IDirectSoundCaptureBuffer::Lock method.
dwAudioBytes2
Number of bytes actually read from the lpvAudioPtr2 parameter. It should not exceed the number of bytes returned by the IDirectSoundCaptureBuffer::Lock method.

Return Values

If the method succeeds, the return value is DS_OK.

If the method fails, the return value may be one of the following values:

DSERR_INVALIDPARAM
DSERR_INVALIDCALL

Remarks

An application must pass both pointers, lpvAudioPtr1 and lpvAudioPtr2, returned by the IDirectSoundCaptureBuffer::Lock method to ensure the correct pairing of IDirectSoundCaptureBuffer::Lock and IDirectSoundCaptureBuffer::Unlock. The second pointer is needed even if zero bytes were written to the second pointer.

Applications must pass the number of bytes actually written to the two pointers in the parameters dwAudioBytes1 and dwAudioBytes2.

Make sure that the capture buffer does not remain locked for long periods of time.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.
Import Library: Use dsound.lib.


IDirectSoundNotify

The IDirectSoundNotify interface provides a mechanism for setting up notification events for a playback or capture buffer.

The interface is obtained by calling the QueryInterface method of an existing interface on a DirectSoundBuffer object. For an example, see Play Buffer Notification.

The interface has the following method:

SetNotificationPositions

Like all COM interfaces, the IDirectSoundNotify interface also inherits the IUnknown interface methods. The IUnknown interface supports the following three methods:

IUnknown | AddRef
 | QueryInterface
 | Release

The LPDIRECTSOUNDNOTIFY type is defined as a pointer to the IDirectSoundNotify interface:

typedef struct IDirectSoundNotify    *LPDIRECTSOUNDNOTIFY;

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.
Import Library: Use dsound.lib.


IDirectSoundNotify::SetNotificationPositions

The IDirectSoundCaptureBuffer::SetNotificationPositions method sets the notification positions. During capture or playback, whenever the position reaches an offset specified in one of the DSBPOSITIONNOTIFY structures in the caller-supplied array, the associated event will be signaled. The position tracked in playback is the current play position; in capture it is the current read position.

HRESULT SetNotificationPositions(
  DWORD cPositionNotifies,
  LPCDSBPOSITIONNOTIFY lpcPositionNotifies
);

Parameters

cPositionNotifies
Number of DSBPOSITIONNOTIFY structures.
lpcPositionNotifies
Pointer to an array of DSBPOSITIONNOTIFY structures.

Return Values

If the method succeeds, the return value is DS_OK.

If the method fails, the return value may be one of the following error values:

DSERR_INVALIDPARAM
DSERR_OUTOFMEMORY

Remarks

The value DSBPN_OFFSETSTOP can be specified in the dwOffset member to tell DirectSound to signal the associated event when the IDirectSoundBuffer::Stop or IDirectSoundCaptureBuffer::Stop method is called or when the end of the buffer has been reached and the playback is not looping. If it is used, this should be the last item in the position-notify array.

If a position-notify array has already been set, calling this function again will replace the previous position-notify array.

The buffer must be stopped when this method is called.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.
Import Library: Use dsound.lib.


IKsPropertySet

The IKsPropertySet interface is part of the WDM KS (Win32 driver model kernel streaming) architecture. It allows driver to provide extended capabilities that can be used without extensions to an API. DirectSound supports this interface for accessing properties of sound drivers.

To retrieve this interface, call the QueryInterface method of any interface on a DirectSound buffer.

The IKsPropertySet interface has the following methods:

IKsPropertySet | Get
 | QuerySupport
 | Set

All COM interfaces inherit the IUnknown interface methods. This interface supports the following three methods:

IUnknown | AddRef
 | QueryInterface
 | Release

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.


IKsPropertySet::Get

The IKsPropertySet::Get method retrieves data for an item in a property set.

HRESULT Get(
  REFGUID rguidPropSet,
  ULONG ulId,
  LPVOID pInstanceData,
  ULONG ulInstanceLength,
  LPVOID pPropertyData,
  ULONG ulDataLength,
  ULONG * pulBytesReturned
);

Parameters

rguidPropSet
Reference to (C++) or address of (C) a GUID representing the property set to be accessed.
ulId
Item within the property set to be accessed. Items are indexed from 0 and are always the same for a given property set GUID.
pInstanceData
Instance data for the get call.
ulInstanceLength
Number of bytes pointed to by pInstanceData.
pPropertyData
Data to set for this item.
ulDataLength
Number of bytes pointed to by pPropertyData
pulBytesReturned
Address of a variable to receive the number of bytes written into pPropertyData.

Return Values

Return values are determined by the designer of the property set.

If the method succeeds, the return value may be S_OK.

If it fails, the method may return E_POINTER.

Remarks

The format of the data in both pInstanceData and pPropertyData is item-specific.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.


IKsPropertySet::QuerySupport

The IKsPropertySet::QuerySupport method determines whether a property in a property set is supported on the port or device.

HRESULT QuerySupport(
  REFGUID rguidPropSet,
  ULONG ulId,
  ULONG* pulTypeSupport
);

Parameters

rguidPropSet
Reference to (C++) or address of (C) a GUID representing the property set to be queried.
ulId
Item within the property set to be accessed. Items are indexed from 0 and are always the same for a given property set.
pulTypeSupport
Address of a variable to receive information about support for the property. If the property or property set does not exist, this is set to 0. Otherwise it may contain one or both of the following flags:
KSPROPERTY_SUPPORT_GET
The property item may be retrieved.
KSPROPERTY_SUPPORT_SET
The property item may be set.

Return Values

Return values are determined by the designer of the property set.

If the method succeeds, the return value may be S_OK. (See Remarks.)

If it fails, the method may return one of the following error values:

E_NOTIMPL (See Remarks.)
E_POINTER

Remarks

Whether it is valid to support some properties within the set but not others depends on the definition of the property set. Consult the hardware manufacturer's specification for the property set of interest.

Some implementations may return S_OK when the property is not supported, and others may return E_NOTIMPL. To be sure that a property is supported you should check both the return value of the method and the value returned in pulTypeSupport.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.


IKsPropertySet::Set

The IKsPropertySet::Set method sets the value of a property in a property set.

HRESULT Set(
  REFGUID rguidPropSet,
  ULONG ulId,
  LPVOID pInstanceData,
  ULONG ulInstanceLength,
  LPVOID pPropertyData,
  ULONG pulDataLength
);

Parameters

rguidPropSet
Reference to (C++) or address of (C) a GUID representing the property set to be accessed.
ulId
Item within the property set to be accessed. Items are indexed from 0 and are always the same for a given property set.
pInstanceData
Instance data for the set call. If there are multiple objects within the port that this operation could act on, the instance data specifies which object should be used. No standard property set items at the DirectMusic API level use instance data; however, vendor-defined extensions are free to use it.
ulInstanceLength
Number of bytes pointed to by pInstanceData
pPropertyData
Property data to set for this item.
ulDataLength
Number of bytes pointed to by pPropertyData

Return Values

Return values are determined by the designer of the property set.

If the method succeeds, the return value may be S_OK.

If it fails, the method may return E_POINTER.

Remarks

The format of the data in both pInstanceData and pPropertyData is item-specific.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.


Functions

This section contains reference information for the following DirectSound and DirectSoundCapture global functions:

  • DirectSoundCaptureCreate
  • DirectSoundCaptureEnumerate
  • DirectSoundCreate
  • DirectSoundEnumerate


DirectSoundCaptureCreate

The DirectSoundCaptureCreate function creates and initializes an object that supports the IDirectSoundCapture interface.

HRESULT WINAPI DirectSoundCaptureCreate(
  LPGUID lpGUID,
  LPDIRECTSOUNDCAPTURE *lplpDSC,
  LPUNKNOWN pUnkOuter
);

Parameters

lpGUID
Address of the GUID that identifies the sound capture device. The value of this parameter must be one of the GUIDs returned by DirectSoundCaptureEnumerate, or NULL for the default device.
lplpDSC
Address of a pointer to a DirectSoundCapture object created in response to this function.
pUnkOuter
Controlling unknown of the aggregate. Its value must be NULL.

Return Values

If the function succeeds, the return value is DS_OK.

If the function fails, the return value may be one of the following error values:

DSERR_INVALIDPARAM
DSERR_NOAGGREGATION
DSERR_OUTOFMEMORY

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.
Import Library: Use dsound.lib.


DirectSoundCaptureEnumerate

The DirectSoundCaptureEnumerate function enumerates the DirectSoundCapture objects installed in the system.

HRESULT WINAPI DirectSoundCaptureEnumerate(
  LPDSENUMCALLBACK lpDSEnumCallback,
  LPVOID lpContext
);

Parameters

lpDSEnumCallback
Address of the DSEnumCallback function that will be called for each DirectSoundCapture object installed in the system.
lpContext
Address of the user-defined context passed to the enumeration callback function every time that function is called.

Return Values

If the function succeeds, the return value is DS_OK.

If the function fails, the return value may be DSERR_INVALIDPARAM.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.
Import Library: Use dsound.lib.


DirectSoundCreate

The DirectSoundCreate function creates and initializes an IDirectSound interface.

HRESULT WINAPI DirectSoundCreate(
  LPGUID lpGuid,
  LPDIRECTSOUND * ppDS,
  LPUNKNOWN  pUnkOuter
);

Parameters

lpGuid
Address of the GUID that identifies the sound device. The value of this parameter must be one of the GUIDs returned by DirectSoundEnumerate, or NULL for the default device.
ppDS
Address of a pointer to a DirectSound object created in response to this function.
pUnkOuter
Controlling unknown of the aggregate. Its value must be NULL.

Return Values

If the function succeeds, the return value is DS_OK.

If the function fails, the return value may be one of the following error values:

DSERR_ALLOCATED
DSERR_INVALIDPARAM
DSERR_NOAGGREGATION
DSERR_NODRIVER
DSERR_OUTOFMEMORY

Remarks

The application must call the IDirectSound::SetCooperativeLevel method immediately after creating a DirectSound object.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.
Import Library: Use dsound.lib.

See Also

IDirectSound::GetCaps, IDirectSound::SetCooperativeLevel


DirectSoundEnumerate

The DirectSoundEnumerate function enumerates the DirectSound drivers installed in the system.

HRESULT WINAPI DirectSoundEnumerate(
  LPDSENUMCALLBACK lpDSEnumCallback,
  LPVOID lpContext
);

Parameters

lpDSEnumCallback
Address of the DSEnumCallback function that will be called for each DirectSound object installed in the system.
lpContext
Address of the user-defined context passed to the enumeration callback function every time that function is called.

Return Values

If the function succeeds, the return value is DS_OK.

If the function fails, the return value may be DSERR_INVALIDPARAM.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.
Import Library: Use dsound.lib.

See Also

DSEnumCallback


Callback Function

This section contains reference information for the following DirectSound callback function.

  • DSEnumCallback


DSEnumCallback

DSEnumCallback is an application-defined callback function that enumerates the DirectSound drivers. The system calls this function in response to the application's previous call to the DirectSoundEnumerate or DirectSoundCaptureEnumerate function.

BOOL CALLBACK DSEnumCallback(
  LPGUID lpGuid,
  LPCSTR lpcstrDescription,
  LPCSTR lpcstrModule,
  LPVOID lpContext
);

Parameters

lpGuid
Address of the GUID that identifies the DirectSound driver being enumerated. This value can be passed to the DirectSoundCreate function to create a DirectSound object for that driver.
lpcstrDescription
Address of a null-terminated string that provides a textual description of the DirectSound device.
lpcstrModule
Address of a null-terminated string that specifies the module name of the DirectSound driver corresponding to this device.
lpContext
Address of application-defined data that is passed to each callback function.

Return Values

Returns TRUE to continue enumerating drivers, or FALSE to stop.

Remarks

The application can save the strings passed in the lpcstrDescription and lpcstrModule parameters by copying them to memory allocated from the heap. The memory used to pass the strings to this callback function is valid only while this callback function is running.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.
Import Library: User-defined.

See Also

DirectSoundEnumerate


Structures

This section contains reference information for the following structures used with DirectSound:

  • DS3DBUFFER
  • DS3DLISTENER
  • DSBCAPS
  • DSBPOSITIONNOTIFY
  • DSBUFFERDESC
  • DSCAPS
  • DSCBCAPS
  • DSCBUFFERDESC
  • DSCCAPS

Note The memory for all DirectX structures must be initialized to zero before use. In addition, all structures that contain a dwSize member must set the member to the size of the structure, in bytes, before use. The following example performs these tasks on a common structure, DSCAPS:

DSCAPS dscaps; // Can't use this yet.

ZeroMemory(&dscaps, sizeof(dscaps));
dscaps.dwSize = sizeof(dscaps);

// Now the structure can be used.
.
.


DS3DBUFFER

The DS3DBUFFER structure contains all information necessary to uniquely describe the location, orientation, and motion of a 3-D sound buffer. This structure is used with the IDirectSound3DBuffer::GetAllParameters and IDirectSound3DBuffer::SetAllParameters methods.

typedef struct {
    DWORD      dwSize;
    D3DVECTOR  vPosition;
    D3DVECTOR  vVelocity;
    DWORD      dwInsideConeAngle;
    DWORD      dwOutsideConeAngle;
    D3DVECTOR  vConeOrientation;
    LONG       lConeOutsideVolume;
    D3DVALUE   flMinDistance;
    D3DVALUE   flMaxDistance;
    DWORD      dwMode;
} DS3DBUFFER, *LPDS3DBUFFER;

typedef const DS3DBUFFER *LPCDS3DBUFFER;

Members

dwSize
Size of the structure, in bytes. This member must be initialized before the structure is used.
vPosition
A D3DVECTOR structure that describes the current position of the 3-D sound buffer.
vVelocity
A D3DVECTOR structure that describes the current velocity of the 3-D sound buffer.
dwInsideConeAngle
The angle of the inside sound projection cone.
dwOutsideConeAngle
The angle of the outside sound projection cone.
vConeOrientation
A D3DVECTOR structure that describes the current orientation of this 3-D buffer's sound projection cone.
lConeOutsideVolume
The cone outside volume.
flMinDistance
The minimum distance.
flMaxDistance
The maximum distance.
dwMode
The 3-D sound processing mode to be set.
DS3DMODE_DISABLE
3-D sound processing is disabled. The sound will appear to originate from the center of the listener's head.
DS3DMODE_HEADRELATIVE
Sound parameters (position, velocity, and orientation) are relative to the listener's parameters. In this mode, the absolute parameters of the sound are updated automatically as the listener's parameters change, so that the relative parameters remain constant.
DS3DMODE_NORMAL
Normal processing. This is the default mode.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.


DS3DLISTENER

The DS3DLISTENER structure contains all information necessary to uniquely describe the 3-D world parameters and position of the listener. This structure is used with the IDirectSound3DListener::GetAllParameters and IDirectSound3DListener::SetAllParameters methods.

typedef struct {
    DWORD      dwSize;
    D3DVECTOR  vPosition;
    D3DVECTOR  vVelocity;
    D3DVECTOR  vOrientFront;
    D3DVECTOR  vOrientTop;
    D3DVALUE   flDistanceFactor;
    D3DVALUE   flRolloffFactor;
    D3DVALUE   flDopplerFactor;
} DS3DLISTENER, *LPDS3DLISTENER;

typedef const DS3DLISTENER *LPCDS3DLISTENER;

Members

dwSize
Size of the structure, in bytes. This member must be initialized before the structure is used.
vPosition, vVelocity, vOrientFront, and vOrientTop
D3DVECTOR structures that describe the listener's position, velocity, front orientation, and top orientation, respectively.
flDistanceFactor, flRolloffFactor, and flDopplerFactor
The current distance, rolloff, and Doppler factors, respectively.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.


DSBCAPS

The DSBCAPS structure specifies the capabilities of a DirectSound buffer object, for use by the IDirectSoundBuffer::GetCaps method.

typedef struct {
    DWORD  dwSize;
    DWORD  dwFlags;
    DWORD  dwBufferBytes;
    DWORD  dwUnlockTransferRate;
    DWORD  dwPlayCpuOverhead;
} DSBCAPS, *LPDSBCAPS;

typedef const DSBCAPS *LPCDSBCAPS;

Members

dwSize
Size of the structure, in bytes. This member must be initialized before the structure is used.
dwFlags
Flags that specify buffer-object capabilities.
DSBCAPS_CTRL3D
The buffer is either a primary buffer or a secondary buffer that uses 3-D control. To create a primary buffer, the dwFlags member of the DSBUFFERDESC structure should include the DSBCAPS_PRIMARYBUFFER flag.
DSBCAPS_CTRLFREQUENCY
The buffer must have frequency control capability.
DSBCAPS_CTRLPAN
The buffer must have pan control capability.
DSBCAPS_CTRLVOLUME
The buffer must have volume control capability.
DSBCAPS_GETCURRENTPOSITION2
Indicates that IDirectSoundBuffer::GetCurrentPosition should use the new behavior of the play cursor. In DirectSound in DirectX 1, the play cursor was significantly ahead of the actual playing sound on emulated sound cards; it was directly behind the write cursor. Now, if the DSBCAPS_GETCURRENTPOSITION2 flag is specified, the application can get a more accurate play position. If this flag is not specified, the old behavior is preserved for compatibility. Note that this flag affects only emulated sound cards; if a DirectSound driver is present, the play cursor is accurate for DirectSound in all versions of DirectX.
DSBCAPS_GLOBALFOCUS
The buffer is a global sound buffer. With this flag set, an application using DirectSound can continue to play its buffers if the user switches focus to another application, even if the new application uses DirectSound. The one exception is if you switch focus to a DirectSound application that uses the DSSCL_EXCLUSIVE or DSSCL_WRITEPRIMARY flag for its cooperative level. In this case, the global sounds from other applications will not be audible.
DSBCAPS_LOCHARDWARE
The buffer is in hardware memory and uses hardware mixing.
DSBCAPS_LOCSOFTWARE
The buffer is in software memory and uses software mixing.
DSBCAPS_MUTE3DATMAXDISTANCE
The sound is reduced to silence at the maximum distance. The buffer will stop playing when the maximum distance is exceeded, so that processor time is not wasted.
DSBCAPS_PRIMARYBUFFER
Indicates that the buffer is a primary sound buffer. If this value is not specified, a secondary sound buffer will be created.
DSBCAPS_STATIC
Indicates that the buffer will be used for static sound data. Typically, these buffers are loaded once and played many times. These buffers are candidates for hardware memory.
DSBCAPS_STICKYFOCUS
Changes the focus behavior of the sound buffer. This flag can be specified in an IDirectSound::CreateSoundBuffer call. With this flag set, an application using DirectSound can continue to play its sticky focus buffers if the user switches to another application not using DirectSound. In this situation, the application's normal buffers are muted, but the sticky focus buffers are still audible. This is useful for nongame applications, such as movie playback (DirectShow™), when the user wants to hear the soundtrack while typing in Microsoft Word or Microsoft® Excel, for example. However, if the user switches to another DirectSound application, all sound buffers, both normal and sticky focus, in the previous application are muted.
dwBufferBytes
Size of this buffer, in bytes.
dwUnlockTransferRate
Specifies the rate, in kilobytes per second, at which data is transferred to the buffer memory when IDirectSoundBuffer::Unlock is called. High-performance applications can use this value to determine the time required for IDirectSoundBuffer::Unlock to execute. For software buffers located in system memory, the rate will be very high because no processing is required. For hardware buffers, the rate might be slower because the buffer might have to be downloaded to the sound card, which might have a limited transfer rate.
dwPlayCpuOverhead
Specifies the processing overhead as a percentage of main processing cycles needed to mix this sound buffer. For hardware buffers, this member will be 0 because the mixing is performed by the sound device. For software buffers, this member depends on the buffer format and the speed of the system processor.

Remarks

The DSBCAPS structure contains information similar to that found in the DSBUFFERDESC structure passed to the IDirectSound::CreateSoundBuffer method, with some additional information. Additional information includes the location of the buffer (hardware or software) and some cost measures (such as the time to download the buffer if located in hardware, and the processing overhead to play the buffer if it is mixed in software).

Note The dwFlags member of the DSBCAPS structure contains the same flags used by the DSBUFFERDESC structure. The only difference is that in the DSBCAPS structure, either the DSBCAPS_LOCHARDWARE or DSBCAPS_LOCSOFTWARE flag will be specified, according to the location of the buffer memory. In the DSBUFFERDESC structure, these flags are optional and are used to force the buffer to be located in either hardware or software.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.

See Also

IDirectSound::CreateSoundBuffer, IDirectSoundBuffer::GetCaps


DSBPOSITIONNOTIFY

The DSBPOSITIONNOTIFY structure is used by the IDirectSoundNotify::SetNotificationPositions method.

typedef struct {
    DWORD   dwOffset;
    HANDLE  hEventNotify;
} DSBPOSITIONNOTIFY, *LPDSBPOSITIONNOTIFY;

typedef const DSBPOSITIONNOTIFY *LPCDSBPOSITIONNOTIFY;

Members

dwOffset
Offset from the beginning of the buffer where the notify event is to be triggered, or DSBPN_OFFSETSTOP.
hEventNotify
Handle to the event to be signaled when the offset has been reached.

Remarks

The DSBPN_OFFSETSTOP value in the dwOffset member causes the event to be signaled when playback or capture stops, either because the end of the buffer has been reached (and playback or capture is not looping) or because the application called the IDirectSoundBuffer::Stop or IDirectSoundCaptureBuffer::Stop method.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.


DSBUFFERDESC

The DSBUFFERDESC structure describes the necessary characteristics of a new DirectSoundBuffer object. This structure is used by the IDirectSound::CreateSoundBuffer method.

typedef struct {
    DWORD           dwSize;
    DWORD           dwFlags;
    DWORD           dwBufferBytes;
    DWORD           dwReserved;
    LPWAVEFORMATEX  lpwfxFormat;
} DSBUFFERDESC, *LPDSBUFFERDESC;

typedef const DSBUFFERDESC *LPCDSBUFFERDESC;

Members

dwSize
Size of the structure, in bytes. This member must be initialized before the structure is used.
dwFlags
Identifies the capabilities to include when creating a new DirectSoundBuffer object. Specify one or more of the following:
DSBCAPS_CTRL3D
The buffer is either a primary buffer or a secondary buffer that uses 3-D control.
DSBCAPS_CTRLALL
The buffer must have all control capabilities.
DSBCAPS_CTRLDEFAULT
The buffer should have default control options. This is the same as specifying the DSBCAPS_CTRLPAN, DSBCAPS_CTRLVOLUME, and DSBCAPS_CTRLFREQUENCY flags.
DSBCAPS_CTRLFREQUENCY
The buffer must have frequency control capability.
DSBCAPS_CTRLPAN
The buffer must have pan control capability.
DSBCAPS_CTRLPOSITIONNOTIFY
The buffer must have position notification capability.
DSBCAPS_CTRLVOLUME
The buffer must have volume control capability.
DSBCAPS_GETCURRENTPOSITION2
Indicates that IDirectSoundBuffer::GetCurrentPosition should use the new behavior of the play cursor. In DirectSound in DirectX 1, the play cursor was significantly ahead of the actual playing sound on emulated sound cards; it was directly behind the write cursor. Now, if the DSBCAPS_GETCURRENTPOSITION2 flag is specified, the application can get a more accurate play position. If this flag is not specified, the old behavior is preserved for compatibility. Note that this flag affects only emulated sound cards; if a DirectSound driver is present, the play cursor is accurate for DirectSound in all versions of DirectX.
DSBCAPS_GLOBALFOCUS
The buffer is a global sound buffer. With this flag set, an application using DirectSound can continue to play its buffers if the user switches focus to another application, even if the new application uses DirectSound. The one exception is if you switch focus to a DirectSound application that uses the DSSCL_EXCLUSIVE or DSSCL_WRITEPRIMARY flag for its cooperative level. In this case, the global sounds from other applications will not be audible.
DSBCAPS_LOCHARDWARE
Forces the buffer to use hardware mixing, even if DSBCAPS_STATIC is not specified. If the device does not support hardware mixing or if the required hardware memory is not available, the call to the IDirectSound::CreateSoundBuffer method will fail. The application must ensure that a mixing channel will be available for this buffer; this condition is not guaranteed.
DSBCAPS_LOCSOFTWARE
Forces the buffer to be stored in software memory and use software mixing, even if DSBCAPS_STATIC is specified and hardware resources are available.
DSBCAPS_MUTE3DATMAXDISTANCE
The sound is to be reduced to silence at the maximum distance. The buffer will stop playing when the maximum distance is exceeded, so that processor time is not wasted.
DSBCAPS_PRIMARYBUFFER
Indicates that the buffer is a primary sound buffer. If this value is not specified, a secondary sound buffer will be created.
DSBCAPS_STATIC
Indicates that the buffer will be used for static sound data. Typically, these buffers are loaded once and played many times. These buffers are candidates for hardware memory.
DSBCAPS_STICKYFOCUS
Changes the focus behavior of the sound buffer. This flag can be specified in an IDirectSound::CreateSoundBuffer call. With this flag set, an application using DirectSound can continue to play its sticky focus buffers if the user switches to another application not using DirectSound. In this situation, the application's normal buffers are muted, but the sticky focus buffers are still audible. This is useful for nongame applications, such as movie playback (DirectShow), when the user wants to hear the soundtrack while typing in Microsoft Word or Microsoft Excel, for example. However, if the user switches to another DirectSound application, all sound buffers, both normal and sticky focus, in the previous application are muted.
dwBufferBytes
Size of the new buffer, in bytes. This value must be 0 when creating primary buffers. For secondary buffers, the minimum and maximum sizes allowed are specified by DSBSIZE_MIN and DSBSIZE_MAX, defined in Dsound.h.
dwReserved
This value is reserved. Do not use.
lpwfxFormat
Address of a structure specifying the waveform format for the buffer. This value must be NULL for primary buffers. The application can use IDirectSoundBuffer::SetFormat to set the format of the primary buffer.

Remarks

The DSBCAPS_LOCHARDWARE and DSBCAPS_LOCSOFTWARE flags used in the dwFlags member are optional and mutually exclusive. DSBCAPS_LOCHARDWARE forces the buffer to reside in memory located in the sound card. DSBCAPS_LOCSOFTWARE forces the buffer to reside in main system memory, if possible.

These flags are also defined for the dwFlags member of the DSBCAPS structure, and when used there, the specified flag indicates the actual location of the DirectSoundBuffer object.

When creating a primary buffer, applications must set the dwBufferBytes member to 0; DirectSound will determine the optimal buffer size for the particular sound device in use. To determine the size of a created primary buffer, call IDirectSoundBuffer::GetCaps.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.

See Also

IDirectSound::CreateSoundBuffer


DSCAPS

The DSCAPS structure specifies the capabilities of a DirectSound device for use by the IDirectSound::GetCaps method.

typedef {
    DWORD  dwSize;
    DWORD  dwFlags;
    DWORD  dwMinSecondarySampleRate;
    DWORD  dwMaxSecondarySampleRate;
    DWORD  dwPrimaryBuffers;
    DWORD  dwMaxHwMixingAllBuffers;
    DWORD  dwMaxHwMixingStaticBuffers;
    DWORD  dwMaxHwMixingStreamingBuffers;
    DWORD  dwFreeHwMixingAllBuffers;
    DWORD  dwFreeHwMixingStaticBuffers;
    DWORD  dwFreeHwMixingStreamingBuffers;
    DWORD  dwMaxHw3DAllBuffers;
    DWORD  dwMaxHw3DStaticBuffers;
    DWORD  dwMaxHw3DStreamingBuffers;
    DWORD  dwFreeHw3DAllBuffers;
    DWORD  dwFreeHw3DStaticBuffers;
    DWORD  dwFreeHw3DStreamingBuffers;
    DWORD  dwTotalHwMemBytes;
    DWORD  dwFreeHwMemBytes;
    DWORD  dwMaxContigFreeHwMemBytes;
    DWORD  dwUnlockTransferRateHwBuffers;
    DWORD  dwPlayCpuOverheadSwBuffers;
    DWORD  dwReserved1;
    DWORD  dwReserved2;
} DSCAPS, *LPDSCAPS;

typedef const DSCAPS *LPCDSCAPS;

Members

dwSize
Size of the structure, in bytes. This member must be initialized before the structure is used.
dwFlags
Specifies device capabilities. Can be one or more of the following:
DSCAPS_CERTIFIED
This driver has been tested and certified by Microsoft.
DSCAPS_CONTINUOUSRATE
The device supports all sample rates between the dwMinSecondarySampleRate and dwMaxSecondarySampleRate member values. Typically, this means that the actual output rate will be within +/- 10 hertz (Hz) of the requested frequency.
DSCAPS_EMULDRIVER
The device does not have a DirectSound driver installed, so it is being emulated through the waveform-audio functions. Performance degradation should be expected.
DSCAPS_PRIMARY16BIT
The device supports primary sound buffers with 16-bit samples.
DSCAPS_PRIMARY8BIT
The device supports primary buffers with 8-bit samples.
DSCAPS_PRIMARYMONO
The device supports monophonic primary buffers.
DSCAPS_PRIMARYSTEREO
The device supports stereo primary buffers.
DSCAPS_SECONDARY16BIT
The device supports hardware-mixed secondary sound buffers with 16-bit samples.
DSCAPS_SECONDARY8BIT
The device supports hardware-mixed secondary buffers with 8-bit samples.
DSCAPS_SECONDARYMONO
The device supports hardware-mixed monophonic secondary buffers.
DSCAPS_SECONDARYSTEREO
The device supports hardware-mixed stereo secondary buffers.
dwMinSecondarySampleRate and dwMaxSecondarySampleRate
Minimum and maximum sample rate specifications that are supported by this device's hardware secondary sound buffers.
dwPrimaryBuffers
Number of primary buffers supported. This value will always be 1.
dwMaxHwMixingAllBuffers
Specifies the total number of buffers that can be mixed in hardware. This member can be less than the sum of dwMaxHwMixingStaticBuffers and dwMaxHwMixingStreamingBuffers. Resource tradeoffs frequently occur.
dwMaxHwMixingStaticBuffers
Specifies the maximum number of static sound buffers. See
dwMaxHwMixingStreamingBuffers
Specifies the maximum number of streaming sound buffers.
dwFreeHwMixingAllBuffers, dwFreeHwMixingStaticBuffers, and dwFreeHwMixingStreamingBuffers
Description of the free, or unallocated, hardware mixing capabilities of the device. An application can use these values to determine whether hardware resources are available for allocation to a secondary sound buffer. Also, by comparing these values to the members that specify maximum mixing capabilities, the resources that are already allocated can be determined. See Remarks.
dwMaxHw3DAllBuffers, dwMaxHw3DStaticBuffers, and dwMaxHw3DStreamingBuffers
Description of the hardware 3-D positional capabilities of the device.
dwFreeHw3DAllBuffers, dwFreeHw3DStaticBuffers, and dwFreeHw3DStreamingBuffers
Description of the free, or unallocated, hardware 3-D positional capabilities of the device. See Remarks.
dwTotalHwMemBytes
Size, in bytes, of the amount of memory on the sound card that stores static sound buffers.
dwFreeHwMemBytes
Size, in bytes, of the free memory on the sound card.
dwMaxContigFreeHwMemBytes
Size, in bytes, of the largest contiguous block of free memory on the sound card.
dwUnlockTransferRateHwBuffers
Description of the rate, in kilobytes per second, at which data can be transferred to hardware static sound buffers. This and the number of bytes transferred determines the duration of a call to the IDirectSoundBuffer::Unlock method.
dwPlayCpuOverheadSwBuffers
Description of the processing overhead, as a percentage of the central processing unit, needed to mix software buffers (those located in main system memory). This varies according to the bus type, the processor type, and the clock speed.

The unlock transfer rate for software buffers is 0 because the data need not be transferred anywhere. Similarly, the play processing overhead for hardware buffers is 0 because the mixing is done by the sound device.

dwReserved1 and dwReserved2
Reserved for future use.

Remarks

Some audio cards may be unable to report accurately the number of available or free hardware buffers. This can happen, for example, when the card can play more sounds at lower sampling rates than at higher rates. In general, a non-zero value in any of the members relating to number of free hardware buffers signifies that at least one hardware resource of the appropriate type is available.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.

See Also

IDirectSound::GetCaps


DSCBCAPS

The DSCBCAPS structure is used by the IDirectSoundCaptureBuffer::GetCaps method.

typedef struct {
    DWORD  dwSize;
    DWORD  dwFlags;
    DWORD  dwBufferBytes;
    DWORD  dwReserved;
} DSCBCAPS, *LPDSCBCAPS;

typedef const DSCBCAPS *LPCDSCBCAPS;

Members

dwSize
Size of the structure, in bytes. This member must be initialized before the structure is used.
dwFlags
Specifies device capabilities. Can be zero or the following flag:
DSCBCAPS_WAVEMAPPED
The Win32 wave mapper will be used for formats not supported by the device.
dwBufferBytes
The size, in bytes, of the capture buffer.
dwReserved
Reserved for future use.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.


DSCBUFFERDESC

The DSCBUFFERDESC structure is used by the IDirectSoundCapture::CreateCaptureBuffer method.

typedef struct {
    DWORD           dwSize;
    DWORD           dwFlags;
    DWORD           dwBufferBytes;
    DWORD           dwReserved;
    LPWAVEFORMATEX  lpwfxFormat;
} DSCBUFFERDESC, *LPDSCBUFFERDESC;

typedef const DSCBUFFERDESC *LPCDSCBUFFERDESC;

Members

dwSize
Size of the structure, in bytes. This member must be initialized before the structure is used.
dwFlags
Specifies device capabilities. Can be zero or the following flag:
DSCBCAPS_WAVEMAPPED
The Win32 wave mapper will be used for formats not supported by the device.
dwBufferBytes
Size of capture buffer to create, in bytes.
dwReserved
Reserved for future use.
lpwfxFormat
Pointer to a WAVEFORMATEX structure containing the format in which to capture the data.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.


DSCCAPS

The DSCCAPS structure is used by the IDirectSoundCapture::GetCaps method.

typedef struct {
    DWORD  dwSize;
    DWORD  dwFlags;
    DWORD  dwFormats;
    DWORD  dwChannels;
} DSCCAPS, *LPDSCCAPS;

typedef const DSCCAPS *LPCDSCCAPS;

Members

dwSize
Size of the structure, in bytes. This member must be initialized before the structure is used.
dwFlags
Specifies device capabilities. Can be 0 or the following flag:
DSCCAPS_EMULDRIVER
There is no DirectSoundCapture driver for the device, so the standard wave audio functions are being used.
dwFormats
Standard formats that are supported. These are equivalent to the values in the WAVEINCAPS structure used in the Win32 waveform audio functions, and are reproduced here for convenience.
Value | Meaning
WAVE_FORMAT_1M08 | 11.025 kHz, mono, 8-bit
WAVE_FORMAT_1M16 | 11.025 kHz, mono, 16-bit
WAVE_FORMAT_1S08 | 11.025 kHz, stereo, 8-bit
WAVE_FORMAT_1S16 | 11.025 kHz, stereo, 16-bit
WAVE_FORMAT_2M08 | 22.05 kHz, mono, 8-bit
WAVE_FORMAT_2M16 | 22.05 kHz, mono, 16-bit
WAVE_FORMAT_2S08 | 22.05 kHz, stereo, 8-bit
WAVE_FORMAT_2S16 | 22.05 kHz, stereo, 16-bit
WAVE_FORMAT_4M08 | 44.1 kHz, mono, 8-bit
WAVE_FORMAT_4M16 | 44.1 kHz, mono, 16-bit
WAVE_FORMAT_4S08 | 44.1 kHz, stereo, 8-bit
WAVE_FORMAT_4S16 | 44.1 kHz, stereo, 16-bit

dwChannels
Number specifying the number of channels supported by the device, where 1 is mono, 2 is stereo, and so on.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsound.h.


Return Values

Errors are represented by negative values and cannot be combined. This table lists the values that can be returned by all IDirectSound and IDirectSoundBuffer methods. For a list of the error codes each method can return, see the individual method descriptions.

DS_OK
The request completed successfully.
DSERR_ALLOCATED
The request failed because resources, such as a priority level, were already in use by another caller.
DSERR_ALREADYINITIALIZED
The object is already initialized.
DSERR_BADFORMAT
The specified wave format is not supported.
DSERR_BUFFERLOST
The buffer memory has been lost and must be restored.
DSERR_CONTROLUNAVAIL
The buffer control (volume, pan, and so on) requested by the caller is not available.
DSERR_GENERIC
An undetermined error occurred inside the DirectSound subsystem.
DSERR_INVALIDCALL
This function is not valid for the current state of this object.
DSERR_INVALIDPARAM
An invalid parameter was passed to the returning function.
DSERR_NOAGGREGATION
The object does not support aggregation.
DSERR_NODRIVER
No sound driver is available for use.
DSERR_NOINTERFACE
The requested COM interface is not available.
DSERR_OTHERAPPHASPRIO
Another application has a higher priority level, preventing this call from succeeding
DSERR_OUTOFMEMORY
The DirectSound subsystem could not allocate sufficient memory to complete the caller's request.
DSERR_PRIOLEVELNEEDED
The caller does not have the priority level required for the function to succeed.
DSERR_UNINITIALIZED
The IDirectSound::Initialize method has not been called or has not been called successfully before other methods were called.
DSERR_UNSUPPORTED
The function called is not supported at this time.


DirectSound Samples

This section provides summaries of the applications in the DirectX SDK that are primarily intended to demonstrate the DirectSound component. The following sample programs demonstrate the use and capabilities of DirectSound:

  • DS3DView Sample
  • DSPStream Sample
  • DSShow Sample
  • DSShow3D Sample
  • DSStream Sample
  • FDFilter Sample

Although DirectX samples include Microsoft® Visual C++® project workspace files, you might need to verify other settings in your development environment to ensure that the samples compile properly. For more information, see Compiling DirectX Samples and Other DirectX Applications.


DS3DView Sample

Description

The DS3DView program demonstrates the integration of 3-D graphics and 3-D sound, using Direct3D and DirectSound.

Path

Source: (SDK root)\Samples\Multimedia\DSound\Src\DS3DView

Executable: (SDK root)\Samples\Multimedia\DSound\Bin

User's Guide

To display an object, choose Add 3D Visual from the File menu. More than one object can be added. You can find .x files containing the definitions of 3-D objects in the Media directories for the D3DIM and D3DRM samples.

Attach a sound to an object by clicking on the object, selecting Attach Sound from the Sound menu, and then loading a wave file. You can attach one sound to each object. To select a sound after it is loaded, click on the object to which the sound is attached.

After you select a sound, you can hear it by choosing Play Sound Once or Play Sound Looping from the Sound menu. To hear some of the effects of DirectSound, try selecting Orbit Selected Object or Bullet Selected Object from the Motion menu. You can vary the speed of the object by changing the value in the dialog box that appears.

You can experiment with the 3-D properties of a sound by selecting it and then choosing Selected Sound Properties from the Sound menu. Choosing Global Properties allows you to modify parameters of the listener object.

Programming Notes

In addition to 3-D retained mode techniques, this program illustrates how to load wave files, attach them to objects in a 3-D environment, and change the parameters of 3-D sound buffers.


DSPStream Sample

Description

The DSPStream sample is similar to DSStream, except that it streams wave data directly to the primary buffer.

Path

Source: (SDK root)\Samples\Multimedia\DSound\Src\DSPStrm

Executable: (SDK root)\Samples\Multimedia\DSound\Bin

User's Guide

Load a single wave file by selecting Open from the File menu. Play the sound once by choosing Play! from the main menu or by clicking the Play button. Halt the playback by choosing Stop! from the main menu or by clicking the Stop button.

To make the program play the sound continuously, select the checkbox labeled Looped.

The program displays controls for panning the sound and adjusting the volume. If DEBUG was defined during compilation, the scrolling display shows a record of the write position (wp), play position (pp), and next write (nw), along with the percentage of the wave file that has been played. The progress through the file is also shown by a slider.

You can make DSStream enumerate the sound drivers when it is next started. To do this, select Enumerate Drivers from the Options menu.

Programming Notes

The program demonstrates how to stream a wave file directly into the primary buffer. The buffer's format is changed to match that of the wave data.


DSShow Sample

Description

This sample application demonstrates many of the capabilities of DirectSound 2-D buffers.

Path

Source: (SDK root)\Samples\Multimedia\DSound\Src\DSShow

Executable: (SDK root)\Samples\Multimedia\DSound\Bin

User's Guide

The title bar displays information about the hardware mixing capabilities of your sound card: the number of free hardware mixing channels and hardware memory, if you have an ISA card. If both of those numbers are 0, your card does not have hardware mixing.

Choose Open from the File menu to load one or more short wave files. If you try to open a file that is very large, you will run out of system memory because all sounds are loaded into static buffers.

You can also load files by dragging them onto the program's icon, or from the command line using the following syntax:

DSShow [/PLAY [/LOOP]] [file] [file] ...

Specifying /PLAY causes any specified files to be played as they're opened. Adding /LOOP causes them to loop as well, but /LOOP without /PLAY means nothing. File names can be enclosed in quotation marks.

For each sound, DSShow displays buffer information and a group of controls. The file name is displayed at the top. The next line states whether the buffer is mixed in software (SW) or hardware (HW), and whether the buffer is playing or stopped. DSShow will put buffers in hardware whenever possible. On the next two lines, the positions of the current play and write cursors are displayed.

You can play, stop, and remove the sound, set the frequency, and adjust the master volume. The Pan slider also controls the left-right volume indicators, which cannot be moved separately. If you want the sound to play continuously, check the Looped checkbox. To remove the sound file, select the Close button.

The Output Type choice on the Options menu lets you change the format of the primary buffer, and Check Latency brings up a dialog box that you can use to test how rapidly a sound starts and stops after it is triggered. You can tell the DSShow application to enumerate all available sound drivers the next time it starts up by selecting Enumerate Drivers.

Programming Notes

The application demonstrates device enumeration, changing the format of the primary buffer, and changing parameters of secondary buffers. It uses static sound buffers.


DSShow3D Sample

Description

DSShow3D allows you to modify the parameters of 3-D sound buffers and the 3-D listener.

Path

Source: (SDK root)\Samples\Multimedia\DSound\Src\DSShow3D

Executable: (SDK root)\Samples\Multimedia\DSound\Bin

User's Guide

Using Open from the File menu, you can open one or more short sound files and play them at the same time.

You can also load files by dragging them onto the program's icon, or from the command line using the following syntax:

DSShow3D [/PLAY [/LOOP]] [file] [file] ...

Specifying /PLAY causes any specified files to be played as they're opened. Adding /LOOP causes them to loop as well, but /LOOP without /PLAY means nothing. File names can be enclosed in quotation marks.

For each wave file that you open, DSShow3D displays a group of buffer controls in a client window. The listener settings, which apply to all open sounds, are shown in a separate window.

To play the sound, click the Play button in its window. To play it continuously, press the Looped button. You can create a duplicate of the sound buffer by choosing Duplicate! from the client window's menu.

To close a buffer, choose Close from the buffer's File menu, or simply close the window.

You can change the format of the primary buffer by choosing Output Format from the Options menu in the main window. On the same menu, Settings lets you choose preferences that will take effect next time the application is started.

Changes made in the 3D Listener Object Settings window do not take effect until you click the Commit button.

Programming Notes

The source code demonstrates creation and duplication of 3-D sound buffers, changing parameters of sound buffers, changing listener parameters, changing the primary format, and using notification positions. The program uses static sound buffers.


DSStream Sample

Description

The DSStream sample illustrates the use of streaming sound buffers. It works best with sounds that are more than 2 seconds in length.

Path

Source: (SDK root)\Samples\Multimedia\DSound\Src\DSStream

Executable: (SDK root)\Samples\Multimedia\DSound\Bin

User's Guide

Load a single wave file by selecting Open from the File menu. Play the sound once by choosing Play! from the main menu or by clicking the Play button. Halt the playback by choosing Stop! from the main menu or by clicking the Stop button.

To make the program play the sound continuously, select the checkbox labeled Looped.

The DSStream program displays controls for panning the sound, decreasing the volume, and changing the frequency.

You can make DSStream enumerate the sound drivers when it is next started. To do this, select Enumerate Drivers from the Options menu.

Programming Notes

The program demonstrates how to stream a lengthy wave file into a secondary buffer, using notification positions and a separate thread to handle notifications.


FDFilter Sample

Description

The FDFilter program demonstrates how to use DirectSound to implement full duplex audio and a filter.

A microphone or other audio input is required.

Path

Source: (SDK root)\Samples\Multimedia\DSound\Src\FDfilter

Executable: (SDK root)\Samples\Multimedia\DSound\Bin

User's Guide

When you start the program, it presents you with a dialog box that contains pull-down lists of the sound input and output devices attached to your computer. Select the appropriate devices. Usually the defaults are the most appropriate.

You next see lists of sampling rates for the input and output buffers. Select an output format, then an input format. You can change these formats later from the Settings menu.

The program then shows a dialog box that enables you to select the filter. The available options are None (pass-through), which just plays back the input sound as is, or Gargle, which distorts the input sound into a gargling noise. Click Enable to begin capturing and playing sound.

Programming Notes

FDFilter is designed to be a simple example of how one might go about implementing full-duplex audio. It is designed primarily to show application developers the proper sequence of steps for dealing with the sound devices installed on the system for using full-duplex audio with waveIn as an input source and DirectSound as the output device.

For more information, see the Readme.txt file in the Fdfilter directory.


DirectMusic

This documentation covers the following Microsoft® DirectMusic™ application programming interface (API) topics:

  • About DirectMusic
  • Why Use DirectMusic?
  • DirectMusic Architecture
  • DirectMusic Essentials
  • DirectMusic Tutorials
  • DirectMusic Reference
  • DirectMusic Samples


About DirectMusic

DirectMusic™ is the musical component of the DirectX® application programming interface (API). Unlike the DirectSound® API, which is for the capture and playback of digital sound samples, DirectMusic works with message-based musical data which is converted to wave samples either in hardware or in a software synthesizer. The default software implementation uses the Microsoft® Software Synthesizer to create wave samples that are then streamed to DirectSound. Instrument voices are synthesized from samples according to the downloadable sounds (DLS) standard.

As well as supporting input in Musical Instrument Digital Interface (MIDI) format, DirectMusic can compose music at run time. This music is not algorithmically generated but is based on elements authored by a human composer. (The Microsoft authoring tool, DirectMusic Producer, is documented separately.) It is performed with variations and can respond dynamically to program events.

Like other components of DirectX, DirectMusic provides an API based on the Component Object Model (COM).

DirectMusic delivers full functionality on Windows® 95, Windows 98, and Windows 2000.


Why Use DirectMusic?

The DirectMusic API addresses fundamental requirements for delivering music on the platform:

  • Consistent playback experience. By using downloadable sounds, an application can count on musical instruments sounding the same on all machines, and can perform with instruments of its own design.
  • Jitter-free timing. Playback of MIDI-generated music has timing accuracy within two milliseconds.
  • Extensibility. DirectMusic does not restrict vendors to a base-level feature set.

In addition, DirectMusic provides important features for easing program development and for enriching the user's experience:

  • Generic mechanism for loading and performing musical segments, regardless of the performance technology. DirectMusic equally supports standard MIDI files, authored music segments, and third-party technology.
  • Multiple performances. More than one piece of music can be played at once, with completely separate timing, instrument sets, and so on.
  • More than 16 MIDI channels. By mapping performance channels to channel groups, DirectMusic breaks through the 16-channel limitation and makes it possible for any number of voices to be played simultaneously, up to the limits of the synthesizer.
  • Automated management of DLS instruments.
  • Dynamic and interactive playback. In combination with DirectMusic Producer, the DirectMusic performance engine can be used to create dynamic musical soundtracks based on stored compositional material. The music does not assume its final form until it is about to be played, and can respond to program events.
  • Synchronization of all music playback through the use of a master clock.


DirectMusic Architecture

This section introduces the components of DirectMusic. The following topics are discussed:

  • Core and Performance Layers
  • Overview of DirectMusic Objects and Interfaces
  • Overview of DirectMusic Data Flow
  • DirectMusic Messages
  • Downloadable Sounds
  • Microsoft Software Synthesizer

For information about how to implement these components in your application, see DirectMusic Essentials.


Core and Performance Layers

The DirectMusic core layer manages timing and ports and provides services for managing DLS collections. It supports buffered, timestamped MIDI input and output. By default DirectMusic itself sequences the MIDI data.

The core layer also includes the Microsoft Software Synthesizer, which uses DLS to synthesize wave output from the sequenced MIDI data.

The DirectMusic performance layer is responsible for the higher-level aspects of music playback, including the loading and playback of MIDI files and the composition of music based on elements authored in DirectMusic Producer or a similar program.

The interfaces and related API elements for the core layer are found in Dmusicc.h, and those for the performance layer are in Dmusici.h.


Overview of DirectMusic Objects and Interfaces

In DirectMusic it is helpful to make a distinction between objects and their COM interfaces, because many objects have multiple interfaces. The object that supports the IDirectMusicCollection interface, for example, also supports the standard COM IPersistStream interface as well as IDirectMusicObject.

In this documentation, DirectMusic objects are referred to by the name of their principal or unique interface, but without the initial "I"; thus the object represented by IDirectMusicCollection is called the DirectMusicCollection object. Objects may also be referred to by short names such as collection, performance, segment, and track.

Interface pointers are often used as pointers to their objects so that these objects can be accessed through the methods of other interfaces. In fact, one interface, IDirectMusicDownloadedInstrument, has no unique methods of its own and is used only as a parameter to the methods of other interfaces.

DirectMusic consists of many COM objects and interfaces which are related to one another in rather complex ways. However, they may be divided into categories according to their broad functionality, as follows:

  • Core Objects and Interfaces
  • Loader Objects and Interfaces
  • Instrument Objects and Interfaces
  • Tool Objects and Interfaces
  • Performance Objects and Interfaces
  • Composition Objects and Interfaces
  • Synthesizer Objects and Interfaces


Core Objects and Interfaces

The core objects handle the basic needs of DirectMusic: input, output, and timing. These objects are most often managed by other objects such as DirectMusicPerformance, and you might never need to use their interfaces directly.

DirectMusic Object

The DirectMusic object, represented by the IDirectMusic interface, is used for creating ports and buffers, for connecting with DirectSound, and for setting up a master clock. There should not be more than one instance of this object per application.

Many applications never need to use the IDirectMusic interface directly. In this respect it differs from other DirectX base interfaces. For example, IDirectSound is the starting point for every DirectSound application, performing essential tasks such as setting the cooperative level and creating sound buffers. In DirectMusic, most initialization is handled by other objects such as DirectMusicPerformance, and these objects are created independently by direct calls to CoCreateInstance.

Port

Each device that sends or receives music data is encapsulated in a DirectMusicPort object. The methods of the IDirectMusicPort interface allow direct manipulation of the port, but most applications do not need to use these methods, because the port is managed by the performance. For example, you assign channels to a port through the DirectMusicPerformance object so that data in those channels is correctly routed.

Buffer

The IDirectMusicBuffer interface represents the data currently ready to be played by the port (or read from the port). Most applications don't deal directly with the buffer object, but methods are available to directly manipulate its contents.

Thru

The IDirectMusicThru interface is used to set up direct transmission of data from a capture port to another port.

Reference Clock

Objects that implement the IReferenceClock interface represent the master clock that synchronizes all DirectMusic activity, and the latency clock of a port.


Loader Objects and Interfaces

Certain types of objects, such as DirectMusicCollection and DirectMusicStyle, have to be loaded (typically from a file) before they can be incorporated into a music performance. Others, such as DirectMusicSegment, may be either loaded or constructed on the fly. The interfaces introduced in this section are essential for loading.

Loader

The DirectMusicLoader object, through its IDirectMusicLoader interface, manages the enumeration, caching, and loading of objects.

Stream

Data being read from a file or resource is represented by a stream object. Most applications do not have to deal directly with streams, which are created and managed by the loader. The stream object implements the following two interfaces:

  • IStream streams the data from a file or resource and passes it to the object being loaded, which parses it by using its own implementation of IPersistStream.
  • IDirectMusicGetLoader has a single method that returns a pointer to the DirectMusicLoader object that created the stream. It is used when a reference to another object is found in a stream, and the object being loaded needs to call the loader to load the referenced object.

For a closer look at the use of these interfaces in the loading process, see DirectMusic Loader.

Object

Every object in DirectMusic that represents a file or resource supports the IDirectMusicObject interface, which is used as a generic pointer by the loader. When an application has obtained a pointer to this interface, the IDirectMusicObject::QueryInterface method can be used to obtain a pointer to the object's own unique interface, such as IDirectMusicCollection or IDirectMusicStyle. However, you will usually obtain the interface you need from the call to IDirectMusicLoader::GetObject.

The methods of IDirectMusicObject are used internally by the loader for identifying objects.


Instrument Objects and Interfaces

An instrument is an object that represents a basic musical timbre or other sound. For all ports except legacy hardware MIDI ports, each instrument is associated with its own set of downloadable sounds (DLS), which must be downloaded to the port before the instrument can be used.

Downloadable sounds can be handled at three levels of abstraction. At the highest level, you load a band from a file and let the band object handle the DLS downloading for the instruments. At the next level, you directly access individual instruments in a collection and download them to a port. At the lowest level, you work with the DLS data itself.

The following objects and interfaces are used for managing instruments.

Collection

Instruments are stored in a DirectMusicCollection object, which represents an instance of a DLS file. Once the DirectMusicCollection object has been loaded, the IDirectMusicCollection interface can be used to enumerate instruments in the collection and to obtain a pointer to an instrument that has a given MIDI patch number.

Instrument

An instrument from a collection is represented by a pointer to the IDirectMusicInstrument interface. This pointer can be passed to the IDirectMusicPerformance::DownloadInstrument or IDirectMusicPort::DownloadInstrument method to download DLS data to a port.

Once an instrument has been downloaded, it is represented by an IDirectMusicDownloadedInstrument interface pointer. This pointer is used only to unload the instrument by calling IDirectMusicPort::UnloadInstrument.

Applications that need to download their own DLS data for an instrument (such as collection editing tools) use the methods of the IDirectMusicPortDownload interface (implemented by the port object) to get that data to the synthesizer. When this interface is used to allocate a buffer for instrument data, an IDirectMusicDownload interface pointer is returned. The single method of this interface can be used to obtain a pointer to the buffer itself.

Band

The DirectMusicBand object represents a set of instruments and MIDI program changes for a musical segment. The band is created in an authoring tool and can be loaded separately from a file, or it can be part of an authored segment.

The IDirectMusicBand interface can be used to download and unload bands. It also has a method for creating a secondary segment from a band. This segment can be played by the performance in order to effect program changes.

The key differences between a collection and a band are as follows:

  • A collection is a group of instruments available for use in the playback of any segment. A band is a group of instruments that actually plays a particular segment.
  • Instruments in a collection contain DLS data defining their timbre. Instruments in a band contain no such data but are linked to instruments in one or more collections.
  • An instrument from a collection is not inherently associated with any particular performance channel (PChannel) of a segment. A band assigns the patch number of an instrument to each PChannel in a segment and assigns a voice priority to the channel.
  • A collection does not contain any information about how the instruments are to be played. A band contains settings for the volume, pan, and transposition of each instrument.


Tool Objects and Interfaces

Tools are objects that intercept musical messages and process them before they are passed on to the port. All tools (except the output tool implemented by DirectMusic) are application-defined.

Tool

The IDirectMusicTool interface represents a single tool. The methods of this interface are implemented by the application or DLL in order to define the tool's functionality.

Graph

Tools are collected in a graph, represented by the IDirectMusicGraph interface, which is implemented by both the segment and the performance object. The interface is used for directing messages from one tool to the next as well as for adding tools to the graph, retrieving pointers to individual tools, and shutting down the graph.


Performance Objects and Interfaces

The following objects and interfaces are used in the playback of musical data. With a total of over 75 methods, the interfaces in this group play a major role in any DirectMusic application.

Performance

The DirectMusicPerformance object is the overall manager of music playback. Through the IDirectMusicPerformance interface, it adds and removes ports, downloads instruments, attaches graphs (collections of tools), manages event notification for multiple segments, and plays segments.

Segment

A DirectMusicSegment object represents a chunk of data, most often a piece of music, contained in one or more tracks. Typically a segment would be either loaded from a file or created at run time by a DirectMusicComposer object. To play the segment, the application passes the IDirectMusicSegment interface pointer to the IDirectMusicPerformance::PlaySegment method.

Methods of the IDirectMusicSegment interface are used to manage timing and looping, event notification, tracks, tool graphs, and various other parameters of the segment.

An instance of a segment that is playing is represented by another interface, IDirectMusicSegmentState. Methods of this interface return information about the state of playback, and a pointer to the interface is used by the performance to stop or remove the segment instance.

Track

A chunk of timed data of a particular kind is represented by a DirectMusicTrack object, more simply referred to as a track. Methods of the IDirectMusicTrack interface can be used to set and retrieve data, play the data, and set notifications. Most applications do not use this interface directly, because tracks are normally handled through the methods of the DirectMusicSegment object that contains them.

Note A DirectMusicTrack is not the same thing as an instrument track. A DirectMusicTrack represents any kind of timed data, such as MIDI messages, a chord progression, or band changes.


Composition Objects and Interfaces

The objects and interfaces in this category are used in the real-time composition of music. Except for the composer itself, they represent data loaded from a file created in an application such as DirectMusic Producer. For a closer look at the role of each object, see Music Composition.

Composer

Methods of the IDirectMusicComposer interface allow an application to compose musical segments and transitions, using chordmaps, styles, and templates created by a human author.

Style

Styles contain basic information about a piece of music, including note patterns. Styles often form part of authored segments, where they do most of their work behind the scenes. They can also be used to compose entirely new segments at run time. Styles are represented by the IDirectMusicStyle interface.

Chordmap

A DirectMusicChordMap object represents a collection of chords and pathways used by DirectMusicComposer in determining the chord progression in a piece of music.

The IDirectMusicChordMap interface is obtained for a DirectMusicChordMap object loaded from a file. A pointer to this interface is passed to the methods of IDirectMusicComposer so that a segment or transition can be composed at run time using the authored chordmap. You can also change the chord pattern of an existing segment by applying a new chordmap.

Template

Templates are a special type of DirectMusicSegment object. They are never played directly but are used by the DirectMusicComposer in the real-time construction of segments based on styles and chordmaps.


Synthesizer Objects and Interfaces

The synthesizer is responsible for converting MIDI messages to waveform data and streaming this to the wave output device. Although DirectMusic comes with its own software synthesizer, it allows the implementation of custom synthesizers. It also allows output to be directed to different devices. Information on these topics in contained in the DirectX Device Driver Kit (DDK).

Synthesizer

A synthesizer implemented by an application is represented by the IDirectMusicSynth interface. Most applications do not use this interface, and it is not documented in the DirectX Programmer's Reference.

Synth Sink

The wave stream to which the synthesizer is sending data—for example, DirectSound or Win32 waveform audio—is represented by an IDirectMusicSynthSink interface. Most applications do not use this interface, and it is not documented in the DirectX Programmer's Reference.


Overview of DirectMusic Data Flow

Typically a DirectMusic application obtains musical data from one or more of the following sources:

  • MIDI file.
  • Segment file authored in an application such as DirectMusic Producer.
  • Component files authored in an application such as DirectMusic Producer and turned into a complete composition by the DirectMusicComposer object.

Data from these sources is encapsulated in DirectMusicSegment objects. Each segment object represents data from a single source. At any given moment in a performance, one or more segments may be playing: a primary segment and possibly one or more secondary segments. Source files can be mixed—for example, a secondary segment based on a MIDI file can be played along with a primary segment based on an authored segment file.

A segment comprises several tracks, each containing timed data of a particular kind—for example, notes or tempo changes.

Most tracks generate messages when the segment is played by the performance, and the performance dispatches the messages to any application-defined tools, which have the opportunity to modify messages and pass them on, delete messages, and send new messages. Tools are grouped in segment graphs that process only messages from their own segments, and a performance graph that accepts messages from all segments.

Finally, the messages are delivered to the output tool, which converts the data to MIDI format before passing it to a port. Channel-specific MIDI messages are directed to the appropriate channel group on the port. The port synthesizes a sound wave that is streamed to a wave output device (normally a DirectSound buffer).

The following diagram gives an overview of how musical data gets from files to the wave output device. For the sake of simplicity, only a single segment is shown. Note that this segment gets its data from only one of the three possible sources shown: either a MIDI file, an authored segment file, or component files combined by the DirectMusicComposer object.

For a closer look at the flow of messages through the performance, see DirectMusic Messages.

For information on how to implement the process illustrated in the diagram, see the DirectMusic Essentials section, in particular the topics DirectMusic Loader and Playing Music.

For more about segment and component files, see Music Composition.


DirectMusic Messages

Musical data passes through the DirectMusic performance engine in the form of messages. Most DirectMusic applications will not have to work directly with messages, but a basic knowledge of their structure can help you understand how DirectMusic works.

DirectMusic works with two different kinds of messages:

  • Performance messages, based on the DMUS_PMSG structure. All sequenced data passes through the performance engine in this form. These messages contain detailed information about timing and routing of the data.
  • Standard MIDI messages. These can be read from a MIDI file or device and either passed directly (thrued) to another device or converted to DMUS_PMSG format before being passed to the performance. Final output to the synthesizer is also in the form of MIDI messages.

The following topics give more information about messages and how they are routed:

  • Channels
  • Message Creation and Delivery
  • Performance Message Types
  • MIDI Messages


Channels

A channel is a destination for a message that is specific to one part in the performance. For example, a channel might receive a note-on message that causes the instrument on that channel to make a sound, or a program change message that assigns a different instrument to that part. (See MIDI Channel Messages.)

Under the MIDI 1.0 standard, there are 16 MIDI channels, meaning that no more than 16 instruments can be playing at one time. In order to support this standard but at the same time make more channels available to applications, DirectMusic creates channel groups. Up to 65,536 channel groups can exist at one time, each containing 16 channels, for a total of over one million channels. A particular port can be assigned any number of channel groups up to its capability to support them. Legacy MIDI hardware ports have only a single channel group.

System exclusive messages address all 16 channels within a channel group, but not other channel groups.

Every instrument in a DirectMusic performance has a unique performance channel, or PChannel. The PChannel represents a particular MIDI channel in a particular group on a particular port. When a band is selected by a performance, the instruments in that band are each mapped to a PChannel.

The actual number of notes that can be played simultaneously is limited by the number of voices available on the port. (This number can be determined from the dwVoices member of the DMUS_PORTPARAMS structure.) A voice is a set of resources dedicated to the synthesis of a single note being played on a channel. In the event that there are more notes playing than there are available voices, one or more notes will have to be suppressed by the synthesizer. The choice is determined by the priority of the voice currently playing the note, which is based in turn on the priority of the channel. By default, channels are ranked according to their index value, except that channel 10, the MIDI percussion channel, is ranked highest. However, applications and synthesizers can set their own channel priorities.

For more information on channel priority, see the Remarks for IDirectMusicPort::GetChannelPriority. See also DMUS_CHANNEL_PRIORITY_PMSG.


Message Creation and Delivery

When a segment is played, most of its tracks generate messages containing information about events that are to take place during the playback. (For more information, see Tracks.)

A few tracks send more than one kind of message. For example, a style track sends note messages and time signature messages. In such cases, an application can disable certain kinds of messages in the track. For more information, see Setting and Retrieving Track Parameters.

Applications may also place messages in the queue directly. You might do this, for example, to change the tempo. For sample code, see IDirectMusicPerformance::SendPMsg.

The performance engine determines when each message is to be processed in real time (reference time). In the case of channel messages, the performance also determines to what PChannel the message is to be directed. This information, along with other data including the message type, its source track, and pointers to the first graph and tool that are to receive the message, are stored in the DMUS_PMSG members of the message structure.

Certain messages, such as tempo and time signature changes, are immediately processed and freed by the performance. Other messages, such as notes and patch changes, are placed in a queue, where they are processed in order of time-stamp.

Notes There is no guarantee that messages with the same time-stamp will be processed in any particular order.

Tempo messages (DMUS_TEMPO_PMSG) tell the performance how to convert music time to reference time. Time signature messages (DMUS_TIMESIG_PMSG) are purely informational, because the time signature is built into the segment and cannot be changed.

Messages are first sent to any tools in the segment's graph and then to tools in the performance's graph. (The application is responsible for creating either or both of these graphs and defining the tools. There is no default graph.)

The first tool in a graph processes the message and then, if it wishes to pass it on, has the graph stamp the message with a pointer to the next tool. (For a closer look at this process, see Tutorial 2: Using Tools.)

At this point the graph also flags the message with a delivery type that determines when the message is delivered to the next tool. The flag is based on what delivery type the tool is expecting, as follows:

  • If the message is flagged as DMUS_PMSGF_TOOL_IMMEDIATE, it is to be delivered to the next tool immediately.
  • If it is flagged as DMUS_PMSGF_TOOL_QUEUE, the message is to be delivered just before the time at which it is supposed to play, taking latency into account (see Latency and Bumper Time).
  • If the message has the DMUS_PMSGF_TOOL_ATTIME flag, it is to be delivered at exactly the time at which it is to be processed. Notification messages are given this flag, because there is little or no latency involved in processing a notification.

The current tool has the opportunity to change the delivery type after the graph is finished stamping and flagging the message.

Ultimately, unless a message has been discarded, it arrives at the DirectMusic output tool, which converts all the data it receives into standard MIDI messages and delivers these to the synthesizer through the port buffer.


Performance Message Types

Messages are stored in various structures derived from DMUS_PMSG. Because C does not support inheritance, the members of DMUS_PMSG are included in the declaration for each message type as the DMUS_PMSG_PART macro. These members contain data common to all messages, including the type of the message, time stamps, the performance channel to which the message is directed, and what graph and tool are next in line to process the message. The other members contain data unique to the message type.

The following message structures are defined:

DMUS_PMSG | Simple message with no additional parameters.
DMUS_CHANNEL_PRIORITY_PMSG | Channel priority change. See Channels.
DMUS_CURVE_PMSG | Curve.
DMUS_MIDI_PMSG | Any MIDI message that does not have a unique message type—for example, a control change.
DMUS_NOTE_PMSG | Music note. (Includes duration, so MIDI note-on and note-off messages are combined in this type.)
DMUS_NOTIFICATION_PMSG | Notification. See Notification and Event Handling.
DMUS_PATCH_PMSG | MIDI patch change.
DMUS_SYSEX_PMSG | MIDI system exclusive message.
DMUS_TEMPO_PMSG | Tempo change.
DMUS_TIMESIG_PMSG | Time signature change.
DMUS_TRANSPOSE_PMSG | Transposition.


MIDI Messages

This section gives an overview of standard MIDI messages and how such messages, typically streamed from a MIDI file, are handled by DirectMusic. Most applications will not have to deal directly with MIDI messages, because the loader and the performance manage all the details of playback. (See Tutorial 1: Playing a MIDI File.)

MIDI input is converted to performance message format (using structures based on DMUS_PMSG) before being routed through tools by the performance. The output tool converts the data back to the standard MIDI message format before passing it to the synthesizer.

Note There is no guarantee that MIDI messages will be processed in the same order in which they occur in the file. DirectMusic messages are delivered in order of timestamp, and two MIDI messages with identical timestamps might not be delivered in the expected order. Care must be taken, in authoring MIDI content, not to give events simultaneous timestamps when they must take place sequentially. For example, don't place a program change at the exact same time as a note that is supposed to use the program change.

MIDI messages consist of a status byte usually followed by one or two data bytes. System exclusive MIDI messages are of variable length. The status byte indicates the type of message and, in some cases, the channel that is to receive the message. When several events of the same kind are in sequence in the file, the status byte can be omitted. This is called running status. Data bytes are recognizable because the high bit is always clear, whereas in status bytes it is always set.

The timing of MIDI events being streamed from a file is controlled by a number before each message indicating how many ticks separate this event from the last. The actual duration of a tick depends on the time format in the file header.

MIDI messages are divided into two main categories:

  • MIDI Channel Messages
  • MIDI System Messages


MIDI Channel Messages

A channel message is addressed to a particular MIDI channel, which corresponds to a single part in the music.

A channel message can be either a mode message or a voice message.

A mode message determines how a channel will deal with subsequent voice messages. For example, a mode message might instruct the channel to remain silent, ignoring all note-on messages until further notice.

Most channel messages are voice messages: they instruct the channel to begin or stop playing a note or to modify the note in some way, or they change the instrument by assigning a different MIDI patch number to the channel.

Voice messages are of the following types:

Voice message | Purpose
Note-on | Play a note.
Note-off | Stop playing the note.
Control change | Modify the tone with data from a pedal, lever, and so on; also used for miscellaneous controls such as volume and bank select.
Program (patch) change | Select an instrument for the channel by assigning a patch number.
Aftertouch | Modify an individual note, or all notes on the channel, according to the aftertouch of a key.
Pitch bend change | Cause the tone to make a smooth transition in pitch.

Keep in mind that these descriptions apply to standard MIDI messages, not MIDI data that has been converted to performance message format. For example, a pair of MIDI messages to start and stop a note will be combined by DirectMusic into a single DMUS_NOTE_PMSG giving the duration of the note. DirectMusic messages also contain much additional information about the timing and routing of the message.

MIDI notes

The data bytes of a note-on message represent the pitch and velocity. In most cases, a pitch value of 0 represents C below subcontra C (called C0 in MIDI notation), 12 represents subcontra C (or C1), 60 is middle C (or C5), and so on. For drum kits, the data byte instead represents a particular drum sound. For example, as long as the General MIDI (GM) percussion key map is being adhered to, a value of 60 represents a high bongo sound. Channel 10 is reserved for drum kits, so the synthesizer knows that note-on messages on that channel are to be treated differently than on other channels.

For information on how DirectMusic converts to and from MIDI notes, see Music Values and MIDI Notes.

Program changes

Program changes and patch numbers are a key concept in MIDI playback and in DirectMusic. A program change assigns a particular instrument (also called a program or timbre) to a channel, so that the notes sent to that channel are played with the appropriate sound. Instruments are identified by patch numbers. If the GM instrument set is loaded, a program change specifying patch number 1 will always cause the channel to play its notes as an acoustic grand piano. (Of course, the actual sound produced at the speakers depends on the way the instrument is synthesized.)

Bank selection

Because a single data byte is used to select the patch number in a program change, and only 7 bits in each data byte of a MIDI message are significant, a program change can select from a maximum of 128 instruments. In order to provide a greater choice, the MIDI specification allows for the use of up to 16,384 instrument banks, each containing up to 128 instruments.

To select an instrument from a different bank, the MIDI sequencer must first send a control change message called bank select. The two data bytes of this message are referred to as the most significant byte (MSB) and least significant byte (LSB), and they are combined to identify a bank. Once the bank has been selected, each subsequent program change selects an instrument from that bank.

DirectMusic patch numbers

In DirectMusic, the instrument patch number is not the 7-bit MIDI patch number but a 32-bit value that packs the MIDI patch number together with the MSB and LSB of the bank select and a one-bit flag for a drum kit. This extended patch number is returned by the IDirectMusicCollection::EnumInstrument, IDirectMusicCollection::GetInstrument, and IDirectMusicInstrument::GetPatch methods. It can be changed for an instrument by using the IDirectMusicInstrument::SetPatch method.

The organization of DirectMusic patch values is as follows:

Bits | Purpose
0-7 | MIDI patch number (bit 7 always 0)
8-15 | LSB bank select (bit 15 always 0)
16-23 | MSB bank select (bit 23 always 0)
24-30 | Unused
31 | Flag for drum kit


MIDI System Messages

System messages are not exclusive to any channel. They are of three kinds, as shown in the following table.

Message type | Purpose
System common | Miscellaneous commands and data.
System exclusive | Equipment-specific commands and data.
System real-time | Synchronization of clock-based MIDI equipment.

Unlike other MIDI messages, system exclusive messages can contain any number of data bytes. After transmitting the data, the sequencer sends a system common message called an EOX, which signals the end of the system exclusive message. In DirectMusic, the DMUS_SYSEX_PMSG structure contains the length of the data and a pointer to an array of data bytes.


Downloadable Sounds

In the past, most computer music has been produced in one of two fundamentally different ways, each with its advantages and disadvantages:

  • Wave forms are reproduced from digital samples, typically stored in a .wav file or, in the case of Red Book audio, on a standard CD track. Digital samples can reproduce any sound, and the output is very similar on all sound cards. However, they require large amounts of storage and resources for streaming.
  • Instrument sounds are synthesized, usually in hardware, in response to messages, typically from a MIDI file. MIDI files are compact and require few streaming resources, but the output is limited to the number of instruments available in the General MIDI set and in the synthesizer, and may sound very different on different systems.

One way to combine the advantages of digital sampling with the compactness and flexibility of MIDI is wavetable synthesis—the synthesis of instrument sounds from digital samples. These samples are obtained from recordings of real instruments and then stored on the hardware. The samples are looped and adjusted in such a way as to produce sounds of any length at various pitches and volumes.

Wavetable synthesis produces more realistic timbres than algorithmic FM synthesis, but is still limited to a fixed set of instruments. Moreover, a particular instrument may sound different on different pieces of hardware depending on the manufacturer's implementation of that instrument.

Enter the downloadable sounds (DLS) standard, published by the MIDI Manufacturers Association. DLS is basically a way of enabling wavetable synthesis to be based on samples provided at run time rather than hardwired into the system. The data describing an instrument is downloaded to the synthesizer, and then the instrument can be played just like any other MIDI instrument. Because DLS data can be distributed as part of an application, developers can be sure that their soundtracks will be delivered uniformly on all systems. Moreover, they are not limited in their choice of instruments.

A DLS instrument is created from one or more digital samples, typically representing single pitches which are then modified by the synthesizer to create other pitches. Multiple samples are used in order to make the instrument sound realistic over a wide range of pitches. When a DLS instrument is downloaded, each sample is assigned to a certain range of pitches, called a region. Usually there are no more than 16 regions.

In addition, samples may be given an articulation, which defines things like attack (how quickly a note reaches full volume), decay (how quickly it falls away from full volume), and other characteristics that make the sound more like that produced by a real instrument.

Downloadable sounds are stored in instrument collections, from which they are downloaded to the synthesizer.

DLS instruments are assigned patch numbers and respond to MIDI messages just like other MIDI instruments. However, a DLS instrument does not have to belong to the General MIDI set. In fact, it doesn't have to represent a musical instrument at all. Any sound, even a fragment of speech or a fully composed measure of music, can be turned into a DLS instrument.

For more information on DLS collections and how instruments are created, see the documentation for DirectMusic Producer. For a guide to incorporating DLS in your applications, see Using Downloadable Sounds.


Microsoft Software Synthesizer

The Microsoft Software Synthesizer is supplied with DirectMusic and is the default port. The synthesizer creates a waveform based on a stream of MIDI messages, using instrument timbres synthesized from DLS samples. By default the samples are from the Roland GS collection, which is also part of the DirectMusic installation.

Note The Roland GM/GS Sound Set cannot be modified. See the Copyright Warning for the legal restrictions.

In the current release of DirectMusic, the synthesizer is implemented in a DLL that sends its output to the DirectSound mixer.

The Microsoft Software Synthesizer includes reverberation capabilities, which are on by default. The Waves TrueVerb reverberation technology is licensed to Microsoft as the SimpleVerb implementation.


DirectMusic Essentials

This section gives practical information on how to implement DirectMusic in applications. For a more general overview, see DirectMusic Architecture.

The following topics are discussed:

  • Building DirectMusic Projects
  • Integrating DirectMusic and DirectSound
  • Using Ports
  • DirectMusic Loader
  • DirectMusic File Format
  • Using Downloadable Sounds
  • Playing Music
  • Music Parameters
  • Capturing Music
  • DirectMusic Tools
  • Music Composition


Building DirectMusic Projects

Unlike other components of DirectX, the DirectMusic application programming interface (API) is completely COM-based and does not contain any library functions such as helper functions to create COM objects. As a result, there is no Dmusic.lib file to link to during the build.

Most projects will need to include the header files Dmusicc.h and Dmusici.h, which contain declarations for the core and performance layers respectively, and Dmerror.h, which contains return values. Dmusicf.h has to do with file formats and is needed only for applications such as music authoring tools that work directly with files and do not rely solely on the loaders built into DirectMusic.

Dmksctrl.h contains declarations for the IKsControl interface, used for property sets. You do not need this file if you have the Ksproxy.h and Ks.h files.

DirectMusic uses the multithreading capabilities of the Windows 32-bit operating system. Multithreading allows DirectMusic to generate, process, and synthesize music in the background while your application is concentrating on other tasks. You should develop your project with multithreading in mind. If nothing else, be sure to link with the multithreaded libraries.

You also need to make sure your application has access to the GUIDs used by DirectMusic. For more information, see Compiling DirectX Samples and Other DirectX Applications.


Integrating DirectMusic and DirectSound

Although it is possible to use DirectMusic to send wave data to any device, the default synthesizer streams its output to DirectSound.

DirectMusic is capable of handling all the details of linking to DirectSound without any action on your part. When it creates or links to a DirectSound object, DirectMusic ensures that the primary buffer format matches that of the highest format among all DirectMusic ports.

In an application that uses only music files for its soundtrack, and does not require DirectSound for playing wave files or resources, the DirectSound object is typically created when the DirectMusic performance is initialized, as in the following example, where pPerf is a pointer to the IDirectMusicPerformance:

pPerf->Init(NULL, NULL, hwnd);

In this example, the first NULL specifies that the DirectMusic object is to be created and managed internally, the second NULL specifies the same for the DirectSound object, and hwnd is the controlling window for DirectSound.

Note It is good practice to supply the top-level application window handle when requesting that DirectMusic create the DirectSound object. See the Remarks for IDirectMusicPerformance::Init and IDirectSound::SetCooperativeLevel.

More information is contained in the following topics:

  • Setting the DirectSound Object
  • Setting the DirectSound Buffer Object


Setting the DirectSound Object

Allowing DirectMusic to create and manage the DirectSound object works for applications that are not using DirectSound independently. However, if your application is using DirectSound to play wave data from a source other than the DirectMusic synthesizer, you have to ensure that the same IDirectSound interface is used by DirectMusic. You must create the DirectSound object first, then pass the interface pointer to DirectMusic. This can be done in the call to IDirectMusicPerformance::Init, as in the following example, where pPerf is the IDirectMusicPerformance and pDS is a pointer to IDirectSound:

pPerf->Init(NULL, pDS, NULL);

Note When an IDirectSound pointer is passed to IDirectMusicPerformance::Init, the third parameter, the window handle, is ignored. The application is responsible for setting the controlling window by calling IDirectSound::SetCooperativeLevel.

It is strongly recommended that you set the DSSCL_PRIORITY cooperative level for any DirectSound object to be used with DirectMusic. If you set the DSSCL_NORMAL cooperative level, DirectMusic cannot upgrade the primary buffer format.

If you create the DirectMusic object by using CoCreateInstance, rather than letting the performance do it for you, you must also explicitly link it to an existing IDirectSound interface. This is done by using the IDirectMusic::SetDirectSound method.

You can also use the IDirectMusicPort::SetDirectSound method to assign a different DirectSound object to a port. You would do this when different ports were on different audio devices, each represented by its own IDirectSound interface. The DirectSound object for a port cannot be changed once the port has been activated.

When a port that requires DirectSound is activated, it takes the first available IDirectSound interface pointer from the following list:

  1. The IDirectSound passed to IDirectMusicPort::SetDirectSound.
  2. The IDirectSound passed to IDirectMusic::SetDirectSound.
  3. The IDirectSound created by DirectMusic if NULL was passed to IDirectMusic::SetDirectSound.

When DirectSound is in emulation mode, it has exclusive use of the audio device. A well-behaved application will release DirectSound whenever it loses the focus, in order to allow other applications to use the device. Typically this is done in response to a WM_ACTIVATE message.

If DirectMusic created the DirectSound object, it will automatically release the object when all ports are deactivated (and create a new one when the first port using DirectMusic is reactivated). However, if you created the DirectSound object yourself, you are responsible for releasing it. This can be done by using the IDirectMusic::SetDirectSound or IDirectMusicPort::SetDirectSound method, passing NULL as the pDirectSound parameter.


Setting the DirectSound Buffer Object

When DirectMusic is linked to DirectSound, it creates and manages a secondary DirectSound buffer for the wave output from each port, in a format matching that of the port. You can override the default behavior and ensure that the data is streamed to a different buffer, by using the IDirectMusicPort::SetDirectSound method. You can do this, for example, to have 3-D effects on the sound buffer. (See the the 3DMusic Sample.) You might even create multiple instances of the synthesizer port, each with its own DirectSound 3-D buffer, to place different instruments at different points in space.

The buffer you pass to IDirectMusicPort::SetDirectSound must be a secondary streaming buffer with a matching format. You can get information about the wave format and recommended buffer size by calling the IDirectMusicPort::GetFormat method.

DirectMusic will not attempt to upgrade the primary buffer when you pass your own IDirectSoundBuffer to IDirectMusicPort::SetDirectSound.


Using Ports

A port is a device that sends or receives musical data. It may correspond to a hardware device, a software synthesizer, or a software filter.

Each port in a DirectMusic application is represented by an IDirectMusicPort interface. Methods of this interface are used to retrieve information about the device, manage the memory on the device, download and unload DLS instruments, read incoming data, and cue playback buffers.

Every performance must have at least one port. To create a port object, you must first set up a DMUS_PORTPARAMS structure. You don't have to fill in all members, but you do need to let DirectMusic know which members have valid information by putting the appropriate flags in the dwValidParams member. Then you pass the structure to the IDirectMusic::CreatePort method.

The following C++ code demonstrates how an object might be created for the default port, setting five channel groups on the port. It is assumed that pDirectMusic is a valid IDirectMusic pointer.

IDirectMusicPort*  pPort;
DMUS_PORTPARAMS    dmos;

ZeroMemory( &dmos, sizeof(DMUS_PORTPARAMS) );
dmos.dwSize = sizeof(DMUS_PORTPARAMS);
dmos.dwValidParams = DMUS_PORTPARAMS_CHANNELGROUPS;
dmos.dwChannelGroups = 5;
HRESULT hr = pDirectMusic->CreatePort( GUID_NULL, &dmos,
        &pPort, NULL )

Once you have a port, you must activate it by calling IDirectMusic::Activate or IDirectMusicPort::Activate and attach it to the performance by using the IDirectMusicPerformance::AddPort method.

When you add a port to a performance, you must assign a block of PChannels to it by calling the IDirectMusicPerformance::AssignPChannelBlock method. The only time this is not necessary is when you add the default port by passing NULL to IDirectMusicPerformance::AddPort. In that case, PChannels 0 to 15 are assigned to the MIDI channels in the first group on the port.

You can map PChannels differently, add more PChannels, or assign PChannels to a different port by using the IDirectMusicPerformance::AssignPChannelBlock and IDirectMusicPerformance::AssignPChannel methods.

More information about ports is contained in the following topics:

  • Default Port
  • Legacy Ports
  • Port Property Sets


Default Port

If you want your application to use the default port, you don't have to call the IDirectMusic::CreatePort method before adding the port to the performance. You can instead pass NULL to IDirectMusicPerformance::AddPort.

In the current version of DirectMusic, the Microsoft Software Synthesizer is the default port. However, you should not assume that the default port has the features you need or that it will always be the Microsoft Software Synthesizer. It is good practice to obtain the default port by a call to IDirectMusic::GetDefaultPort, then check its capabilities by using the IDirectMusicPort::GetCaps method. If the port does not meet the needs of your application, you can use the IDirectMusic::EnumPort method to find the Microsoft Software Synthesizer or another port.


Legacy Ports

Under Windows 95 and Windows 98, DirectMusic supports legacy ports—that is, it will sequence output data to a MIDI device that uses FM or hardware wavetable synthesis. You can recognize a legacy port by the DMUS_PORT_WINMM_DRIVER flag in the dwType member of the DMUS_PORTCAPS structure returned by IDirectMusic::EnumPort or IDirectMusicPort::GetCaps.

Legacy ports have the following restrictions in DirectMusic:

  • Not supported on Windows 2000.
  • No support for downloadable sounds.
  • Master volume cannot be changed. (This can be done for other ports by setting a global parameter. See Setting and Retrieving Global Parameters.)
  • There is only one channel group. (See Channels.)

Another respect in which legacy ports differ from others is that the application determines whether channels on the legacy port are to be shared between ports, by setting the fShare member of the DMUS_PORTPARAMS structure. This member is relevant only for ports that have the DMUS_PC_SHAREABLE flag in the dwFlags member of DMUS_PORTCAPS, as is always the case for legacy ports.

Most applications do not need to consider the presence of legacy ports, because the Microsoft Software Synthesizer produces consistent results on all output devices capable of playing waveform audio.


Port Property Sets

Through property sets, DirectMusic is able to provide unlimited support for new features in hardware and drivers. A property set is associated with a particular port.

Hardware vendors define new capabilities as properties and publish the specification for these properties, including GUIDs. You, the application developer, can then use the IKsControl::KsProperty method to find out whether a property is available and then to set and retrieve values for that property. You obtain the IKsControl interface for a port by calling the IDirectMusicPort::QueryInterface method, passing IID_IKsControl as the interface identifier.

A property set is represented by a GUID, and each item within the set is represented by a zero-based index. The meaning of the indexed items for a GUID never changes. For a list of the property sets supported by DirectMusic, see KSPROPERTY.

All property sets predefined by DirectMusic have only one item, usually at index 0. However, the full definition of kernel streaming (KS) properties is supported, and vendors are free to create property sets with any number of items and instances and data of any size.

Routing of the property item request to the port varies depending on the port implementation. No properties are supported by ports which represent DirectMusic emulation on top of the Win32 handle-based multimedia calls (midiOut and midiIn functions).

The following code uses the IKsControl::KsProperty method to determine if the port supports General MIDI in hardware:

BOOL IsGMSupported(IDirectMusicPort *pPort)
{
    HRESULT     hr;
    IKsControl  *pControl;
    KSPROPERTY  ksp;
    DWORD       dwFlags;
    ULONG       cb;
    BOOL        fIsSupported;

    // Query for IKsControl interface
    hr = pPort->QueryInterface(IID_IKsControl, (void**)&pControl);
    if (FAILED(hr))
    {
        // Port does not support properties, assume no GM support
        return FALSE;
    }
    // Ask about GM
    ksp.Set   = GUID_DMUS_PROP_GM_Hardware;
    ksp.Id    = 0;
    ksp.Flags = KSPROPERTY_TYPE_BASICSUPPORT;
    hr = pControl->KsProperty(&ksp, sizeof(ksp),
            &dwFlags, sizeof(dwFlags), &cb);
    fIsSupported = FALSE;
    if (SUCCEEDED(hr) || (cb >= sizeof(dwFlags))
    {
        // Set is supported
        fIsSupported = (BOOL)(dwFlags & KSPROPERTY_TYPE_GET);
    }
    pControl->Release();
    return fIsSupported;
}

The following sample code shows how a property can be changed. In this case, the reverberation properties of the software synthesizer are set to those contained in a DMUS_WAVES_REVERB_PARAMS structure.

/* Assume that m_* variables have been initialized to valid values.
   m_pPort is a pointer to IDirectMusicPort. */

DMUS_WAVES_REVERB_PARAMS Params;

Params.fInGain = m_fReverbIn;
Params.fHighFreqRTRatio = m_fReverbHigh;
Params.fReverbMix = m_fReverbMix;
Params.fReverbTime = m_fReverbTime;

IKsControl *pControl;
if (m_pPort)
{
    // Query for IKsControl interface
    HRESULT hr = m_pPort->QueryInterface(IID_IKsControl,
            (void**)&pControl);
    if (SUCCEEDED(hr))
    {
        KSPROPERTY ksp;
        ULONG cb;

        ZeroMemory(&ksp, sizeof(ksp));
        ksp.Set   = GUID_DMUS_PROP_WavesReverb;
        ksp.Id    = 0;
        ksp.Flags = KSPROPERTY_TYPE_SET;

        pControl->KsProperty(&ksp,
                             sizeof(ksp),
                             (LPVOID)&Params,
                             sizeof(Params),
                             &cb);
        pControl->Release();
    }
}

The following code actually turns on the reverb effect for the port represented by m_pPort:

DWORD dwEffects = 0;
IKsControl *pControl;
HRESULT hr = m_pPort->QueryInterface(IID_IKsControl,
        (void**)&pControl);
if (SUCCEEDED(hr))
{
  KSPROPERTY ksp;
  ULONG cb;

  ZeroMemory(&ksp, sizeof(ksp));
  dwEffects = DMUS_EFFECT_REVERB;
  ksp.Set   = GUID_DMUS_PROP_Effects;
  ksp.Id    = 0;
  ksp.Flags = KSPROPERTY_TYPE_SET;

  pControl->KsProperty(&ksp,
             sizeof(ksp),
             (LPVOID)&dwEffects,
             sizeof(dwEffects),
             &cb);
  pControl->Release();
}

The final example shows how you might turn off reverb while leaving any other effects intact:

DWORD dwEffects = 0;
IKsControl *pControl;
HRESULT hr = m_pPort->QueryInterface(IID_IKsControl,
        (void**)&pControl);
if (SUCCEEDED(hr))
{
  KSPROPERTY ksp;
  ULONG cb;

  ZeroMemory(&ksp, sizeof(ksp));
  ksp.Set   = GUID_DMUS_PROP_Effects;
  ksp.Id    = 0;
  ksp.Flags = KSPROPERTY_TYPE_GET;

  pControl->KsProperty(&ksp,
             sizeof(ksp),
             (LPVOID)&dwEffects,
             sizeof(dwEffects),
             &cb);

  ZeroMemory(&ksp, sizeof(ksp));
  dwEffects = dwEffects & ~DMUS_EFFECT_REVERB;
  ksp.Set   = GUID_DMUS_PROP_Effects;
  ksp.Id    = 0;
  ksp.Flags = KSPROPERTY_TYPE_SET;

  pControl->KsProperty(&ksp,
             sizeof(ksp),
             (LPVOID)&dwEffects,
             sizeof(dwEffects),
             &cb);

  pControl->Release();
}


DirectMusic Loader

Many DirectMusic objects have to be loaded from a file or resource before they can be incorporated into a music performance. The IDirectMusicLoader interface is used to manage the loading of such objects, as well as for finding and enumerating objects and caching them so that they are not loaded more than once.

An application should have only one instance of the loader in existence at any time. It is a good idea to create a single global loader object and not free it until there is no more loading to be done. This strategy will ensure that the finding and caching of objects is done efficiently.

The DirectMusic implementation of IStream streams the data from the source. The parsing of the data is handled by the various objects themselves, through their implementations of IPersistStream. As long as you are dealing only with standard DirectMusic data, you don't need to use these interfaces directly.

Loading of objects referenced by other objects is handled transparently. For example, suppose a style being loaded from a DirectMusic Producer file contains a reference to a band whose data is in another file. When the style's IPersistStream comes across the reference, it obtains the IDirectMusicGetLoader interface from the IStream that passed it the data stream. Using this interface, it obtains a pointer to the DirectMusicLoader. Then it calls IDirectMusicLoader::GetObject to load the band.

More information on using the DirectMusicLoader is contained in the following topics:

  • Setting the Loader's Search Directory
  • Scanning a Directory for Objects
  • Enumerating Objects
  • Loading Objects
  • Loading an Object from a Resource
  • Getting Object Descriptors
  • Caching Objects
  • Setting Objects
  • Custom Loading


Setting the Loader's Search Directory

By default, the loader looks for objects in the current directory, unless a full path is specified in the wszFileName member of the DMUS_OBJECTDESC structure describing the object being sought. By using the IDirectMusicLoader::SetSearchDirectory method, you can set a different default path for the IDirectMusicLoader::GetObject and IDirectMusicLoader::EnumObject methods. This default path can apply to all objects, or only objects of a certain class.

The following sample function sets the search path for style files:

HRESULT mySetLoaderPath (
    IDirectMusicLoader *pILoader)    // Previously created
{
    return pILoader->SetSearchDirectory(
            CLSID_DirectMusicStyle,
            L"c:\\mymusic\\funky",
            FALSE);
}

Having called this function, the application can now load a style by file name without including the full path, as in the following example function:

HRESULT myLoadStyleFromPath (
    IDirectMusicStyle **ppIStyle,    // Receives pointer to style
    IDirectMusicLoader *pILoader)    // Loader already created
{
    HRESULT hr;
    DMUS_OBJECTDESC Desc;

    ZeroMemory(&Desc, sizeof(DMUS_OBJECTDESC);
    Desc.dwSize = sizeof(DMUS_OBJECTDESC);
    wcscpy(Desc.wszFileName, L"polka.sty");   // Short file name
    Desc.guidClass = CLSID_DirectMusicStyle;  // Object class
    Desc.dwValidData = DMUS_OBJ_CLASS | DMUS_OBJ_FILENAME;

    hr = pILoader->GetObject(&Desc,
            IID_IDirectMusicStyle, (void **) ppIStyle);
    return hr;
}


Scanning a Directory for Objects

The IDirectMusicLoader::ScanDirectory method scans the current search directory for objects of a given class. You can further narrow down the search by providing a subclass and a file extension other than "*".

The method compiles a list of all matching files and uses the IDirectMusicObject::ParseDescriptor method to extract the GUID and the name of the object. These identifiers are retained in an internal database so that the application can subsequently load objects by GUID or name rather than by file name. (See Loading Objects.)

Note It is always a good idea to call IDirectMusicLoader::ScanDirectory before loading any objects. Even though you may be loading objects explicitly by file name, those objects might contain references to other objects not identified by file name, and the loader will not be able to find these referenced objects if ScanDirectory has not been called on every directory where the objects might be.

If you include a pointer to a string in the pwszScanFileName parameter of the ScanDirectory method, the results of the scan will be cached in a file by that name in order to speed up subsequent scans. When a cache file is available, the method updates object information only for files whose timestamps or sizes have changed.

Note In the current version of DirectMusic, ScanDirectory does not actually use the cache file. Nonetheless you can implement a cache file now and it will speed up performance under future versions.

For an example, see Enumerating Objects.


Enumerating Objects

You can use the IDirectMusicLoader::EnumObject method to iterate through all objects of a given class, or of all classes, that have previously been listed in the internal database through a call to IDirectMusicLoader::ScanDirectory or calls to IDirectMusicLoader::GetObject. A description of each object found is returned in a DMUS_OBJECTDESC structure.

Note To be sure of finding all objects, you must call ScanDirectory first. EnumObject works by checking the internal database of objects, not by parsing disk files.

The following example enumerates all listed style objects in the current search directory and displays information about each one by using the TRACE debugging macro. The loop continues executing until there are no more objects of that class to enumerate.

void myListStyles(
        IDirectMusicLoader *pILoader)

{
    HRESULT hr = pILoader->SetSearchDirectory(
            CLSID_DirectMusicStyle,
            L"c:\\mymusic\\wassup",
            TRUE);
    if (SUCCEEDED(hr))
    {
        hr = pILoader->ScanDirectory(
                CLSID_DirectMusicStyle,
                L"sty",
                L"stylecache");
        if (hr == S_OK)    // Only if files were found...
        {
            DWORD dwIndex;
            DMUS_OBJECTDESC Desc;
            Desc.dwSize = sizeof(DMUS_OBJECTDESC);
            for (dwIndex = 0; ;dwIndex++)
            {
                if (S_OK ==(pILoader->EnumObject(
                        CLSID_DirectMusicStyle,
                        dwIndex, &Desc)))
                {
                    TRACE("Name: %S, Category: %S, Path: %S\n",
                            Desc.wszName,
                            Desc.wszCategory,
                            Desc.wszFileName);
                }
                else break;
            }
        }
    }
}

Notice that the example does not use the SUCCEEDED macro to test the result of the method call, because EnumObject returns a success code, S_FALSE, for an invalid index number.


Loading Objects

To load an object, you must first obtain the IDirectMusicLoader interface, as in the following example:

IDirectMusicLoader* m_pLoader;

CoInitialize(NULL);
HRESULT hr = CoCreateInstance(
    CLSID_DMLoader,
    NULL,
    CLSCTX_INPROC,
    IID_IDirectMusicLoader,
    (void**)&m_pLoader);

You then describe the object and call the IDirectMusicLoader::GetObject method to load it and obtain the desired interface.

The following example function loads a style from disk and returns a pointer to it in the variable addressed by the parameter.

void myLoadStyle(
    IDirectMusicStyle **ppIStyle)
{
    IDirectMusicLoader *pILoader;        // Loader interface.

/* Normally you would create the loader once and use it for the
   duration of the application. This reduces overhead and takes
   advantage of the loader's ability to cache objects. However, for
   purposes of this example, we create it dynamically and throw it
   away once the style is loaded. */

    CoCreateInstance(
            CLSID_DirectMusicLoader,NULL,
            CLSCTX_INPROC,
            IID_IDirectMusicLoader,
            (void **) &pILoader);

    if (pILoader)
    {
        DMUS_OBJECTDESC Desc;

        // Start by initializing Desc with the file name and
        // class GUID for the style object.

        wcscpy(Desc.wszFileName,L"c:\\mymusic\\funky\\polka.sty");
        Desc.guidClass = CLSID_DirectMusicStyle;
        Desc.dwSize = sizeof (DMUS_OBJECTDESC);
        Desc.dwValidData = DMUS_OBJ_CLASS |
                           DMUS_OBJ_FILENAME |
                           DMUS_OBJ_FULLPATH;

        pILoader->GetObject(&Desc, IID_IDirectMusicStyle,
                (void **) ppIStyle);
        pILoader->Release();
    }
}

This example function identifies the file by a full path name and indicates that it is doing so by setting the DMUS_OBJ_FULLPATH flag. If you have previously set the search directory, you can use the short name of the file without full path information. For an example, see Setting the Loader's Search Directory.

To identify the particular file object being sought you must fill in at least one of the wszName, guidObject, and wszFileName members of the DMUS_OBJECTDESC structure and set the corresponding flag or flags in the dwValidData member. If you identify the file by wszName or guidObject but not by wszFileName, you must first call the IDirectMusicLoader::ScanDirectory method in order to make the GUIDs and names in the current directory available. For more information, see Scanning a Directory for Objects.

See also Loading an Object from a Resource.


Loading an Object from a Resource

Loading an object from a resource, or from some other location in memory, is done in a similar fashion to loading an object from a file. (See Loading Objects.) In this case, however, the wszName, guidObject, and wszFileName members of the DMUS_OBJECTDESC structure are irrelevant. Instead you must obtain a pointer to the block of memory occupied by the object, and its size, and put these in the pbMemData and llMemLength members respectively of the DMUS_OBJECTDESC structure. You must also set the DMUS_OBJ_MEMORY flag in the dwFlags member.

Note that the memory cannot be released once IDirectMusicLoader::GetObject has been called, because the loader keeps the pointer to the memory internally, to facilitate caching data. If you want to clear it out, call IDirectMusicLoader::SetObject with the same DMUS_OBJECTDESC descriptor, but with NULL in pbMemData. This is not an issue with loading from a resource, because resource memory is not freed.

The following function loads a MIDI file from a resource into a segment:

HRESULT LoadMidi(HMODULE hMod, WORD ResourceID)
{
    HRESULT              hr;
    DMUS_OBJECTDESC      ObjDesc;
    IDirectMusicSegment* pSegment = NULL;

    HRSRC hFound = FindResource(hMod,
            MAKEINTRESOURCE(ResourceID), RT_RCDATA);
    HGLOBAL hRes = LoadResource(hMod, hFound);

    ObjDesc.dwSize = sizeof(DMUS_OBJECTDESC);
    ObjDesc.guidClass = CLSID_DirectMusicSegment;
    ObjDesc.dwValidData = DMUS_OBJ_CLASS | DMUS_OBJ_MEMORY;
    ObjDesc.pbMemData = (BYTE *) LockResource(hRes);
    ObjDesc.llMemLength = SizeofResource(hMod, hFound);

    hr = m_pDXPerformance->m_pLoader->GetObject(
            &ObjDesc, IID_IDirectMusicSegment,
            (void**) &m_pSegment );

    return hr;
}


Getting Object Descriptors

Once you have loaded an object. you can use its IDirectMusicObject interface to retrieve information about it in a DMUS_OBJECTDESC structure. You must first obtain the IDirectMusicObject interface for the object.

The following example uses the IDirectMusicObject::GetDescriptor method to obtain the name of a style:

/* It is assumed that pStyle is a valid pointer to an
   IDirectMusicStyle interface. */

if (pStyle)
{
    IDirectMusicObject *pIObject;
    DMUS_OBJECTDESC Desc;

    if (SUCCEEDED(pStyle->QueryInterface(IID_IDirectMusicObject,
            (void **) &pIObject)
    {
        if (SUCCEEDED(pIObject->GetDescriptor(&Desc))
        {
            if (Desc.dwValidData & DMUS_OBJ_NAME)
            {
                TRACE("Style name is %S\n",Desc.wszName);
            }
        }
        pIObject->Release();
    }
}


Caching Objects

When an object is cached, the same interface pointer is always returned by the IDirectMusicLoader::GetObject method.

Caching is used extensively in the file loading process to resolve links to objects. If an object is not found in the cache, it has to be reloaded, even if it already exists. For example, two segments could reference the same style. When the first segment loads, it calls the loader to get the style, which in turn creates a style object, loads it from disk, stores a pointer to the style in the cache, and returns it to the segment. If caching is enabled, when the second segment loads it asks for the style and the loader immediately returns it, so both segments point to the same style. If caching is disabled, the second segment's request for the style results in a duplicate style loaded from the file. This is very inefficient.

Another example: IDirectMusicBand counts on the loader to keep the General MIDI DLS collection cached. Every time it comes across a GM instrument, it gets the collection from the loader by requesting it with GUID_DefaultGMCollection. If caching for CLSID_DirectMusicCollection is disabled, every patch change in a MIDI file will result in a separate copy of the entire GM collection being created—not good.

By default, caching is enabled for all object classes. You can disable caching for an object class, or for all objects, by using the IDirectMusicLoader::EnableCache method. This method can also be used to re-enable caching for any or all object classes.

If you wish to clear the cache without disabling future caching, use the IDirectMusicLoader::ClearCache method.

To cache a single object, pass it to the IDirectMusicLoader::CacheObject method. You can remove it from the cache, ensuring that it will be loaded again on the next call to GetObject, by using the IDirectMusicLoader::ReleaseObject method.

It is a good idea to call ReleaseObject on a cached object, particularly a segment, before destroying the object by calling its own Release method. If you don't do this, a copy of the object remains in the cache along with certain state information. In the case of a segment, any instance you later create will be loaded from the cache, and its start point and loop points will be the same as they were when the previous instance was destroyed.

With judicious use of CacheObject, ReleaseObject, and EnableCache, you can have the objects you don't need released, while others remain in the cache.


Setting Objects

Sometimes it is desirable to tell the loader where to get an object without actually loading that object, so that the loader will be able to retrieve it if the object is later referenced by other objects as they are being loaded.

For example, suppose your application uses its own DLS data for the General MIDI instrument collection. Normally, the loader finds Gm.dls at its default installation point and loads data from that file whenever an object is loaded that references the GM collection. In order to override that default behavior, before any of those referencing objects are loaded you need to tell the loader to get the collection from somewhere else. This is done by using the IDirectMusicLoader::SetObject method.

SetObject takes as a parameter a DMUS_OBJECTDESC structure that contains two key pieces of information:

  • A pointer to the data. This can be either a file path or a pointer to a block of memory. (See Loading Objects and Loading an Object from a Resource.)
  • Something by which to identify the object when it is referenced later. This could be a GUID or a name. In the case of Gm.dls, it is GUID_DefaultGMCollection. Later, the call to GetObject will find the stored object by using the same name or GUID.

The following sample code instructs the DirectMusicLoader m_pLoader to look for the GM collection in the file myGM.dls rather than in Gm.dls:

DMUS_OBJECTDESC ObjDesc;

wcscpy( ObjDesc.wszFileName,L"myGM.dls" );
ObjDesc.guidClass = CLSID_DirectMusicCollection;
ObjDesc.guidObject = GUID_DefaultGMCollection;
ObjDesc.dwSize = sizeof(DMUS_OBJECTDESC);
ObjDesc.dwValidData = DMUS_OBJ_CLASS | DMUS_OBJ_FILENAME
        | DMUS_OBJ_OBJECT;
HRESULT hr = m_pLoader->SetObject( &ObjDesc);

The following code forces the loader to look for the GM collection in a resource identified as IDR_GMDLS in the module hMod:

DMUS_OBJECTDESC ObjDesc;

HRSRC hFound = FindResource(hMod,
        MAKEINTRESOURCE(IDR_GMDLS), RT_RCDATA);
HGLOBAL hRes = LoadResource(hMod, hFound);

ObjDesc.pbMemData = (BYTE *) LockResource(hRes);
ObjDesc.llMemLength = SizeofResource(hMod, hFound);
ObjDesc.guidClass = CLSID_DirectMusicCollection;
ObjDesc.guidObject = GUID_DefaultGMCollection;
ObjDesc.dwSize = sizeof(DMUS_OBJECTDESC);
ObjDesc.dwValidData = DMUS_OBJ_CLASS | DMUS_OBJ_MEMORY |
        DMUS_OBJ_OBJECT;

HRESULT hr = m_pLoader->SetObject( &ObjDesc);


Custom Loading

Specialized applications might create their own object types that encapsulate data from a file or resource. It can be convenient to have the DirectMusic loader handle the loading of such objects. This is especially true if the custom object is referenced by other objects or contains references to other objects.

To implement a loading mechanism that takes advantage of the DirectMusic loader, you must take the following steps:

  • Register the object class so that it can be found by IDirectMusicLoader::GetObject.
  • Implement the IDirectMusicObject interface on the object, so that the loader can get the information it needs for finding and caching it.
  • Implement the IPersistStream interface on the object, with full functionality in the IPersistStream::Load method. This is where you parse the data, which you obtain through calls on the IStream interface passed by the DirectMusicLoader.
  • In the implementation of Load, ensure that references to other objects are dealt with by querying the IStream for the IDirectMusicGetLoader interface, then calling IDirectMusicGetLoader::GetLoader to obtain a pointer to the DirectMusicLoader that created the stream. Once you have this pointer, you can call IDirectMusicLoader::GetObject to load the new object.

There are circumstances where an application may need to manage file input itself — for example, because all objects are stored in a special compressed resource file. The application can create its own loader by creating an object that supports the IDirectMusicLoader interface, with the IDirectMusicLoader::GetObject method implemented. All other methods are optional. This implementation of the loader must also create its own stream object that has both the IStream and the IDirectMusicGetLoader interfaces.


DirectMusic File Format

This section describes the format of music files created in an application such as DirectMusic Producer and read by DirectMusic when IDirectMusicLoader::GetObject is called. Most applications do not need to parse these files directly. This format information is included for developers of music-authoring applications or DirectMusic plug-ins who want to be able to save data in a compatible format or load data into their own objects.

DirectMusic data is stored in the resource interchange file format (RIFF). The following topics contain information about RIFF files and how DirectMusic data is stored:

  • About RIFF
  • RIFF Notation
  • DirectMusic File Chunks

For a reference to data structures used in DirectMusic files, see File Structures.


About RIFF

The basic building block of a RIFF file is a chunk. A chunk is a logical unit of data. Each chunk contains the following fields:

  • A four-character code (FOURCC) specifying the chunk identifier. Conventionally, this is upper case for registered chunk types and lower-case otherwise.
  • A DWORD value specifying the size of the data member in the chunk.
  • The data.

A chunk contained in another chunk is a subchunk. The only chunks allowed to contain subchunks are those with a chunk identifier of "RIFF" or "LIST".

The first chunk in a file must be identified as "RIFF". All other chunks in the file are subchunks of the RIFF chunk.

RIFF chunks include an additional field in the first four bytes of the data field. This additional field provides the form type of the chunk. The form type is a four-character code identifying the format of the data stored in the file. For example, DirectMusic styles have the form type "DMST".

LIST chunks also include an additional field in the first four bytes of the data field. This additional field contains the list type of the field. The list type is a four-character code identifying the contents of the list. For example, DirectMusic styles have a LIST chunk with a list type of "part" that contains data pertaining to a particular part (instrument track) in the performance.

A LIST chunk is a grouping of subchunks. Some of these subchunks may appear multiple times, but a LIST is not an array. The terminology can be a little confusing. You might expect the chunk labeled <part-list>, for example, to be a list of parts. In fact, it is a list of the elements of a "part" chunk, which describes a single part.

Note Every four-character code used in DirectMusic files has a corresponding macro in Dmusicf.h. For example, the FOURCC for "DMST" is returned by the macro DMUS_FOURCC_STYLE_FORM.

For more information on RIFF files in general, see Resource Interchange File Format Services in the Platform SDK documentation.


RIFF Notation

The descriptions of DirectMusic files in the following sections use a subset of the conventional notation for RIFF files. The principal parts of this notation are shown in the following table:

Notation | Description
<element> | File element labeled "element", or of type element
[ <element> ] | Optional file element
<element>... | One or more copies of the specified element
[<element>]... | Zero or more copies of the specified element
name, 'name', NAME, or 'NAME' | FOURCC identifier of a form type, list type, or chunk.
// Comment | Comment.

Labels are used only in the notation, not in the files themselves. The label <cheh-ck> refers to a chunk with a unique FOURCC identifier and format. Wherever a chunk of this kind occurs in the notation, the same label is used.

The data or sub-elements associated with a label are described as in the following example:

<cheh-ck> -> cheh( <DMUS_IO_CHORDENTRY> )

This notation shows that the chunk labeled <cheh-ck> consists of the FOURCC identifier "cheh" followed by a DMUS_IO_CHORDENTRY structure. Of course, a DWORD showing the size of the data must precede the data as in any RIFF chunk. The presence of this data size element is assumed and is not shown in the notation.

The next example shows a list element, consisting of the FOURCC "LIST" followed by the list identifier "cmap" and one or more elements labeled <choe-list>. The <choe-list> element would be expanded elsewhere.

<cmap-list> -> LIST( 'cmap'
    <choe-list>... )


DirectMusic File Chunks

The following sections describe the format of chunks used in DirectMusic RIFF files:

  • Common Chunks
  • Band Form
  • Chordmap Form
  • Segment Form
  • Style Form
  • Tool Form
  • Tool Graph Form
  • Track Form


Common Chunks

The following chunks occur within various list chunks and forms.

GUID Chunk
<guid-ck> -> guid( <GUID> )

This is the GUID identifier of the element.

Version Chunk
<vers-ck> -> vers( <DMUS_IO_VERSION> )

This chunk contains version information for the element.

UNFO Chunk
<UNFO-list> -> LIST( 'UNFO'
    <unfo-text-ck>...
    )

The UNFO chunk is like a standard RIFF INFO list, except that it uses Unicode characters. INFO and UNFO lists consist of various chunks that contain null-terminated strings.

Reference List Chunk

The reference list chunk contains information about a reference to an object in another file. For example, a band object might contain a reference to a DLS collection in a separate file.

The notation for a reference list is as follows:

<DMRF-list> ->LIST( 'DMRF'
    <refh-ck>       // Reference header
    [<guid-ck>]     // Object GUID
    [<date-ck>]     // File date
    [<name-ck>]     // Name
    [<file-ck>]     // File name
    [<catg-ck>]     // Category name
    [<vers-ck>]     // Version info
)

The data begins with a header that includes information about the object being referred to:

<refh-ck> -> refh( <DMUS_IO_REFERENCE> )

All other chunks are optional. The GUID and version chunks are described previously. The notation for the others is as follows:

<date-ck> -> date( <FILETIME> )
<name-ck> -> name( <WCHAR>... )  // Null-terminated string
<file-ck> -> file( <WCHAR>... )  // Null-terminated string
<catg-ck> -> catg( <WCHAR>... )  // Null-terminated string


Band Form

The following notation shows the format of the top-level chunk, or form, of a band file. Band forms can also be contained in other chunks.

RIFF( 'DMBD'
    [<guid-ck>]     // GUID for band
    [<vers-ck>]     // Optional version info
    [<UNFO-list>]   // Name, author, copyright info, comments
    <lbil-list>     // List of instruments
)

For the first three chunks, which are optional, see Common Chunks.

The data is contained in a list of lists:

<lbil-list> -> LIST( 'lbil'
    <lbin-list>...
    )

Each instrument is described in a list that has the following format:

<lbin-list> -> LIST( 'lbin'
    <bins-ck>
    [<DMRF-list>]
    )

Within the instrument list, the following chunk contains a header describing the instrument:

<bins-ck> -> bins( <DMUS_IO_INSTRUMENT> )

The instrument list may also contain <DMRF-list>, which is a reference to a DLS file. See Common Chunks.


Chordmap Form

The following notation shows the organization of the top-level chunk, or form, of a chordmap file:

RIFF( 'DMPR'
    <perh-ck>       // Chordmap header chunk
    [ <guid-ck> ]   // GUID chunk
    [ <vers-ck> ]   // version chunk
    [ <UNFO-list> ] // UNFO list
    <chdt-ck>       // chord data chunk
    <chpl-list>     // chord palette
    <cmap-list>     // chord graph
    <spsq-list>     // signpost list
)

Each of the items with the exception of the GUID chunk, version chunk, and UNFO list (see Common Chunks) is required.

The required chunks and their subchunks are as follows:

<perh-ck> -> perh( <DMUS_IO_CHORDMAP> )

This is the basic header information for a chordmap.

<chdt-ck> -> chdt(
    <WORD>    // size of DMUS_IO_CHORDMAP_SUBCHORD
    <DMUS_IO_CHORDMAP_SUBCHORD>...
    )

The <chdt-ck> chunk contains a WORD indicating the number of bytes per subchord followed by an array of unique subchords. The subchord identifiers referenced in other parts of this file all correspond directly to an index into this array.

<chpl-list> -> LIST( 'chpl'
    <chrd-list>...
    )

This list contains the chord palette. Currently there must be exactly 24 items in this list.

<chrd-list> -> LIST( 'chrd'
    <UNAM-ck>    // chord name
    <sbcn-ck>    // subchord indexes
    )

This list contains the basic chord information. This information is simply the chord's name and a list of identifiers for the subchords that make it up.

<UNAM-ck> -> UNAM ( <WCHAR>... )

The UNAM chunk stores the name of the chord.

<sbcn-ck> -> sbcn( <WORD>... )

The "sbcn" chunk contains one or more subchord identifiers. These correspond directly to an index into the array found in <chdt-ck>. Currently a maximum of four chords is supported.

<cmap-list>  ->  LIST( 'cmap'
    <choe-list>...
    )

The "cmap" list contains the entire chord connection graph for the chordmap. The bulk of the data for the chordmap resides in this chunk.

<choe-list> -> LIST( 'choe'
    <cheh-ck>      // chord entry data
    <chrd-list>    // chord data; see above
    <ncsq-ck>      // nextchord list
    )

The "choe" list contains data for a single entry in the chord graph along with pointers to all the chords that may occur next in the chord graph.

<cheh-ck> -> cheh( <DMUS_IO_CHORDENTRY> )

This is the chord entry header. The identifier in the structure is the identifier for the chord connection graph, not a subchord identifier.

<ncsq-ck> -> ncsq (
    <WORD>         // size of DMUS_IO_NEXTCHORD
    <DMUS_IO_NEXTCHORD>...
    )

The "ncsq" chunk contains data that connects one chord in the connection graph to another. Each chord in the connection graph is represented by a 16-bit identifier.

<spsq-list> -> LIST( 'spsq'
    <spst-list>...
    )

The "spsq" list contains data for each of the signposts.

<spst-list>  ->  LIST( 'spst'
    <spsh-ck>
    <chrd-list>  // chord data; see above
    [ <cade-list> ]
    )

The "spst" list contains data for a single signpost, consisting of a header, chord information, and optional cadence chords.

<cade-list> -> LIST( 'cade'
    <chrd-list>...
    )

The "cade" list contains the chord information for cadence chords. Currently there is support for up to two cadence chords in this list. Any additional chords or other information will be ignored.

<spsh-ck> -> spsh(
    <DMUS_IO_CHORDMAP_SIGNPOST>
)

Finally, the "spsh" chunk contains the signpost data.


Segment Form

The following notation shows the organization of the top-level chunk of a segment file:

RIFF( 'DMSG'
    <segh-ck>       // Segment header chunk
    [<guid-ck>]     // GUID for segment
    [<vers-ck>]     // Optional version info
    [<UNFO-list>]   // Name, author, copyright info, comments
    <trkl-list>     // List of tracks
    [<DMTG-form>]   // Optional tool graph
    )

The individual chunks and their subchunks are as follows:

<segh-ck> -> segh( <DMUS_IO_SEGMENT_HEADER> )

This chunk contains the basic header information for a segment.

For the next three chunks, see Common Chunks.

Next comes the track list. Each track is encapsulated in a Track Form.

<trkl-list> -> LIST( 'trkl'
    <DMTK-form>...
    )

Finally, the segment form may contain a Tool Graph Form.


Style Form

The following notation shows the organization of the top-level chunk of a style file:

RIFF( 'DMST'
    <styh-ck>       // Style header chunk
    <guid-ck>       // Unique identifier
    [<UNFO-list>]   // Name, author, copyright info, comments
    [<vers-ck>]     // version chunk
    <part-list>...  // List of parts in the style, used by patterns
    <pttn-list>...  // List of patterns in the style
    <DMBD-form>...  // List of bands in the style
    [<motf-list>]   // List of motifs in the style
    [<prrf-list>]   // List of chordmap references in the style
)

The individual chunks and their subchunks are as follows:

<styh-ck> -> styh( <DMUS_IO_STYLE> )

This chunk contains the basic header information for a style.

For these the next three chunks, see Common Chunks.

Next comes a chunk for each musical part in the style:

<part-list> -> LIST('part'
    <prth-ck>       // Part header chunk
    [<UNFO-list>]
    [<note-ck>]     // List of notes in part
    [<crve-ck>]     // List of curves in part
    )

The part list includes a header, an optional UNFO chunk, and a list of notes and curves, as shown in the following notation. (For the UNFO list, see Common Chunks.)

<prth-ck> -> prth( <DMUS_IO_STYLEPART> )

<note-ck> -> note(
    < DWORD >  // size of DMUS_IO_STYLENOTE
    < DMUS_IO_STYLENOTE >...
    )

<crve-ck> -> crve(
    < DWORD >  // size of DMUS_IO_STYLECURVE
    < DMUS_IO_STYLECURVE >...
    )

After the part-list chunk comes the pattern-list chunk:

<pttn-list> -> LIST( 'pttn'
    <ptnh-ck>       // Pattern header chunk
    <rhtm-ck>       // List of rhythms for chord matching
    [<UNFO-list>]
    [<mtfs-ck>]     // Motif settings chunk
    <pref-list>...  // List of part reference IDs
    )

The pattern list consists of the following subchunks. (For the optional UNFO list, see Common Chunks.)

<ptnh-ck> -> ptnh(
    < DMUS_IO_PATTERN >
    )

<rhtm-ck> -> rhtm(
    < DWORD >...
    )

This chunk consists of an array of DWORDs, one for each measure, giving the rhythm pattern. For information on the arrangement of the bits, see the dwRhythmPattern member of DMUS_RHYTHM_PARAM.

<mtfs-ck> -> mtfs(
    < DMUS_IO_MOTIFSETTINGS >
    )

<pref-list> -> LIST( 'pref'
    <prfc-ck>   // Part reference chunk
    )

The "pref" chunk in turn consists of an array of part references:

<prfc-ck> -> prfc(
    < DMUS_IO_PARTREF >
    )

The last chunk in the style form is the list of chordmap references:

<prrf-list> -> LIST( 'prrf'
    <DMRF-list>...
    )

For more information on <DMRF-list>, see Common Chunks.


Tool Form

The tool form contains information about tools. Tools can be embedded in a Tool Graph Form or stored as separate files.

<DMTL-form> -> RIFF( 'DMTL'
    <tolh-ck>
    [<guid-ck>]     // GUID for tool object instance
    [<vers-ck>]     // Version info
    [<UNFO-list>]   // Name, author, copyright info., comments
    [<data>]        // Tool data.
)

The tool header chunk is as follows:

<tolh-ck> -> tolh( <DMUS_IO_TOOL_HEADER> )

For the next three elements, which are optional, see Common Chunks.

The <data> element consists of a chunk of the type identified in the DMUS_IO_TOOL_HEADER. The format of this chunk depends on the definition of the tool. It may be a list or a simple chunk.


Tool Graph Form

A tool graph chunk can occur either as a top-level form or as a subchunk of a segment form.

RIFF( 'DMTG'
    [<guid-ck>]     // GUID for tool graph
    [<vers-ck>]     // Optional version info
    [<UNFO-list>]   // Name, author, copyright info, comments
    <toll-list>     // List of tools
)

For the first three elements, which are optional, see Common Chunks.

The main and only required part of the tool graph chunk is the tool list:

<toll-list> -> LIST( 'toll'
    <DMTL-form>...
    )

For more information on the <DMTL-form> chunk, see Tool Form.


Track Form

The track form contains information about a single track. It can be embedded in a Segment Form or stored in its own file.

<DMTK-form> -> RIFF( 'DMTK'
    <trkh-ck>
    [<guid-ck>]     // GUID for track object instance
    [<vers-ck>]     // Version info
    [<UNFO-list>]   // Name, author, copyright info, comments
    [<data>]        // Track data
)

The subchunks of the form are as follows:

<trkh-ck> -> trkh(
    <DMUS_IO_TRACK_HEADER>
    )

This chunk contains the basic header information for a track.

For the next three elements, which are optional, see Common Chunks.

The last element in the track form is the data for the track. The chunk type used for the data is identified in the DMUS_IO_TRACK_HEADER structure. The following standard track chunks are defined:

  • Band Track Form
  • Chord Track List
  • Chordmap Track List
  • Command Track Chunk
  • Mute Track Chunk
  • Sequence Track List
  • Signpost Track Chunk
  • Sysex Track Chunk
  • Tempo Track Chunk
  • Time Signature Track Chunk


Band Track Form

The band track form can be a top-level form but is also found as the data part of a Track Form. It is organized as follows:

RIFF( 'DMBT'
    [<bdth-ck>]     // Band track header
    [<guid-ck>]     // GUID for band track
    [<vers-ck>]     // Optional version info
    [<UNFO-list>]   // Name, author, copyright info, comments
    <lbdl-list>     // List of band lists
    )

The subchunks of the form are as follows:

<bnth-ck> -> bdth( <DMUS_IO_BAND_TRACK_HEADER> )

This optional chunk contains header information for a band track. The only data in the structure is a flag for automatic downloading.

For the next three elements, which are optional, see Common Chunks.

The last chunk contains one or more bands:

<lbdl-list> -> LIST( 'lbdl'
    <lbnd-list>...
    )

Each band is encapsulated in a list of the following type:

<lbnd-list> -> LIST( 'lbnd'
    <bdih-ck>
    <DMBD-form>
    )

The band list begins with a header:

<bdih-ck> -> ( <DMUS_IO_BAND_ITEM_HEADER> )

The header is followed by a Band Form containing information about the instruments in the band.


Chord Track List

The chord track list contains chord data for a Track Form. It is organized as follows:

<cord-list> -> LIST( 'cord'
    <crdh-ck>       // Header
    <crdb-ck>       // Chord body chunk
    )

The subchunks are as follows:

<crdh-ck> -> crdh ( <DWORD> )

The header is a DWORD containing the chord root in the upper 8 bits and the scale in the lower 24 bits. For an explanation of what these bits represent, see DMUS_IO_SUBCHORD.

The body of data for the chord track list consists of information about a chord change and the component subchords:

<crdb-ck> -> crdb(
    <DWORD>           // size of DMUS_IO_CHORD
    <DMUS_IO_CHORD>
    <DWORD>           // number of subchords
    <DWORD>           // size of DMUS_IO_SUBCHORD
    <DMUS_IO_SUBCHORD>...
    )


Chordmap Track List

The chordmap track list contains data for a Track Form. It is organized as follows:

<pftr-list> -> LIST('pftr'
    <pfrf-list>...
    )

The data consists of one or more lists containing timestamps and references to chordmaps:

<pfrf-list> -> LIST('pfrf'
    <stmp-ck>
    <DMRF-list>
    )

The notation for the timestamp chunk is as follows:

<stmp-ck> -> stmp( <DWORD> )

For information on <DMRF-list>, see Common Chunks.


Command Track Chunk

The command track chunk contains data for a Track Form. It is organized as follows:

<cmnd-ck> -> cmnd(
    <DWORD>    //size of DMUS_IO_COMMAND
    <DMUS_IO_COMMAND>...
    )


Mute Track Chunk

The mute track chunk contains data for a Track Form. It is organized as follows:

<mute-ck> -> mute(
    <DWORD>     //size of DMUS_IO_MUTE
    <DMUS_IO_MUTE>...
    )


Sequence Track List

The sequence track list contains data for a Track Form. It is organized as follows:

<seqt-list> -> LIST('seqt'
    <evtl-ck>
    <curl-ckt>
    )

The list contains two chunks, one for sequence items and one for curve items:

<evtl-ck> -> evtl(
    <DWORD>     // Size of DMUS_IO_SEQ_ITEM
    <DMUS_IO_SEQ_ITEM>...
    )

<curl-ck> -> curl(
    <DWORD>     // Size of DMUS_IO_CURVE_ITEM
    <DMUS_IO_CURVE_ITEM>...
    )


Signpost Track Chunk

The signpost track chunk contains data for a Track Form. It is organized as follows:

<sgnp-list> -> sgnp(
    <DWORD>    // Size of DMUS_IO_SIGNPOST
    <DMUS_IO_SIGNPOST>...
    )


Sysex Track Chunk

The sysex track chunk contains data for a Track Form. It is an array of sysex items, as shown in the following notation:

<syex-ck> -> syex(
    <DMUS_IO_SYSEX_ITEM>
    <BYTE>...  // Data
    )...


Tempo Track Chunk

The tempo track chunk contains data for a Track Form. It is organized as follows:

<tetr-ck> -> tetr(
    <DWORD>    // size of DMUS_IO_TEMPO_ITEM
    <DMUS_IO_TEMPO_ITEM>...
    )


Time Signature Track Chunk

The time signature track chunk contains data for a Track Form. It is organized as follows:

<tims-ck> -> tims(
    <DWORD>    // size of DMUS_IO_TIMESIGNATURE_ITEM
    <DMUS_IO_TIMESIGNATURE_ITEM>...
    )


Using Downloadable Sounds

This section covers the practical use of downloadable sounds (DLS) in DirectMusic. For an architectural overview of DLS, see Downloadable Sounds.

Most applications do not have to deal directly with instruments or downloadable sounds. The opening of collections and downloading of instrument data is handled by the DirectMusicBand object. When you download a band, all the instrument data associated with that band is downloaded as well. For more information, see Using Bands.

For specialized DirectMusic applications that do their own DLS management, two steps must be taken: loading the instrument collection and downloading data for individual instruments to a port.

These steps are covered in the following sections:

  • Loading a Collection
  • Working with Instruments
  • Playing a MIDI File with Custom Instruments

Applications that allow the editing of instruments and collections need to work with DLS data at an even lower level. This topic is covered in the following section:

  • Low-Level DLS


Loading a Collection

The simplest way to load a collection from a file is to use the IDirectMusicLoader interface. (For more information, see Loading Objects.) Once you have obtained a pointer to the IDirectMusicCollection interface, you have access to all the instruments in the collection. At this point, though, none of them have actually been downloaded to a port. In fact, no instrument data is loaded into memory until it is needed.

Here's what happens behind the scenes. The collection is a COM object that supports the IDirectMusicCollection, IDirectMusicObject, and IPersistStream interfaces. IPersistStream is a standard COM interface providing methods for saving and loading objects that use a simple serial stream for their storage needs.

IDirectMusicCollection does not load the entire collection when IPersistStream::Load is called. Typically, objects supporting IPersistStream load all of the persistent data in the stream and do not use the IStream pointer outside of the Load method. However, supporting IPersistStream::Load in this manner in IDirectMusicCollection would mean that the entire DLS collection would have to be loaded into memory even if only a single instrument in the collection was to be used. Instead, IDirectMusicCollection saves the IStream pointer and later uses it to load only the data for instruments that will be downloaded to a DirectMusic port. IDirectMusicCollection assumes that the data stream provided through the IPersistStream interface is in the DLS file format.

The following example does manually what the IDirectMusicLoader::GetObject method does automatically: it creates a collection object and loads a stream into it:

HRESULT myLoadCollectionFromStream(
        IStream *pIStream,    // Stream created from file.
        IDirectMusicCollection **ppICollection )

{
    HRESULT hr;

    hr = CoCreateInstance(CLSID_DirectMusicCollection,
                          NULL,
                          CLSCTX_INPROC,
                          IID_IDirectMusicCollection,
                          (void **)ppICollection);
    if (SUCCEEDED(hr))
    {
        IPersistStream* pIPersistStream;
        hr = *ppICollection->QueryInterface(
                IID_IPersistStream, (void**)&pIPersistStream);
        if (SUCCEEDED(hr))
        {
            hr = pIPersistStream->Load(pIStream);
            pIPersistStream->Release();
        }
    }
    return hr;
}

The following example uses the DirectMusicLoader to load the collection by file name.

HRESULT myLoadCollectionByName(
        IDirectMusicLoader *pILoader,
        char *pszFileName,
        IDirectMusicCollection **ppICollection)
{
    HRESULT hr;
    DMUS_OBJECTDESC Desc;             // Descriptor.

    // Start by initializing Desc with the file name and GUID
    // for the collection object.
    // The file name starts as a char string, so convert
    // to Unicode.

    mbstowcs(Desc.wszFileName,pszFileName,DMUS_MAX_FILENAME);
    Desc.dwSize = sizeof(DMUS_OBJECTDESC);
    Desc.guidClass = CLSID_DirectMusicCollection;
    Desc.dwValidData = DMUS_OBJ_CLASS
            | DMUS_OBJ_FILENAME
            | DMUS_OBJ_FULLPATH;

    hr = pILoader->GetObject(&Desc,
            IID_IDirectMusicCollection,
            (void **) ppICollection);
    return hr;
}

To load the standard GM/GS set, pass GUID_DefaultGMCollection to the loader in the guidObject member of the DMUS_OBJECTDESC structure. If you intend to use the loader to access this object more than once, make sure that caching is enabled (as it is by default) so you don't end up creating another copy of the GM collection each time you request it.

Note The GM/GS Sound Set cannot be altered. For more information, see the Copyright Warning.

The following code illustrates how to load a collection identified by its GUID:

HRESULT myGetGMCollection(
        IDirectMusicLoader *pILoader,
        IDirectMusicCollection **ppICollection)
{
    HRESULT hr;
    DMUS_OBJECTDESC desc;

    desc.dwSize = sizeof(DMUS_OBJECTDESC);
    desc.guidClass = CLSID_DirectMusicCollection;
    desc.guidObject = GUID_DefaultGMCollection;
    desc.dwValidData = (DMUS_OBJ_CLASS | DMUS_OBJ_OBJECT);
    hr = pILoader->GetObject(&desc, IID_IDirectMusicCollection,
            (void **) ppICollection);
    return hr;
}


Working with Instruments

Once a DirectMusicCollection is created and loaded from a collection file, you can retrieve the patch number and name of all the available instruments by using the IDirectMusicCollection::EnumInstrument method.

The following example enumerates all instruments in a collection and displays their names and patch numbers.

void myListInstruments(
        IDirectMusicCollection *pCollection)

{
    HRESULT hr = S_OK;
    DWORD dwPatch;
    WCHAR wszName[MAX_PATH];
    DWORD dwIndex;
    for (dwIndex = 0; hr == S_OK; dwIndex++)
    {
        hr = pCollection->EnumInstrument(
                dwIndex, &dwPatch, wszName, MAX_PATH);
        if (hr == S_OK)
        {
           printf("Patch %lx is %S\n",dwPatch,wszName);
        }
    }
}

You can obtain a pointer to a specific instrument by passing its patch number to the IDirectMusicCollection::GetInstrument method.

After obtaining an instrument, you can change its patch number by using the IDirectMusicInstrument::SetPatch method.

Loading a collection and retrieving the instruments is only the first step in making the instruments available. You next have to download them to the port.

To download an instrument to a port, you pass an IDirectMusicInstrument interface pointer to the IDirectMusicPort::DownloadInstrument method. This method simply makes the DLS data available on the port; it does not actually associate the instrument with any particular performance.

Alternatively, you can download an instrument by using the IDirectMusicPerformance::DownloadInstrument method. In addition to downloading the DLS data, this method assigns the instrument to a particular performance channel.

To economize on memory usage, only waves and articulation required for given ranges of notes are downloaded. For example, for a bassoon you might specify that only data for the note range low C to middle B was to be downloaded. Only the data for the regions falling within that range would be downloaded.

The following function, given a collection, a patch number, a port, and a range of notes, retrieves the instrument from the collection and downloads it. It sets up an array of just one DMUS_NOTERANGE structure and passes this to the IDirectMusicPort::DownloadInstrument method. Typically only a single range of notes will be specified, but it is possible to specify multiple ranges. If you pass NULL instead of a pointer to an array, the data for all regions is downloaded.

HRESULT myDownload(
    IDirectMusicCollection *pCollection,    // DLS collection
    IDirectMusicPort *pPort,                // Destination port
    IDirectMusicDownloadedInstrument **ppDLInstrument,
    DWORD dwPatch,                          // Requested instrument
    DWORD dwLowNote,                        // Low note of range
    DWORD dwHighNote)                       // High note of range

{
    HRESULT hr;
    IDirectMusicInstrument* pInstrument;
    hr = pCollection->GetInstrument(dwPatch, &pInstrument);
    if (SUCCEEDED(hr))
    {
        DMUS_NOTERANGE NoteRange[1];         // Optional note range
        NoteRange[0].dwLowNote = dwLowNote;
        NoteRange[0].dwHighNote = dwHighNote;
        hr = pPort->DownloadInstrument(pInstrument,
                ppDLInstrument,
                NoteRange,   // Array of ranges
                1);          // Number of elements in array
        pInstrument->Release();
    }
    return hr;
}

The DownloadInstrument method returns a pointer to the IDirectMusicDownloadedInstrument interface. This pointer has just one purpose: to identify the instrument in a subsequent call to the IDirectMusicPort::UnloadInstrument method, which unloads the instance of the instrument on a particular port. (Note that the DirectMusicCollection is not bound to any specific port. You can download different instruments to different ports, or download a single instrument to multiple ports.)

The following function downloads an instrument and then unloads it, which accomplishes nothing except to illustrate how the IDirectMusicDownloadedInstrument pointer can be used:

HRESULT myFickleDownload(
        IDirectMusicInstrument* pInstrument,
        IDirectMusicPort *pPort,
        DWORD dwPatch)

{
    HRESULT hr;
    IDirectMusicDownloadedInstrument * pDLInstrument;
    hr = pPort->DownloadInstrument(
            pInstrument, &pDLInstrument,
            NULL, 0);
    if (SUCCEEDED(hr))
    {
        pPort->UnloadInstrument(pDLInstrument);
        pDLInstrument->Release();
    }
    return hr;
}

The IDirectMusicBand::Download method automates the downloading of all instruments in a band. You supply a pointer to a performance, and the method downloads each instrument to the appropriate port attached to that performance.


Playing a MIDI File with Custom Instruments

By default, when you play a MIDI file the instruments used are those in the Roland GM/GS Sound Set, contained in the file Gm.dls. However, you can play a MIDI file using instruments from any collection.

To do so, first load the collection as described under Loading a Collection, obtaining a pointer to the IDirectMusicCollection interface. Then call IDirectMusicSegment::SetParam on the MIDI segment to establish a connection between the segment and the collection.

The following sample shows how the connection is made:

/* Assume that pSegment was created from a MIDI file
   and that pLoadedCollection is a valid IDirectMusicCollection
   pointer. */

HRESULT hr = pSegment->SetParam(GUID_ConnectToDLSCollection,
        0xFFFFFFFF, 0, 0,
        (void*)pLoadedCollection);

Note When a custom collection is attached to a MIDI segment, the connection to the GM collection is not broken. For example, suppose you load a collection containing a single instrument that has a patch number of 12, and connect this to the segment. MIDI channels with any patch number other than 12 will continue to be played by the appropriate instruments in the GM collection.

As with any other collection, instruments to be used in playing a MIDI file must be downloaded before the segment is played, unless automatic downloading has been enabled. (For more information on automatic downloading, see Setting and Retrieving Global Parameters and Downloading and Unloading Bands.) If instruments are not being downloaded automatically, you need to download them by calling IDirectMusicSegment::SetParam, as in the following example:

/* pSegment is an IDirectMusicSegment pointer, and pPerformance
   is a valid pointer to IDirectMusicPerformance. */

pSegment->SetParam(GUID_Download -1, 0, 0, (void *) pPerformance);

For more information on downloading by using SetParam, see Setting and Retrieving Track Parameters.


Low-Level DLS

If you are writing a DirectMusic application that edits DLS collections, you need to be able to download instrument data to the synthesizer without encapsulating it in a DirectMusicInstrument object. The following overview describes how to do this.

Working with DLS data requires knowledge of the DLS specification and file structure. For detailed information on these topics, see the document entitled Downloadable Sounds Level 1, published by the MIDI Manufacturers Association.

To download raw instrument data, you first need to get a pointer to the IDirectMusicPortDownload interface, as show in the following example, where it is assumed that pIPort is a valid pointer to an IDirectMusicPort interface:

IDirectMusicPortDownload **ppIDownloadPort;

HRESULT hr = pIPort->QueryInterface(IID_IDirectMusicPortDownload,
        (void **) ppIDownloadPort);

If the HRESULT is not S_OK, the port does not support DLS downloading.

Next identify the buffers that need to be prepared and downloaded. To send an instrument to the synthesizer, you must create one instrument buffer that represents the entire instrument definition with all the regions and articulations, and a series of wave buffers, one for each wave the instrument references for its regions.

Each buffer must be tagged with a unique identifier. Identifiers are used to resolve linkages between buffers, in particular the links between regions and waves. Tally the number of buffers you need to download and call IDirectMusicPortDownload::GetDLId to allocate a range of identifiers. For example, if you are downloading an instrument with three waves, you will need to download four buffers in total, so request a set of four identifiers.

For each buffer, calculate the size needed, then call IDirectMusicPortDownload::AllocateBuffer to allocate it. This method returns an IDirectMusicDownload interface representing the buffer. Call IDirectMusicDownload::GetBuffer to access the actual memory.

Note There are two methods called GetBuffer:

IDirectMusicPortDownload::GetBuffer returns an IDirectMusicDownload interface pointer for a buffer object whose download identifier is known.

IDirectMusicDownload::GetBuffer returns a pointer to the actual memory in the buffer.

Now write the data into each buffer. Each buffer starts with a DMUS_DOWNLOADINFO structure, which defines the size and functionality of the download. This structure must be prepared as follows:

  • Set the dwDLType member to either DMUS_DOWNLOADINFO_INSTRUMENT for an instrument or DMUS_DOWNLOADINFO_WAVE for a wave.
  • Set the dwDLId member to one of the unique identifiers you obtained by using IDirectMusicPortDownload::GetDLId.
  • Set the dwNumOffsetTableEntries member to the number of entries in the DMUS_OFFSETTABLE structure.
  • Set the cbSize member to the size of the download chunk, including DMUS_DOWNLOADINFO and DMUS_OFFSETTABLE.

The DMUS_DOWNLOADINFO structure is always followed by a DMUS_OFFSETTABLE structure. This offset table is used to manage all links within the data. Whenever a structure in the data references another structure, it addresses it with an integer index instead of a pointer. For every structure within the data that can be referenced, there is a unique index. The DMUS_OFFSETTABLE translates this integer index into a byte offset into the data.

The actual instrument or wave data follows the DMUS_OFFSETTABLE. If the download is an instrument, the data starts with the DMUS_INSTRUMENT structure. Otherwise it starts with the DMUS_WAVE structure.

The instrument data that follows the DMUS_INSTRUMENT structure is organized in the following structures:

  • DMUS_ARTICPARAMS
  • DMUS_ARTICULATION
  • DMUS_COPYRIGHT
  • DMUS_EXTENSIONCHUNK
  • DMUS_INSTRUMENT
  • DMUS_NOTERANGE
  • DMUS_REGION

The wave data pointed to by the DMUS_WAVE structure is organized in a DMUS_WAVEDATA structure.

When the buffers are all ready, download them by using IDirectMusicPortDownload::Download. Download the wave buffers first, so they are in place and can be referenced when the instrument is downloaded.

Once the buffers have been downloaded, the synthesizer is ready to play the instrument. The memory in the buffer is no longer accessible.

Later, when done playing the instrument, unload the buffers and release them. First unload the instrument buffer, then all the wave buffers. To unload, call IDirectMusicPortDownload::Unload and pass it the IDirectMusicDownload objects. Then, release each buffer with a call to IDirectMusicDownload::Release.

To update an instrument that has already been downloaded, you cannot write over the previously downloaded buffer. Instead, replace the instrument, but not the waves. To do this, call IDirectMusicPortDownload::AllocateBuffer to allocate a new IDirectMusicDownload interface with a buffer of the correct size. Be sure to generate a new identifier for the buffer with a call to IDirectMusicPortDownload::GetDLId. Write the new articulation information into the buffer, then download it. Then unload the previously downloaded buffer with a call to IDirectMusicPortDownload::Unload.

To update a wave buffer, take one extra step. Create both a new wave buffer and an updated instrument buffer that references it. Download the new wave, then the new instrument. Then unload the old instrument followed by the old wave.


Playing Music

This section introduces the basic elements of a DirectMusic performance and the key interface methods you will need in order to get music data from source to output.

The following topics are discussed:

  • Creating the Performance
  • Segments
  • Tracks
  • Using Bands
  • Timing
  • Notification and Event Handling


Creating the Performance

The manager of music playback is the performance object, which does most of the work of getting music from the source to the output buffer, including adding ports, assigning instruments to channels, downloading instrument data to the synthesizer, playing and stopping segments, dispatching messages, and managing tools and timing.

The following example creates a performance and obtains a pointer to the IDirectMusicPerformance interface:

IDirectMusicPerformance* pPerf;

if (FAILED(CoCreateInstance(
        CLSID_DirectMusicPerformance,
        NULL,
        CLSCTX_INPROC,
        IID_IDirectMusicPerformance,
        (void**)&pPerf
    )))
{
    pPerf = NULL;
}

Once the performance is created, it must be initialized. An important part of initialization is the creation of a DirectMusic object. You can create DirectMusic by passing CLSID_DirectMusic to CoCreateInstance, and then passing the IDirectMusic interface pointer to IDirectMusicPerformance::Init, but it most cases it will be more convenient to have Init create DirectMusic. You can also choose whether or not to retrieve a pointer to the IDirectMusic interface, depending on how much control you need over ports and the master clock. If you intend to use only the default synthesizer and the default master clock, you probably don't need access to the methods of IDirectMusic; in this case, you would pass NULL to Init.

The following example initializes the performance, retrieves a pointer to IDirectMusic, and creates an IDirectSound interface initialized with the application window handle:

IDirectMusic* pDirectMusic;

if (SUCCEEDED(pPerf->Init(&pDirectMusic,
        NULL,     // Create DirectSound object
        hWnd      // Application window handle
        )))
{
    // Performance initialized
}


Segments

The basic chunk of data in DirectMusic is called a segment. A segment is represented by an IDirectMusicSegment interface. You can create a segment in any of the following ways:

  • Load a file or resource object that supports the IDirectMusicSegment interface. For more information, see DirectMusic Loader.
  • Get a motif from a style by using the IDirectMusicStyle::GetMotif method.
  • Use methods of the IDirectMusicComposer interface to create a composition or transition at run time. See Overview of Programming for Composition and Using Transitions.
  • Make a copy of an existing segment by using the IDirectMusicSegment::Clone method.
  • Construct a segment from existing tracks. Create a segment object by calling CoCreateInstance and then add tracks by calling IDirectMusicSegment::InsertTrack.
  • Use the IDirectMusicBand::CreateSegment method. This creates a special type of secondary segment that is used only for making band changes. See Making Band Changes Programmatically.

Each segment consists of one or more tracks, each represented by an IDirectMusicTrack interface. Tracks contain most of the data for the segment, whether that data consists of note events, band changes, tempo changes, or other timed events. Applications generally do not need to use this interface, because the tracks are managed through the segment object. For more information, see Tracks.

Segments can serve different purposes. The following are the kinds of segments you are most likely to use:

  • Primary segment. A piece of music such as a MIDI file, a segment authored in DirectMusic Producer, or a segment formed at run time by the composer object.
  • Motif segment. A short piece of music to be played over the primary segment. Motifs are part of a style object, but you can also create short secondary segments from other sources and play them over the primary segment just like motifs.
  • Band segment. A set of instruments and instrument settings for the various channels in the performance. The application can play a band segment to execute changes in the band performing the music.
  • Template segment. A guide to chord progressions, groove levels, and embellishments, used in conjunction with a style and chordmap to compose music at run time. Unlike other segments, a template segment is never played directly by an application; instead, it is passed to the composer object to be used in creating a musical segment.

The playback of segments is controlled by the IDirectMusicPerformance interface. An instance of a playing segment is represented by an IDirectMusicSegmentState interface, which can be used to retrieve information about the current state of the segment.

Only one primary segment can play inside a performance. When you cue a primary segment for playback, using the IDirectMusicPerformance::PlaySegment method, you can specify that it is to be played after the currently playing segment is finished, or you can use it to replace the current primary segment.

Secondary segments, on the other hand, play on top of the current primary segment, and any number of secondary segments can be playing simultaneously.

Secondary segments do not normally alter the performance of the primary segment. For example, a secondary segment can be based on a different style without affecting the style of the primary segment. However, a secondary segment can be designated a control segment, in which case it takes over the task of responding to IDirectMusicPerformance::SetParam and IDirectMusicPerformance::GetParam calls, which normally go to tracks in the primary segment. Thus a control segment might control the current chord or groove level. For more information, see Tracks.

For more information on control segments, see DMUS_SEGF_FLAGS.

For more information on segment playback, see Segment Timing.


Tracks

Tracks are the components of a segment that contain its sequenced data, including information about notes, underlying chords, tempo, patch and band changes, and everything else the performance needs to know in order to play a piece of music.

Each track is represented by an IDirectMusicTrack interface. The methods of this interface are called by the performance, and most applications will not need to use them directly.

When an application calls IDirectMusicPerformance::PlaySegment, DirectMusic begins calling the IDirectMusicTrack::Play method on the segment's tracks. Most tracks respond by immediately generating timestamped messages containing data that is valid for the part of the segment that is being played. These messages are placed in a queue. (See Message Creation and Delivery for more information about what happens after that.)

A few tracks do not actively generate messages in response to IDirectMusicTrack::Play but instead do their work by responding to requests for information that come from the performance or other tracks in the form of a GetParam call. (See Setting and Retrieving Track Parameters.)

The following list shows the standard track types implemented by DirectMusic, with a brief description of each one. For a list of the methods supported by the standard tracks, see the reference for IDirectMusicTrack.

  • Band. Downloads DLS data to the performance. Sends messages of type DMUS_PATCH_PMSG, DMUS_TRANSPOSE_PMSG, DMUS_CHANNEL_PRIORITY_PMSG, and DMUS_MIDI_PMSG (for volume and pan). Used in segments based on MIDI files and styles.
  • Chord. Used to convert music values (as stored in patterns) to MIDI values. Sends messages of type DMUS_NOTIFICATION_PMSG (for GUID_NOTIFICATION_CHORD notifications).
  • Chordmap. Used in template segments to compose chord tracks.
  • Command. Used in template segments to compose chord tracks, and in style segments to determine which patterns will be played. Sends messages of type DMUS_NOTIFICATION_PMSG (for GUID_NOTIFICATION_COMMAND notifications).
  • Motif. Used to play motifs to accompany other segments. Sends messages of type DMUS_CURVE_PMSG, DMUS_NOTE_PMSG, and DMUS_NOTIFICATION_PMSG (for GUID_NOTIFICATION_MEASUREANDBEAT notifications).
  • Mute. Used with either style-based or MIDI-based segments. Allows PChannels to be remapped to other PChannels or to be muted.
  • Sequence. Sends sequence messages of type DMUS_NOTE_PMSG and DMUS_MIDI_PMSG. Used in segments based on MIDI files. Also sends messages of type DMUS_CURVE_PMSG for segments saved in the .sgt format.
  • Signpost. Used in template segments to compose chord tracks.
  • Style. Fundamental track for segments based on styles. Sends messages of type DMUS_TIMESIG_PMSG, DMUS_CURVE_PMSG, DMUS_NOTE_PMSG, and DMUS_NOTIFICATION_PMSG (for GUID_NOTIFICATION_MEASUREANDBEAT notifications).
  • SysEx. Sends system exclusive messages of type DMUS_SYSEX_PMSG. Used in segments based on MIDI files.
  • Tempo. Sets the tempo of the performance by sending messages of type DMUS_TEMPO_PMSG.
  • Time Signature. Sends messages of type DMUS_TIMESIG_PMSG as well as GUID_NOTIFICATION_MEASUREANDBEAT notifications. Used in segments based on MIDI files.


Using Bands

A band is a choice of instruments assigned to particular parts in a style. At performance time, each instrument track is mapped to a PChannel, which stores the following information:

  • MIDI volume.
  • MIDI pan.
  • Transposition. If this value is nonzero, music notes on the channel are automatically transposed for the instrument.
  • The instrument's MIDI patch number, including MSB and LSB bank selects.
  • A reference to the DLS collection from which to load the instrument. Optionally, the referenced DLS collection is the standard General MIDI collection.

Segments and styles always contain at least one band, called the default band. Styles can contain additional bands. When you load a segment or style, the default band and any other bands are automatically loaded as well. However, you still need to download the DLS data for the instruments in any band you intend to use. You can retrieve a pointer to the default band by using the IDirectMusicStyle::GetDefaultBand method.

Other bands might be authored into the style and can be found and retrieved by using the IDirectMusicStyle::EnumBand and IDirectMusicStyle::GetBand methods. Bands can also be obtained from other style files or from band files. Once you have obtained an IDirectMusicBand interface, you have access to that band and can substitute it for the default band.

Loading a band from its own file is just like loading any other object in DirectMusic. For more information, see Loading Objects.

More information about bands is contained in the following topics:

  • Downloading and Unloading Bands
  • Making Band Changes Programmatically
  • Ensuring Timely Band Changes


Downloading and Unloading Bands

Before a band can be used, it must be downloaded to the performance. This step maps the instruments to PChannels and downloads the DLS data to the port.

By default, the application is responsible for downloading any band it uses. However, you can turn on automatic downloading of bands by setting a parameter on the band track, or by setting a global parameter. When automatic downloading is on, the instruments in the band are downloaded when the segment containing the band is cued. The instruments are automatically unloaded when the segment is stopped, unless another segment using the same instruments is cued to play immediately or is currently playing.

Note Automatic downloading should be used only when the timing of segment starts is not critical. Repeated loading and unloading of instruments takes time and can cause serious degradation of performance in complex musical environments.

Be aware also that automatic unloading, which is part of the automatic downloading mechanism, can lead to undesired results. For example, suppose you play a short secondary segment that changes the instrument on a channel. The instrument is automatically downloaded when the secondary segment starts, replacing the existing instrument. When the secondary segment ends, the instrument is automatically unloaded, with the result that there is now no instrument on that channel, and the channel plays silence.

Downloading a band makes the band available to the performance but does not actually perform any program changes. Program changes take place in response to messages generated by the segment's band track, which is typically authored into a segment file. For information on how to make program changes at run time, see Making Band Changes Programmatically.

Information about how to implement downloading and unloading of bands is contained in the following topics:

  • Automatically Downloading Bands
  • Manually Downloading Bands
  • Unloading Bands


Automatically Downloading Bands

You can turn on automatic downloading of bands in one of the following ways:

  • Call the IDirectMusicPerformance::SetParam method for the GUID_PerfAutoDownload parameter. See Setting and Retrieving Global Parameters, and the following example.
  • Call the IDirectMusicSegment::SetParam or IDirectMusicTrack::SetParam method for the GUID_Enable_Auto_Download parameter. See Setting and Retrieving Track Parameters.

In the following example, the global parameter for the performance pPerf is set to enable automatic downloading of bands:

BOOL fAuto = TRUE;
pPerf->SetGlobalParam(GUID_PerfAutoDownload, &fAuto, sizeof(BOOL));


Manually Downloading Bands

You can manually download a band in one of the following ways:

  • Obtain an IDirectMusicBand interface from a loaded object and call the IDirectMusicBand::Download method. (See the following example.) This is the best way to download the band if you want to unload it after any segments using the band have been released.
  • Call the IDirectMusicSegment::SetParam method for the GUID_Download parameter to download the band in the segment's band track. You can also use IDirectMusicPerformance::SetParam to set this parameter on the primary segment, or IDirectMusicTrack::SetParam to set it directly on the band track. See Setting and Retrieving Track Parameters.

There is no danger in downloading the same instrument multiple times. If an instrument appears in one band multiple times or if it appears in multiple bands that are all opened and downloaded at the same time, only one copy of the instrument actually is sent down to the synthesizer.

The following function loads a band from disk and downloads it:

HRESULT myDownloadBand(
    IDirectMusicLoader *pILoader,      // Loader interface
    IDirectMusicBand **ppBand,         // To retrieve pointer
    IDirectMusicPerformance *pPerf,    // Performance to use band
    WCHAR *pwszFile)                   // File to load

{
    HRESULT hr;
    DMUS_OBJECTDESC Desc;              // Descriptor

    // Start by initializing Desc with the file name and GUID
    // for the band object.

    wcscpy(Desc.wszFileName,pwszFile);
    Desc.dwSize = sizeof(Desc);
    Desc.guidClass = CLSID_DirectMusicBand;
    Desc.dwValidData = DMUS_OBJ_CLASS |
            DMUS_OBJ_FILENAME | DMUS_OBJ_FULLPATH;

    hr = pILoader->GetObject(&Desc, IID_IDirectMusicBand,
            (void **) ppBand);
    if (SUCCEEDED(hr))
    {

        // Download the band via the performance.
        hr = (*ppBand)->Download(pPerf);

    }
    return hr;
}


Unloading Bands

Bands take up memory, so they should be unloaded when they are no longer in use. If you have enabled automatic downloading of bands, the band associated with a segment are unloaded automatically when the segment ends. Otherwise you can manually unload a band in one of the following ways:

  • Call the IDirectMusicBand::Unload method.
  • Call the IDirectMusicSegment::SetParam method for the GUID_Unload parameter to unload the band in the segment's band track. You can also use IDirectMusicPerformance::SetParam to set this parameter on the primary segment, or IDirectMusicTrack::SetParam to set it directly on the band track. See Setting and Retrieving Track Parameters. For an example, see Tutorial 1, Step 6: Shutting Down DirectMusic.

Note that the IDirectMusicPerformance::CloseDown method also unloads any remaining downloaded instruments.


Making Band Changes Programmatically

Most often the band track in a loaded segment will perform program changes. However, you can also do so manually. First create a secondary segment with a call to the IDirectMusicBand::CreateSegment method, and then play that segment by calling IDirectMusicPerformance::PlaySegment. Typically you would use DMUS_SEGF_MEASURE or DMUS_SEGF_GRID (see DMUS_SEGF_FLAGS) in the dwFlags parameter to ensure that the band change takes effect on an appropriate boundary.

The following function creates a segment from a band and plays it:

/ * It is presumed that automatic downloading is turned on, or that the application has called pBand->Download. */

HRESULT myPlayBand(
    IDirectMusicBand *pBand,         // Pointer to band object
    IDirectMusicPerformance *pPerf,  // Performance to use band
    REFERENCE_TIME rfTime,           // Time to play at
    DWORD dwFlags)                   // Performance flags

{
    IDirectMusicSegment *pSegment;
    HRESULT hr = pBand->CreateSegment(&pSegment);
    if (SUCCEEDED(hr))
    {
        hr = pPerf->PlaySegment(pSegment,
                dwFlags | DMUS_SEGF_SECONDARY,
                rfTime,
                NULL);
        pSegment->Release();
    }
    return hr;
}

A performance can be playing instruments from more than one band at a time. For example, suppose your application is playing a primary segment using one band, and then plays a motif from a style that has a different band. As long as the instruments in the first band are mapped to different PChannels than the instruments in the second, no conflict arises. Note, though, that motif segments do not normally have their own band tracks, so you might get silence from the motif's PChannels unless you first create a band segment and play it. (It is possible to add a band track to a motif segment, but creating a separate band segment is easier.)


Ensuring Timely Band Changes

A consideration in playing band segments is the randomness in the timing of notes played by a style track. For instance, a note that is on measure 1 beat 1 may actually play earlier or later than measure 1 beat 1. The band segment doesn't know anything about this, with the result that some of the notes might play with the incorrect instrument.

To prevent this problem, an application should cue the band segment early. Suppose, for example, that you have a style segment pStyleSeg and a band segment pBandSeg. You want to play both the style segment and the band segment on the next measure boundary of the performance (pPerf). You know that the style contains notes that could go out up to 30 ticks earlier (in music time) than the start time of the segment. The following code ensures that the band segment is played 31 ticks before the style segment, so all instruments are in place before any note is played:

/* First get the time of the next measure and convert to
   music time. */

REFERENCE_TIME rtResolved;
MUSIC_TIME mtResolved;

pPerf->GetResolvedTime( 0, &rtResolved, DMUS_TIME_RESOLVE_MEASURE );
pPerf->ReferenceToMusicTime( rtResolved, &mtResolved );

/* Now play the band segment 31 ticks before the measure boundary. */

mtResolved -= 31;
pPerf->PlaySegment( pBandSeg, 0, mtResolved, NULL );

/* Play the style segment on the measure boundary. */

pPerf->PlaySegment( pStyleSeg, 0, 0, DMUS_TIME_RESOLVE_MEASURE );

Note If there is no randomness in the notes played by a segment, you don't need to worry about the timeliness of a band segment played at the same time. By default, all band segments start 1 tick early.


Timing

This section is an overview of various timing issues in DirectMusic. The following topics are discussed:

  • Master Clock
  • Reference Time vs. Music Time
  • Changing the Tempo
  • Performance Time
  • Prepare Time
  • Latency and Bumper Time
  • Segment Timing


Master Clock

To guarantee accurate timing with an acceptably low latency, DirectMusic incorporates a master clock in kernel mode. This clock is based on a hardware timer. DirectMusic automatically selects the system clock as the master clock, but an application can select a different one, such as the wave-out crystal on a sound card.

The master clock is a high-resolution timer that is shared by all processes, devices, and applications that are using DirectMusic. The clock is used to synchronize all music playback in the system. It is a standard IReferenceClock. The IReferenceClock::GetTime method returns the current time as a 64-bit integer (defined as the REFERENCE_TIME type) in increments of 100 nanoseconds.

To obtain an interface to the master clock, you call the IDirectMusic::GetMasterClock method.

You can choose a different master clock for your application, but only if there are no other DirectMusic applications running. First you get descriptions of all devices that can serve as the master clock, by using the IDirectMusic::EnumMasterClock method. Once you have obtained the GUID of the device you want to use as the master clock, you pass this to the IDirectMusic::SetMasterClock method.


Reference Time vs. Music Time

Reference time is the time returned by the master clock. It is a 64-bit value defined as type REFERENCE_TIME. Reference time is measured in units of 100 nanoseconds, more or less, so the clock ticks about 10 million times each second. The value returned by the IReferenceClock::GetTime method is relative to an arbitrary start time.

Music time is a 32-bit value defined as type MUSIC_TIME. It is not an absolute measure of time but is relative to the tempo. The clock is started when the performance is initialized, and ticks DMUS_PPQ times for each quarter-note. (DMUS_PPQ is currently defined as 768.)

To convert between the two kinds of time in a performance, you can use the IDirectMusicPerformance::MusicToReferenceTime and IDirectMusicPerformance::ReferenceToMusicTime methods.

When a segment is cued to play by a call to IDirectMusicPerformance::PlaySegment and the start time is given in reference time, DirectMusic must convert the start time to music time. If no primary segment is currently playing, the conversion is done immediately, based on the current tempo. Otherwise, if another segment is playing, the start time of the cued segment is not converted to music time until the start time has been reached.

If the tempo is changed before the segment starts playing, the actual start time can be affected, or the segment might not start on the desired boundary. In the first case, where the conversion to music time is done immediately, the actual start time (in reference time) will be advanced if the tempo speeds up and delayed if the tempo is slowed down. In the second case, where conversion is done at start time, a change in tempo can mean that the segment does not start at correct resolution boundaries. For example, if the segment is supposed to start on a measure boundary (as indicated in the dwFlags parameter of PlaySegment), the actual start time (in reference time) is calculated when the segment is cued, but if the tempo then changes, a measure boundary might not fall at that time.

When a primary segment is passed to PlaySegment with the DMUS_SEGF_QUEUE flag (see DMUS_SEGF_FLAGS), the i64StartTime parameter is ignored and the segment is cued to play after any primary segments whose start times have already been converted. If a previously cued segment is still stamped in reference time, that segment will play at its designated time, perhaps interrupting another segment.

An example should make this clearer. Say you have three segments, each 10 seconds in length. You cue segment A to play 5 seconds from now. Because no primary segment is currently playing, the start time is immediately converted to music time. At 6 seconds you cue segment B to play at 20 seconds of reference time. In this case, because music is already playing and the tempo might change, the conversion to music time is not done immediately. Then you cue segment C with the DMUS_SEGF_QUEUE flag, so that it will start immediately after segment A finishes, at 15 seconds. At 20 seconds segment B will start playing and interrupt segment C.


Changing the Tempo

The tempo of a performance dictates the conversion between the two types of time used in DirectMusic, which in turn controls the resolution of events to musical boundaries. (See Reference Time vs. Music Time.) The tempo track of the primary segment usually controls the tempo, but it is also possible for an application to set the tempo dynamically.

There are two ways to do so: by sending a message, and by setting a track parameter.

The following example sends a message to change the tempo:

/* Assume that pIDMSegment is a valid IDirectMusicSegment, and
   IDMPerformance is a valid IDirectMusicPerformance. */

// Disable tempo track in segment so that it does not reset tempo
pIDMSegment->SetParam( GUID_DisableTempo, 0xFFFF,0,0, NULL );

DMUS_TEMPO_PMSG* pTempo;

if( SUCCEEDED(pIDMPerformance->AllocPMsg(
        sizeof(DMUS_TEMPO_PMSG), (DMUS_PMSG**)&pTempo)))
{
    // Queue tempo event
    ZeroMemory(pTempo, sizeof(DMUS_TEMPO_PMSG));
    pTempo->dwSize = sizeof(DMUS_TEMPO_PMSG);
    pTempo->dblTempo = 100;
    pTempo->dwFlags = DMUS_PMSGF_REFTIME;
    pTempo->dwType = DMUS_PMSGT_TEMPO;
    pIDMPerformance->SendPMsg((DMUS_PMSG*)pTempo);
}

The following sample code shows how to change the tempo parameter. For more information, see Setting and Retrieving Track Parameters.

DMUS_TEMPO_PARAM Tempo;
Tempo.dblTempo = 100;
pIDMSegment->SetParam(GUID_TempoParam, 0xFFFF, 0, 0, &Tempo);


Performance Time

When a performance is initialized, it starts keeping an internal clock based on the current reference time. You can retrieve the current performance time in both reference time and music time by using the IDirectMusicPerformance::GetTime method.

The IDirectMusicPerformance::AdjustTime method can be used to make small changes to the performance time. Most applications will never need to do this, but it can be useful when synchronizing to another source.


Prepare Time

As a segment is played, the performance makes repeated calls to IDirectMusicTrack::Play on the segment's tracks, causing them to generate messages for the supplied time range, which is some fraction of a second. These messages are then placed in the queue behind those that were generated in previous calls. By default, about a second's worth of messages are in the queue at any given time. The size of the queue can be changed by calling the IDirectMusicPerformance::SetPrepareTime method, and the current size can be retrieved by using IDirectMusicPerformance::GetPrepareTime.

For an illustration, see Latency and Bumper Time.

You can think of the queue as being like a gas tank that is constantly being topped up by calls to IDirectMusicTrack::Play. Each time the performance calls Play, it calculates the end time for that call by adding the prepare time to the current time. If the current time is 10,000 milliseconds (or the equivalent in REFERENCE_TIME units) and the prepare time is the default 1000 ms, then the end time is 11,000 — that is, all new messages that are to play up to time 11,000 must now be prepared and placed in the queue.

Most applications don't need to change the default prepare time, and the process just described is not visible to the application. However, it is helpful to understand the concept of prepare time because of the DMUS_SEGF_AFTERPREPARETIME flag, which the application can pass to IDirectMusicPerformance::PlaySegment.

Normally, if you set a start time of "now" for the segment, the performance invalidates any messages currently in the queue. Any tracks that are still valid at this point (for example, tracks of secondary segments that continue to play despite the introduction of a new primary segment) then have to resend their messages, taking into account any changes made to the the musical environment by the new segment. To avoid unnecessary processing and to ensure continuity (for example, to ensure that a long note or non-musical DLS sound is not cut short), you can use the DMUS_SEGF_AFTERPREPARETIME flag to specify that the segment is not to start playing until all messages currently in the queue have been processed and passed to the port buffer. So, for example, if messages up to time 10,000 are in the queue, and the current time is 9,000, a segment cued to play immediately will actually start playing just after the 10,000 ms mark.

For more information, see Segment Timing.


Latency and Bumper Time

Latency is the delay between when the port receives a musical message and when it has synthesized enough of a wave to play. The IDirectMusicPerformance::GetLatencyTime method retrieves the current time plus the latency for the performance as a whole. This is the largest value returned by any of the ports' latency clocks.

The bumper is an extra amount of time allotted for code to execute between the time that a musical event is put into the port buffer and the time that the port actually starts to process it. By default the bumper length is 50 milliseconds. An application can change this value by using the IDirectMusicPerformance::SetBumperLength method and retrieve the current value by calling IDirectMusicPerformance::GetBumperLength.

Here's an example of how latency time and bumper time are combined. Suppose an event is supposed to play at 10,000 milliseconds. The latency of the port is known to be 100 ms, and the bumper length is at its default value of 50 ms. The performance therefore places the message into the port buffer at 9,850 ms.

Note that once a message has been placed in the port buffer, it no longer belongs to the performance and cannot be stopped from playing by using the IDirectMusicPerformance::Invalidate or IDirectMusicPerformance::Stop methods. The first message that can be invalidated will have a time stamp equal to or greater than the current time plus the latency and bumper time. This value can be retrieved by using the IDirectMusicPerformance::GetQueueTime method.

The following diagram, not to scale, illustrates the relationship of the times and durations retrieved by various methods. The current time is at the left, and the last time for which messages have been prepared is at the right. Remember that prepare time is only an approximation of the total timespan of messages in the queue at any given moment.


Segment Timing

Segments play from the beginning, unless a start point is set by a call to the IDirectMusicSegment::SetStartPoint method. If a repeat count is set by using IDirectMusicSegment::SetRepeats, the entire segment will repeat that number of times, unless a loop has been defined by a call to IDirectMusicSegment::SetLoopPoints, in which case only the part of the segment between the loop points will repeat.

The performance time at which the segment starts playing is determined by two parameters of IDirectMusicPerformance::PlaySegment:

  • The i64StartTime parameter sets the earliest time at which the segment can start playing. If i64StartTime is 0, this time is as soon as possible. The actual time when the segment will start depends on the type of segment. If it is a primary or control segment, the earliest start time is at queue (or flush) time. If it is a non-control secondary segment, the earliest start is at latency time. For more information on queue time and latency time, see Latency and Bumper Time.
  • The dwFlags parameter determines how soon after the scheduled time the segment should actually start playing, depending on the rhythm of the currently playing segment. Most often you will want to wait for an appropriate moment before introducing a new segment, a transition, or a motif. You control the delay by setting one of the following DMUS_SEGF_FLAGS:
    DMUS_SEGF_AFTERPREPARETIME
    Play at the earliest start time plus the prepare time. This ensures that any messages from the currently playing segment that have already been queued to the port are not invalidated. This saves processing time and also ensures that any motifs continue to play smoothly over a transition from one primary segment to another.
    DMUS_SEGF_GRID
    Play on a grid boundary. A grid is a subdivision of a beat. The time signature (authored into the style) determines how many grids each beat is divided into.
    DMUS_SEGF_BEAT
    Play on a beat.
    DMUS_SEGF_MEASURE
    Play at the beginning of a measure.
    DMUS_SEGF_DEFAULT
    Use the cued segment's default boundary. You can set this value by using the IDirectMusicSegment::SetDefaultResolution method.

If none of these flags is set, the segment will start playing at exactly the earliest start time.


Notification and Event Handling

From time to time your application may need to respond to a music event; for example, you might need to know when the end of a segment has been reached. You get this information by asking DirectMusic to notify you when a certain type of event has taken place.

You specify what types of music events you want to be notified of by calling the IDirectMusicPerformance::AddNotificationType method once for each desired type of event. The following example tells DirectMusic to set segment-related events. The actual type of event (such as segment start or segment end) will be derived later from the notification message.

/* It is assumed that pPerformance is a valid
   IDirectMusicPerformance pointer. */

GUID guid = GUID_NOTIFICATION_SEGMENT;
// C syntax:
pPerformance->AddNotificationType(&guid);
// C++ syntax:
pPerformance->AddNotificationType(guid);

Notifications are sent in the form of a DMUS_NOTIFICATION_PMSG message structures. You can poll for any pending notification messages within the Windows message loop by calling the IDirectMusicPerformance::GetNotificationPMsg method, or else you can have DirectMusic signal an event object in a separate thread when a message is pending. (See Using Notification Events.)

More than one message may be waiting when an event is signaled, or when you call GetNotificationPMsg in the message loop. To be sure of catching all notifications, you must call GetNotificationPMsg repeatedly until it returns S_FALSE. Multiple messages with the same time stamp are not queued in any particular order.

It is your responsibility to free any message you retrieve, by calling the IDirectMusicPerformance::FreePMsg method.


Using Notification Events

If you wish to be alerted of pending DirectMusic notification messages by a Windows event object, you must first obtain an event handle by calling the Win32 CreateEvent function. Typically you would create an auto-reset event with a call such as this:

HANDLE g_hNotify = CreateEvent(NULL, FALSE, FALSE, NULL);

Note It is not necessary to create an event in order to retrieve notification messages in your application's message loop. As long as you have requested notifications by calling the IDirectMusicPerformance::AddNotificationType method, the performance will send DMUS_NOTIFICATION_PMSG messages which can be retrieved by calling IDirectMusicPerformance::GetNotificationPMsg.

After creating the event, you assign the handle to the performance by passing it to the IDirectMusicPerformance::SetNotificationHandle method. You can use the second parameter of this method to change the default time that DirectMusic will hold onto the event if it is not retrieved; a value of 0 in this parameter indicates that the default time of 2 seconds is to be used.

In the following example, g_pPerf is a valid pointer to the IDirectMusicPerformance interface:

g_pPerf->SetNotificationHandle(g_hNotify, 0);

The following sample function executes repeatedly in its own thread, checking for signaled events and retrieving notification messages.

void WaitForEvent( LPVOID lpv)
{
    DWORD dwResult;
    DMUS_NOTIFICATION_PMSG* pPmsg;
    char szCount[4];

    while (TRUE)
    {
        dwResult = WaitForSingleObject(g_hNotify, 100);
        while (S_OK == g_pPerf->GetNotificationPMsg(&pPmsg))
        {
            // Check notification type and do something in response.
            .
            .
            .
            g_pPerf->FreePMsg((DMUS_PMSG*)pPmsg);
        }
    }
}

This thread is executed as follows:

_beginthread(WaitForEvent, 0, NULL);

When notifications are no longer needed, the following code shuts down the thread, removes the notification handle from the performance, and destroys the event object.

_endthread();
g_pPerf->SetNotificationHandle(0, 0);
CloseHandle(g_hNotify);


Music Parameters

DirectMusic lets you control many aspects of track behavior by changing parameters on the fly, using one of the following SetParam methods:

  • IDirectMusicPerformance::SetParam sets data on a specific track within the current control segment of this performance. The control segment is normally the primary segment, but a secondary segment can be designated as the control segment when it is played. See DMUS_SEGF_FLAGS.
  • IDirectMusicSegment::SetParam sets data on a specific track within this segment.
  • IDirectMusicTrack::SetParam sets data on this track.

In addition, the IDirectMusicPerformance::SetGlobalParam method lets you set values that apply across the entire performance.

The equivalent GetParam and GetGlobalParam methods retrieve current values for a track or the performance.

In order to have the music respond immediately to a changed parameter, an application can flush messages from the queue by using the IDirectMusicPerformance::Invalidate method. This method causes all tracks to resend messages from the specified point forward.

More information about parameters is contained in the following topics:

  • Setting and Retrieving Track Parameters
  • Setting and Retrieving Global Parameters


Setting and Retrieving Track Parameters

You set and retrieve track parameters by using the SetParam and GetParam methods of either the performance, the segment, or the track.When calling one of these methods on the performance or segment, you can identify the track by setting the dwGroupBits and dwIndex parameters. However, in most cases you can let DirectMusic find the appropriate track for you. For more information, see Identifying the Track.

In some cases you need to specify the time within the track at which the change is to take effect, or for which the parameter is to be retrieved. To see whether this value is used for a particular track parameter, see Track Parameter Types.

In the case of a few parameters, a call to SetParam simply turns a feature on or off, and no data is needed. When setting other parameters, however, you also need to supply a structure or variable containing the data. Only parameters with associated data can be retrieved, so when using GetParam you must always supply a pointer to an appropriate variable or structure to receive the data.

To determine whether a particular parameter is supported by a track, use the IDirectMusicTrack::IsParamSupported method and check for an S_OK result.

More information is given in the following topics:

  • Identifying the Track
  • Track Parameter Types
  • Disabling and Enabling Messages on a Track


Identifying the Track

When you set or retrieve a parameter by using IDirectMusicTrack::SetParam or IDirectMusicTrack::GetParam, the parameter is of course associated with the track on which the method is called. However, when you call IDirectMusicPerformance::SetParam, IDirectMusicPerformance::GetParam, IDirectMusicSegment::SetParam, or IDirectMusicSegment::GetParam, DirectMusic needs to find the appropriate track.

Normally you can let DirectMusic figure out which track contains the desired parameter. To do this, set dwGroupBits to 0xFFFFFFFF (or -1) and dwIndex to 0. For example, the following call to IDirectMusicSegment::SetParam turns off the tempo track so that looping a segment does not reset the tempo:

pIDMSegment->SetParam(GUID_DisableTempo, 0xFFFFFFFF, 0, 0, NULL);

There are times, however, when you need to identify a specific track. Typically this would be the case when a segment contains multiple tracks of the same type. In order to set or retrieve the parameter on the desired track, you need to identify it by group and index value.

Every track belongs to one or more groups, each group being represented by a bit in the dwGroupBits parameter of the one of the methods under discussion. (The track is assigned to a group or groups when it is inserted in the performance. See IDirectMusicSegment::InsertTrack. In the case of segments loaded from a file, track groups are assigned by the author of the segment.)

A track is identified by a zero-based index value within each of the groups it belongs to. The index value is determined by the order in which the tracks were inserted.

Suppose a segment contains the following tracks:

Track | Group bits
A | 0x1
B | 0x2
C | 0x1
D | 0x3

Note that group 1 contains tracks A, C, and D, and group 2 contains tracks B and D. Now if you call GetParam or SetParam with a value of 1 in dwGroupBits and a value of 0 in dwIndex, the parameter is retrieved from track A, which is the first track in group 1. If dwIndex is 1, the parameter is retrieved from track C, the second track in the group. Track D belongs to two groups, 1 and 2, so it can be identified as either dwGroupBits = 1 and dwIndex =2, or dwGroupBits = 2 and dwIndex = 1.

If you set more than one bit in dwGroupBits, the parameter is retrieved from the nth track containing any of those bits, where n is the value in dwIndex.


Track Parameter Types

The track parameter that is being set or retrieved by one of the SetParam or GetParam methods is identified by a GUID in the rguidType parameter of the method. Each parameter that requires data is associated with a particular data type, and pParam must point to a variable or structure of this type. In some cases, part of the data structure must be initialized even when calling GetParam.

The predefined parameters are listed in the following table, which will take you to tables with more detailed information about each parameter. In the detailed tables, note that pParam and mtTime refer to the parameters of the various GetParam and SetParam methods. Note also that although parameters are always associated with particular track types, most often you will call the method on the segment or the performance and let DirectMusic find the appropriate track. (See Identifying the Track.)

GUID_ChordParam | GUID_EnableTimeSig
GUID_Clear_All_Bands | GUID_IDirectMusicBand
GUID_CommandParam | GUID_IDirectMusicChordMap
GUID_ConnectToDLSCollection | GUID_IDirectMusicStyle
GUID_Disable_Auto_Download | GUID_MuteParam
GUID_DisableTempo | GUID_RhythmParam
GUID_DisableTimeSig | GUID_StandardMIDIFile
GUID_Download | GUID_TempoParam
GUID_Enable_Auto_Download | GUID_TimeSignature
GUID_EnableTempo | GUID_Unload


GUID_ChordParam
Track type | Chord.
Purpose | Set or retrieve a chord change.
Data Type (*pParam) | DMUS_CHORD_PARAM
mtTime | The time, in track time, at which to add the chord to the track, or the time at or directly after the chord to be retrieved from the track.


GUID_Clear_All_Bands
Track type | Band.
Purpose | Clear all bands from the track.
Data Type (*pParam) | None.
mtTime | Not used.


GUID_CommandParam
Track type | Command.
Purpose | Set or retrieve a groove or embellishment command.
Data Type (*pParam) | DMUS_COMMAND_PARAM.
mtTime | The time, in track time, at which to add the command to the track, or the time at or directly after the command to be retrieved from the track.


GUID_ConnectToDLSCollection
Track type | Band.
Purpose | Connect a band to a DLS collection. See Playing a MIDI File with Custom Instruments.
Data Type (*pParam) | IDirectMusicCollection pointer.
mtTime | Not used.


GUID_Disable_Auto_Download
Track type | Band.
Purpose | Disable automatic downloading of instruments. See Using Bands
Data Type (*pParam) | None.
mtTime | Not used.


GUID_DisableTempo
Track type | Tempo.
Purpose | Disable tempo messages. See Disabling and Enabling Messages on a Track.
Data Type (*pParam) | None.
mtTime | Not used.


GUID_DisableTimeSig
Track type | Time signature, style, motif.
Purpose | Disable time signature messages. See Disabling and Enabling Messages on a Track.
Data Type (*pParam) | None.
mtTime | Not used.


GUID_Download
Track type | Band.
Purpose | Download instrument data for the track's bands. See Playing a MIDI File with Custom Instruments. See also GUID_Unload.
Data Type (*pParam) | IDirectMusicPerformance pointer.
mtTime | Not used.


GUID_Enable_Auto_Download
Track type | Band.
Purpose | Enable automatic downloading of instruments. See Using Bands.
Data Type (*pParam) | None.
mtTime | Not used.


GUID_EnableTempo
Track type | Tempo.
Purpose | Enable tempo messages. See Disabling and Enabling Messages on a Track.
Data Type (*pParam) | None.
mtTime | Not used.


GUID_EnableTimeSig
Track type | Time signature, style, motif.
Purpose | Disable time signature messages. See Disabling and Enabling Messages on a Track.
Data Type (*pParam) | None.
mtTime | Not used.


GUID_IDirectMusicBand
Track type | Band.
Purpose | Set a band.
Data Type (*pParam) | IDirectMusicBand
mtTime | The time, in track time, at which to add the band to the track.


GUID_IDirectMusicChordMap
Track type | Chordmap.
Purpose | Set or retrieve the chordmap.
Data Type (*pParam) | IDirectMusicChordMap pointer (SetParam) or address of a variable to receive this pointer (GetParam).
mtTime | The time, in track time, at which to add the chordmap to the track, or the time at or directly after the chordmap to be retrieved from the track.


GUID_IDirectMusicStyle
Track type | Style.
Purpose | Set or retrieve the style.
Data Type (*pParam) | IDirectMusicStyle pointer (SetParam) or address of a variable to receive this pointer (GetParam).
mtTime | The time, in track time, at which to add the style to the track, or the time at or directly after the style to be retrieved from the track.


GUID_MuteParam
Track type | Mute.
Purpose | Set or retrieve channel mapping information.
Data Type (*pParam) | DMUS_MUTE_PARAM. The dwPChannel member must be initialized before this structure is passed to GetParam.
mtTime | The time, in track time, at which to add the mute event to the track, or the time at or directly after the mute event to be retrieved from the track.


GUID_RhythmParam
Track type | Chord.
Purpose | Retrieve the rhythm pattern for a sequence of chords stored in a measure in the track.
Data Type (*pParam) | DMUS_RHYTHM_PARAM. The TimeSig member must be initialized before this structure is passed to GetParam.
mtTime | The time, in track time, at or directly after the beginning of the measure containing the rhythm pattern to be retrieved from the track.


GUID_StandardMIDIFile
Track type | Band.
Purpose | Ensure that a standard MIDI file (one not authored specifically for DirectMusic) plays correctly.
Data Type (*pParam) | None.
mtTime | Not used.

Note This parameter must be set for any segment based on a standard MIDI file before any instruments are downloaded.


GUID_TempoParam
Track type | Tempo.
Purpose | Set or retrieve the tempo.
Data Type (*pParam) | DMUS_TEMPO_PARAM. For SetParam, the mtTime member of the structure is ignored. For GetParam, the mtTime member will receive the offset of the tempo change from the requested time, and will always be 0 or less.
mtTime | The time, in track time, at which to set the tempo, or at or directly after the tempo change to retrieve.


GUID_TimeSignature
Track type | Time signature, style.
Purpose | Retrieve the time signature.
Data Type (*pParam) | DMUS_TIMESIGNATURE. The mtTime member will receive the offset of the time signature change from the requested time, and will always be 0 or less.
mtTime | The time, in track time, at which to set the time signature, or at or directly after the time signature change to retrieve.


GUID_Unload
Track type | Band.
Purpose | Unload instrument data for the track's bands. See also GUID_Download.
Data Type (*pParam) | IDirectMusicPerformance pointer.
mtTime | Not used.


Disabling and Enabling Messages on a Track

By setting the GUID_DisableTempo and GUID_DisableTimeSig parameters on a track, you can disable the generation of DMUS_TEMPO_PMSG and DMUS_TIMESIG_PMSG messages respectively. You might want to do this, for example, when you have set the tempo dynamically and do not want the primary segment to send tempo messages.

To re-enable messages, call one of the SetParam methods with GUID_EnableTempo and GUID_EnableTimeSig as the rguidType parameter. You can also set these parameters to force a segment to send tempo messages even though it is not the control segment, or to cause a secondary segment to send time signature messages. (For more information on control segments, see Segments and DMUS_SEGF_FLAGS.)

For more information on how to set a parameter, see Setting and Retrieving Track Parameters.

See also the Remarks for IDirectMusicTrack::IsParamSupported.


Setting and Retrieving Global Parameters

By using the IDirectMusicPerformance::SetGlobalParam and IDirectMusicPerformance::GetGlobalParam methods, you can set and retrieve certain parameters that affect the entire performance rather than a single track.

The parameter to be set or retrieved is identified by a GUID in the rguidType parameter of the method. Each parameter is associated with a particular data type, whose size is given in the dwSize parameter. The predefined GUIDs and their data types are shown in the following table.

Parameter type GUID (rguidType) and Data (*pParam) | Description
GUID_PerfAutoDownload BOOL | This parameter controls whether instruments are automatically downloaded when a segment is played. By default it is off. See Downloading and Unloading Bands.
GUID_PerfMasterTempo float | The master tempo is a scaling factor that is applied to the tempo by the final output tool. By default it is 1. A value of 0.5 would halve the tempo, and a value of 2.0 would double it. This value can be set in the range DMUS_MASTERTEMPO_MIN to DMUS_MASTERTEMPO_MAX.
GUID_PerfMasterVolume long | The master volume is an amplification or attenuation factor, in hundredths of decibels, applied to the default volume of the entire performance. The range of permitted values is determined by the port. Legacy hardware MIDI ports do not support changing master volume.
GUID_PerfMasterGrooveLevel char | The master groove level is a value that is always added to the groove level established by the command track. The resulting value is adjusted, if necessary, to fall within the range 1 to 100.

Applications can also use custom types of global parameters. To create a new type, simply establish a GUID and a data type for it. When the parameter is set, the performance allocates memory for the data, and contents of this memory can be retrieved by a call to IDirectMusicPerformance::GetGlobalParam.


Capturing Music

Capturing MIDI messages from a device such as a keyboard is very easy in DirectMusic.

Typically you would create a port for the capture device and use its IDirectMusicPort::SetReadNotificationHandle method to cause an event to be signaled whenever messages are available to be read. In response to the event, call IDirectMusicPort::Read method repeatedly to place pending events into a buffer, until S_FALSE is returned. Each time Read is called, as many events are put into the buffer as are available, or as will fit into the buffer. If at least one event was put into the buffer, S_OK is returned.

To retrieve events from the buffer, you call the IDirectMusicBuffer::GetNextEvent method. Each call retrieves a single event, until no more are available, at which point S_FALSE is returned.

The following code fragment illustrates this process:

/* Assume that hEvent was created with CreateEvent and
   given to the capture port pPort by a call to
   SetReadNotificationHandle. Assume also that pBuffer was
   initialized by IDirectMusic::CreateMusicBuffer. */

REFERENCE_TIME rt;
DWORD          dwGroup;
DWORD          cb;
BYTE          *pb;

DWORD dw = WaitForMultipleObjects(1, hEvent, FALSE, INFINITE);
for (;;)
{
    hr = pPort->Read(pBuffer);
    if (hr == S_FALSE)
      {
          break;  // No more messages to read into buffer
      }
    pBuffer->ResetReadPtr();
    for (;;)
    {
        hr = pBuffer->GetNextEvent(&rt, &dwGroup, &cb, &pb);
        if (hr == S_OK)
        {
            // pb points to the data structure for the message and
            // you can do with it what you want.
        }
        else if (hr == S_FALSE)
        {
            break;  // No more messages in buffer
        }
    }  // Done with buffer
}  // Done reading pending events

If you do not wish to intercept messages but simply want to send them from one port to another, you can use the IDirectMusicThru interface.


DirectMusic Tools

In DirectMusic parlance, a tool is an object that intercepts messages and handles them in some way. The tool might alter the message and then pass it on to the next tool, or free the message, or send a new message based on information in the old one.

DirectMusic has an output tool that is normally the last in line to receive messages. It is this tool that converts performance messages to standard MIDI messages and streams them to the synthesizer. Other tools are implemented by the application or obtained from libraries.

To implement a tool you must first create an object that supports the IDirectMusicTool interface. The object's implementation of the IDirectMusicTool methods will determine what messages get processed by the tool and what work is performed on these messages.

All tools other than the output tool are normally collected in graphs, and even if your application is using only one other tool, you should create a DirectMusicGraph to contain it. You then add this graph to a segment or the performance. Graphs provide a convenient mechanism for directing messages from one tool to another.

When the performance engine is playing a segment, it gives each tool in the segment graph and then each tool in the performance graph a chance to process each message. After a tool processes a message, it should call the IDirectMusicGraph::StampPMsg method (obtaining the IDirectMusicGraph pointer from the pGraph member of the DMUS_PMSG structure) to stamp the message with a pointer to the next tool, if any, that is to receive it. Then the tool puts the message back in the pipeline.

Tools process messages in a high-priority thread. Do not call time-consuming functions, such as those involving graphics or file input/output, from within a tool's IDirectMusicTool::ProcessPMsg method. If a tool needs to trigger an action, it should do so by signaling a different thread, perhaps the application's main thread.

When implementing the methods of IDirectMusicTool, you must take care not to create circular references to parent objects. Circular references come about when one object creates another and the child keeps an additional reference to the parent. For example, suppose a tool creates a new reference to the graph passed into its IDirectMusicTool::Init method. If the tool fails to release this reference, there is a problem when the segment attempts to release the graph. Because the tool still has a reference to the graph, the graph is not fully released; and because the graph has a reference to the tool, the tool cannot be released either.

For a more detailed look at how to set up a tool, see Tutorial 2: Using Tools.


Music Composition

This section is an introduction to the composition engine of DirectMusic. As a software developer, you can use the engine to implement a dynamic musical program, using previously authored elements such as styles, templates, and bands.

The following topics are discussed in this section:

  • Overview of Music Authoring
  • Music Files for Composition
  • Overview of Programming for Composition
  • How Music Varies During Playback
  • Music Values and MIDI Notes
  • Using Compositional Elements


Overview of Music Authoring

The author of compositional music elements uses a tool such as DirectMusic Producer to create the basic elements of each musical theme required by your program. The following brief introduction to these elements is intended to help software developers understand the content they are dealing with. For more information on all of the following topics, see the documentation for DirectMusic Producer.

  • Authoring Styles
  • Authoring Chordmaps
  • Authoring Style-Based Segments
  • Authoring MIDI-Based Segments
  • Authoring Templates
  • Authoring Bands

Note In this section the human composer will be referred to as the author, in order to avoid confusion with the composer object of DirectMusic.


Authoring Styles

A style is a basic definition of the music. It is a collection of patterns, along with a time signature (meter) and a tempo (beats per minute). A style may also contain one or more bands.

A pattern is a musical figure one or more measures long consisting of a basic sequence of notes for each instrument, or part. These notes are not fixed but will ultimately be mapped to particular pitches according to the current key, chord, and play mode. Patterns also include variations.

A motif is a special type of pattern designed to be played solo over the basic score. Typically a motif would be used in an interactive application to mark an event: for example, the drumbeat that occurs in the DMDonuts sample whenever the ship hits the edge of the screen.

In DirectMusic Producer, patterns are both created by the author on a grid analogous to a piano roll. Each part has its own row (corresponding to a PChannel) on which notes are represented by bars of varying length (duration), thickness (velocity), position on a vertical scale (pitch), and position on a horizontal scale (time).

The author can create many variations for each pattern. Typically he or she would do this by copying the pattern and then making small changes to one or more parts. At run time, variations will be chosen by the style playback mechanism. However, the author can disable any variation for any chord—that is, specify that the variation must never be chosen when a certain chord is being played.

The author also assigns a groove range to the pattern, specifying the groove levels at which the pattern can be played. The pattern can also be designated as an embellishment. Embellishments are of four types—intro, fill, break, and end—and a pattern can be assigned to one or more of these categories. When the music is played and a certain type of embellishment is called for, only patterns of that type are candidates for playback.


Authoring Chordmaps

Much modern music, especially music in the popular, rock, folk and jazz idioms, is based on the concept of chord progression, meaning that all the notes played within a given span of time are associated with a certain chord, and the music moves harmoniously from one chord to another.

The notes within a pattern authored for DirectMusic are derived from or intended to harmonize with a single chord. At run time, however, the pattern is transposed according to the chord progression—that is, each time the underlying chord changes, DirectMusic modifies the pitch of the notes accordingly.

The chordmap is a roadmap of chord progressions. Within the chordmap designer, the author chooses chords that can express the desired musical feeling or personality. He or she then arranges these chords in a flowchart along a time line. (The time line is conceptually circular, so it keeps looping back to the beginning as long as that segment of music is being played.)

Certain important chords are designated as signposts. These are chords that must be played at certain points. The music is always moving from one signpost to the next. Between the signposts, however, the chord progression may follow various routes from one chord to another, as mapped out by the author.

The actual route through the chord chart may be chosen at run time by the composition engine, providing variation over and above that found in the patterns themselves. Or it may be chosen by the authoring tool when the author is creating a segment.

A chord in the chordmap can actually consist of several different chords, referred to as subchords. In order to achieve polytonality by playing different inversions of the same chord, the author can assign different parts to different subchords. Each subchord is valid for one or more levels (see DMUS_SUBCHORD), and these are matched up with levels assigned to parts in the style.

Note DirectMusic allows up to DMUS_MAXSUBCHORD subchords in a chord, and this value is defined as 8. However, DirectMusic Producer currently allows authors to create a maximum of 4 subchords per chord.


Authoring Style-Based Segments

A style-based segment is a largely prebuilt piece of music that the author constructs from the following elements:

  • Style. As explained in Authoring Styles, a style consists of general information about the music (time signature, tempo, and so on) as well as patterns.
  • Chord progression. This might be derived automatically by the authoring tool from a chordmap (by choosing a path through the chord chart), or else entered manually by the author.
  • Series of commands for selecting appropriate patterns at set times. As explained under Authoring Styles, a characteristic of the patterns in styles is that they may be designated as embellishments (intro, fill, break, and end) and may also be assigned a certain groove range by the author. The command track of the segment might instruct the style playback engine to select an intro pattern and play it for the first measure, then play only patterns with a groove level of 25 for the next four measures, then play a break, and so on.
  • Band. The author can assign instruments and PChannels to all the parts played by the various patterns.


Authoring MIDI-Based Segments

A MIDI-based segment is created in DirectMusic Producer by importing a MIDI file. The author can then add tempo, key, and band changes as well as loop points. Unlike a style-based segment, a MIDI segment has no patterns and no command track. Instead it has a sequence track that contains MIDI notes and other commands.


Authoring Templates

A template is a segment, but unlike a style-based segment, it is not bound to a particular style and does not have a fixed chord progression.

Instead of a chord progression, the template has a series of signpost group markers along a time line. Signposts, as explained in Authoring Chordmaps, are chords that mark the beginning and end of regions where variations in the chord progression are possible. When the author creates a signpost, he or she assigns it to a group.

Here's what happens later, either within the authoring tool or at run time, when the DirectMusicComposer generates a segment by combining the template with a particular style and chordmap. Each time the engine encounters a pair of signpost group markers along the time line in the template, it looks in the chordmap for a pair of signpost chords that belong to that group. If it finds a pair, and if the interval between them fits into the time available, it follows the chord progression between those two signpost chords as defined in the chordmap. If it is unable to find a path that works, or if there is no end signpost marker, the engine simply plays any chord from the group of the beginning signpost group marker.

The author might use templates in order to apply similar chord progressions, groove levels, and embellishments to different styles while composing segments. But templates can also be combined with styles and chordmaps by the DirectMusicComposer object at run time.


Authoring Bands

A band is a set of instruments, together with their performance parameters, associated with particular parts in a piece of music. This is not the same as a DLS collection, which represents a set of instruments that can be downloaded to the synthesizer and thus made available to any application.

In a tool such as DirectMusic Producer, the author creates a band by assigning instruments to PChannels. These instruments can be from any DLS collection, and instruments from different sources can be mixed within a band. For example, a band might have a jazz guitar from the General MIDI set in part 1, a sixties organ from the Roland GS set in part 2, and an ethnic percussive instrument from a custom DLS collection in part 3. Each of these instruments is also given volume, pan, and transposition settings.

PChannels map instruments to parts. If a pattern calls for a particular note on PChannel 1, then that note will be played by the instrument in the current band that is assigned to PChannel 1. The sound is modified by the band's settings for the volume, pan, and transposition of that instrument.

Bands may be saved as separate files or included in styles or segments.


Music Files for Composition

When programming for DirectMusic composition, you will use a variety of files produced in a tool such as DirectMusic Producer. You load these elements into the application as COM objects and obtain interfaces to them. (See DirectMusic Loader.)

The following table summarizes the types of files you will encounter. The Class GUID is the value you put in the guidClass member of the DMUS_OBJECTDESC structure when loading the object.

Note Bands can be authored as part of a style, in which case they are automatically loaded when the style is loaded. Similarly, styles and bands can be authored into a segment, in which case you don't need separate files for those elements.

Files may also contain references to other files. If a style contains a reference to a band, the band is automatically loaded when the style is, provided the loader can find the band file.

Element | Class GUID | Interface | File Type
Band | CLSID_DirectMusicBand | IDirectMusicBand | .bnd
DLS Collection | CLSID_DirectMusicCollection | IDirectMusicCollection | .dls
ChordMap | CLSID_DirectMusicChordMap | IDirectMusicChordMap | .cdm
Segment | CLSID_DirectMusicSegment | IDirectMusicSegment | .sgt
Style | CLSID_DirectMusicStyle | IDirectMusicStyle | .sty
Template | CLSID_DirectMusicSegment | IDirectMusicSegment | .tpl


Overview of Programming for Composition

As a developer of software that implements music composed at run time, you will use previously authored objects as building blocks. In consultation with the author or other content provider, you can choose to get the musical data in the form of small building blocks that offer you the greatest possible flexibility and variation at run time, or you can use larger prefabricated elements that define the form of the music more fully.

Using the largest building blocks, you load highly structured segments (either style-based or MIDI-based) that contain everything the performance needs to know about the music in order to play it. All you have to do is load the segment and query for the IDirectMusicSegment interface. You pass this interface pointer to the IDirectMusicPerformance::PlaySegment method. The style playback engine then selects pattern variations from the style and plays them according to a fixed chord progression—or, in the case of a MIDI-based segment, simply plays the MIDI sequence. Band changes will usually be contained in the segment as well.

If you want to use smaller building blocks, you obtain the following elements:

  • Chordmaps, which are roadmaps of chord progressions.
  • Styles, which define a basic melody and rhythm together with variations, motifs, and embellishments.
  • Template segments, which are structural plans that control various aspects of playback including the length of the segment, whether it loops, where groove level changes and embellishment patterns are to be placed, and what types of chords in the chordmap are to serve as signposts.

You then construct a segment by combining any chordmap, style, and template, using the IDirectMusicComposer::ComposeSegmentFromTemplate method.

To have even more flexibility in music composition at run time, you can create segments based on predefined shapes rather than templates, using the IDirectMusicComposer::ComposeSegmentFromShape method. The shape is used in creating the command and signpost tracks, which control the groove level of the music, the choice of embellishment patterns, and the chord progression.

When playing segments, you can also control the band used to play the parts. Bands are typically authored right into styles and templates, but they may be supplied as separate files so that band changes can be made dynamically by the application. In this case, you must create a secondary segment containing only the band, using the IDirectMusicBand::CreateSegment method, and play this segment when it is time to assign instruments and instrument settings to the primary segment. For more information, see Using Bands.


How Music Varies During Playback

As DirectMusic plays a segment (other than a simple MIDI file or an authored segment based on a MIDI file), changes are made to the basic harmony and rhythm so that the performance does not sound static. Changes are partly scripted and partly random.

  • Choice of pattern. Typically a style contains multiple patterns, which are selected in response to commands from the command track. For example, if the command track calls for a break embellishment to be played, the style playback engine selects a break pattern that is compatible with the current groove level. (The author specifies which groove levels are appropriate for each pattern.) If there is more than one suitable pattern, a random choice is made.
  • Variations within a pattern. Any part within a pattern can have multiple variations. Variations may play in an order specified by the author; otherwise the style playback engine makes a random choice of variations on each repetition of the pattern.
  • Groove level. The current groove level of the segment determines which of the patterns in the style can be selected for playback. The current level is set by the command track, which is normally authored into a segment or template. However, the progression of groove levels is composed by the engine at run time if the segment is created by using the IDirectMusicComposer::ComposeSegmentFromShape method. A shape is simply a predefined pattern of intensity, such as "rising" or "consistently low." The current groove level of a segment can be changed programmatically by setting a track parameter (see GUID_CommandParam), and a modifier can be applied to all segments by setting the master groove level for the performance (see Setting and Retrieving Global Parameters).
  • Transposition. As the segment plays, the underlying chord changes according to the progression in the chord track. The notes in the current pattern are automatically transposed to harmonize with the new chord. The application can change the chord progression of an existing segment by using the IDirectMusicComposer::ChangeChordMap method.
  • Variations in timing. The playback engine can introduce small random changes in the parameters of individual notes—when they begin and when they end.
  • Band. The choice of instruments and instrument settings (volume, pan, and transposition) can be changed as the segment is playing, either by the band track within an authored segment or dynamically by the application. The application can change the band by creating a secondary segment with a call to IDirectMusicBand::CreateSegment, then playing that segment.

In many cases, applications will exert control over the music by playing different segments rather than by manipulating existing segments. For example, to have the music reflect a change in the intensity of a game, you can simply transition to a new segment authored for that intensity level. You can achieve a similar effect with a single style-based segment by having the author create patterns with different groove ranges, then changing the groove level in response to game events.

For more information on how to change the music at run time, see Music Parameters.


Music Values and MIDI Notes

Notes in a pattern within a DirectMusic style are not fixed notes. Rather they are music values that become actual notes only when they are transposed to the current chord according to the current play mode and subchord level.

A music value is a representation of the note's intended role. For example, a music value can say that a note is intended to be played as the second position in the chord, up one in the scale. When that music value is applied to a particular chord, it is converted to the appropriate MIDI note, the one in the second position in the chord, up one in the scale. For an explanation of the data format of music values, see DMUS_NOTE_PMSG.

The play mode determines how to interpret the note against the chord. For example, if the mode is DMUS_PLAYMODE_NORMALCHORD, the note is interpreted against the intervals of the chord and scale, based on the root of the chord. If the mode is DMUS_PLAYMODE_FIXEDTOKEY, the note is interpreted as a linear value. For more information on the various play modes, see DMUS_PLAYMODE_FLAGS.

The subchord level is a value in the range 0 to 31 that determines which subchords can be used in establishing the music value. A DirectMusic chord (as represented by a DMUS_CHORD_PARAM or DMUS_CHORD_KEY structure) actually consists of one or more subchords, allowing for complex harmonies with multiple parallel chord progressions. Each subchord supports one or more levels, as specified in the dwLevels member of the DMUS_SUBCHORD structure. The author of the music defines the supported levels for each subchord.

When a segment is played, each note is encapsulated in a DMUS_NOTE_PMSG structure. The bMidiValue member of this structure holds the MIDI note value that would normally be sent to the synthesizer. The message also holds the original music value as well as the play mode and subchord level that were used in transposition. A tool can use this information to alter the note in any way it likes. For example, a tool could intercept a note that was transposed in a certain play mode, change the play mode, obtain a new MIDI note by using the IDirectMusicPerformance::MusicToMIDI method, and put the new value in the bMidiValue member of the message before passing it on.

The MusicToMIDI method is at the heart of the style playback mechanism of DirectMusic. It is called by the style track to convert its internal music values into notes, using the current chord in the chord track.

If a tool wants to go the opposite way and obtain a new music value from a MIDI note using a different chord, play mode, or subchord level, it calls the IDirectMusicPerformance::MIDIToMusic method. The new music value can be placed in the wMusicValue member of the note message, where it might be of use to other application-defined tools, but of course the DirectMusic output tool will ignore it and play the note in bMidiValue as usual.


Using Compositional Elements

This section is a practical guide to incorporating music components into a DirectMusic application. It is presumed that you have a basic understanding of the purpose of each component and how it is represented by an object. If not, you may first want to read Composition Objects and Interfaces and Overview of Music Authoring.

Remember that you can incorporate DirectMusic into your applications without necessarily working with individual components such as styles, chordmaps, and templates. If you prefer, you can work with fully authored segments or even with MIDI files. Using individual components simply gives you greater control over the performance at run time.

This section covers the following topics:

  • Using Authored Segments
  • Using Styles
  • Using Motifs
  • Using Chordmaps
  • Using Templates
  • Using Transitions


Using Authored Segments

An authored segment is a file or resource that contains all the data for a piece of music. It may be based on a MIDI file, or on a style and a chordmap. Unlike a simple MIDI file or resource, it can contain band changes and variations.

Note A template is an authored segment as well, but it does not represent a self-contained piece of music. For more information, see Using Templates.

You create the segment in your application by loading the segment as an object and obtaining the IDirectMusicSegment interface, as in the following example, where the segment is loaded from a DirectMusic Producer file:

/* It is assumed that pLoader is a valid pointer to
   an IDirectMusicLoader interface, and that the search
   directory has been properly set. */

DMUS_OBJECTDESC ObjectDescript;
IDirectMusicSegment* pSegment;

ObjectDescript.dwSize = sizeof(DMUS_OBJECTDESC);
ObjectDescript.idClass = CLSID_DirectMusicSegment;
strcpy(ObjectDescript.wszFileName, L"Dance.sgt");
ObjectDescript.dwValidData = DMOBJ_CLASS | DMOBJ_PATH ;
pLoader->GetObject(&ObjectDescript, IID_IDirectMusicSegment,
    (void**) pSegment)))

You can now pass pSegment to the IDirectMusicPerformance::PlaySegment method.


Using Styles

The DirectMusicStyle object represents a collection of musical patterns, usually including embellishments and motifs, together with a time signature, tempo, and band. It defines the basic rhythm and the notes that will be played in each instrument part.

You obtain the DirectMusicStyle object from a style or segment file. For more information, see Loading Objects and Music Files for Composition.

A style by itself does not contain enough information to create a segment of music at run time. For this you need two other components: a chordmap (map of chord progressions) and a command track to set the groove level and embellishments as the music plays. The command track can come from a template or be generated at run time from a shape.

To create a segment with a command track based on a template, call the IDirectMusicComposer::ComposeSegmentFromTemplate method. (See Using Templates.)

To create a segment based on a shape, call the IDirectMusicComposer::ComposeSegmentFromShape method. You supply pointers to the style and the chordmap, and a variable to receive a pointer to the created segment. You also supply a rate of harmonic motion, which controls the frequency of chord changes, and a shape constant, which determines the progression of groove levels and embellishments.


Using Motifs

A motif is a special kind of pattern in a style intended to be played on top of the basic style pattern, typically in response to an interactive event. Although a motif can be as complex as any other pattern, even containing variations and multiple instrument parts, most often it is a short, simple musical figure that will sound good against a variety of background patterns. It might also be a sound effect played by a custom DLS instrument or instruments.

All the motifs authored into a style become available to you as soon as you have loaded that style. To get a particular motif ready for playback, you call the IDirectMusicStyle::GetMotif method, passing in the following parameters:

  • The name of the motif. You might know this from the documentation for the style, or you can obtain it from an index value by using the IDirectMusicStyle::EnumMotif method.
  • The number of times the motif should repeat when it is played.
  • A pointer to receive the IDirectMusicSegment interface to the segment object that will be created by the method.

The following example function obtains and plays the motif whose name is passed in as pwszMotifName.

void PlayMotif(IDirectMusicPerformance* pPerf,
         IDirectMusicStyle* pStyle,
         WCHAR* pwszMotifName)
{
  IDirectMusicSegment* pSeg;

  // Get the motif segment from the style, setting it to play once
  // through (no repeats). Check for S_OK specifically, because
  // GetMotif() returns S_FALSE if it doesn't find the motif.

  if (S_OK == pStyle->GetMotif(pwszMotifName, &pSeg))
  {
    /* Play the segment. DMUS_SEGF_BEAT means play on the next beat if
       there is a segment currently playing. DMUS_SEGF_SECONDARY means
       play the segment as a secondary segment, which plays on top of
       the currently playing primary segment. The 0 indicates to
       play now. The final NULL means do not return an
       IDirectMusicSegmentState* in the last parameter,
       because we don't need to track the state of playback. */

    pPerf->PlaySegment(pSeg,
                       DMUS_SEGF_BEAT | DMUS_SEGF_SECONDARY,
                       0,
                       NULL);
    pSeg->Release();
  }
}

Note that pSeg is played as a secondary segment, because a motif is normally played over a primary segment. You can't play a motif as a primary segment, because it doesn't have a chord track or band track. If you do want to play a motif against silence, you can create a primary segment from a style that has only blank patterns, and keep that segment playing while you play the motif.


Using Chordmaps

A DirectMusicChordMap object represents a collection of chords that provides the foundation of the harmonic structure and the mood of the music. A chordmap contains several pathways with many interconnected chords, providing many possibilities for the composition engine to choose from in determining the chord progression in a piece of music.

For authored segments, applications don't normally need to concern themselves with chordmaps. The chordmap is used at the authoring stage to create a fixed chord progression. However, chordmaps can be used to compose segments at run time and to alter the chord progression of existing segments.

You obtain the DirectMusicChordMap object from a chordmap file. For more information, see Loading Objects and Music Files for Composition.

If a chordmap has been authored into a style, you can retrieve a pointer to its IDirectMusicChordMap interface by passing its name (assigned by the author) to the IDirectMusicStyle::GetChordMap method. You can also use the IDirectMusicStyle::EnumChordMap method to search for a particular chordmap, or the IDirectMusicStyle::GetDefaultChordMap method to obtain a pointer to the default chordmap for the style.

Note DirectMusic Producer currently does not support authoring chordmaps into style files.

You set the chordmap for a composition when you create a segment by using either IDirectMusicComposer::ComposeSegmentFromTemplate or IDirectMusicComposer::ComposeSegmentFromShape. For more information, see Using Styles.

Once a segment has been created, you can change its chordmap by calling the IDirectMusicComposer::ChangeChordMap method. This will have the effect of changing the mood of the music without altering its basic rhythm and melody.

Every chordmap has an underlying scale consisting of 24 tones. You can determine the tones of the scale by using the IDirectMusicChordMap::GetScale method. The lower 24 bits of the variable pointed to by the pdwScale parameter of this method are set or clear depending on whether the corresponding tone is part of the scale. The upper 8 bits give the root of the scale as an integer between 0 and 23 (low C to middle B).


Using Templates

A template is a special kind of segment that can be used in composing a playable segment of music at run time. The template sets the length of the segment and any loop points. It provides the command track, which controls changes in the groove level and the choice of embellishment patterns. It also prescribes how the chordmap is used in composing the segment, by specifying from which signpost group each new chord must come.

A template is represented by a DirectMusicSegment object.

There are two ways to obtain a template:

  • Obtain one from a template file. You load the file as a DirectMusicObject and query for the IDirectMusicSegment interface. For more information, see Loading Objects.
  • Create one from a shape, using the IDirectMusicComposer::ComposeTemplateFromShape method. You choose the length, the overall shape, whether intro and end embellishment patterns are to be played, and how long the ending is to be. You get back a pointer to the IDirectMusicSegment interface.

Once you have obtained a template segment object, you can pass it to the IDirectMusicComposer::ComposeSegmentFromTemplate method, along with pointers to a style and a chordmap. You also supply a rate of harmonic motion, which sets the frequency of chord changes. The ComposeSegmentFromTemplate method creates a segment and returns a pointer to its IDirectMusicSegment interface at the address given in the ppSectionSeg parameter. It is this pointer that you pass to the IDirectMusicPerformance::PlaySegment method.


Using Transitions

In order to avoid a sudden and perhaps discordant break when stopping one segment and beginning another, or when bringing the music to a close, you can have the composer create an intermediate or closing segment that will provide an appropriate transition.

You have your choice of two methods for composing transitional segments.

  • The IDirectMusicComposer::AutoTransition method, given a pointer to the performance, creates a transition from the currently playing segment to a second segment of your choice and then automatically cues the transitional segment and the second segment for playback, returning an IDirectMusicSegmentState interface for both. The transition begins playing immediately, or on the next boundary as specified in the dwFlags parameter. Optionally the second segment can be NULL, so that the transition is to silence.
  • The IDirectMusicComposer::ComposeTransition method composes a transition from any point in one segment to the beginning of a second segment, or to silence, and returns an IDirectMusicSegment interface so that the application can play the transition.

Both these methods take a chordmap, a command, and a set of flags as parameters.

  • The chordmap, as usual, is used to create a chord track that defines the chord progression in the segment.
  • The command is one of the DMUS_COMMANDT_TYPES enumeration. It determines which type of pattern—either an ordinary groove pattern or one of the embellishments—will be called for in the command track of the transitional segment. When the segment plays, an appropriate pattern will be selected from the style.
  • The flags are from DMUS_COMPOSEF_FLAGS and further define the transition, principally its timing. The DMUS_COMPOSEF_MODULATE flag can be used to cause the transition to move smoothly from one tonality to another; it can't be used when there is no second segment, because there can be no modulation to silence.

Note that transitions are normally a single measure in length. There are two exceptions: when the DMUS_COMPOSEF_LONG flag is included, and when the command is DMUS_COMMANDT_END and the end embellishment in the style is more than one measure long.


DirectMusic Tutorials

This section contains tutorials providing step-by-step instructions for implementing basic Microsoft® DirectMusic™ functionality.

  • Tutorial 1: Playing a MIDI File
  • Tutorial 2: Using Tools
  • Tutorial 3: Using Compositions


Tutorial 1: Playing a MIDI File

This tutorial is a guide to setting up the simplest possible DirectMusic application, one that simply plays a primary segment. In this example the segment represents a MIDI file, but the process of loading and playing the data would be exactly the same if the source were a segment authored in a tool such as DirectMusic Producer.

The tutorial is broken down into the following steps:

  • Step 1: Initializing COM
  • Step 2: Creating the Performance
  • Step 3: Creating the Loader
  • Step 4: Loading the MIDI File
  • Step 5: Playing the MIDI File
  • Step 6: Shutting Down DirectMusic


Step 1: Initializing COM

Before making any calls to DirectMusic, you have to initialize COM as follows:

if (FAILED(CoInitialize(NULL)))
{
    // Terminate the application.
}   // Else full speed ahead!


Step 2: Creating the Performance

The central object of any DirectMusic application is the performance, which manages the playback of segments. It is created by using the COM CoCreateInstance function, as in the following sample function:

IDirectMusicPerformance* CreatePerformance(void)
{
    IDirectMusicPerformance* pPerf;

    if (FAILED(CoCreateInstance(
            CLSID_DirectMusicPerformance,
            NULL,
            CLSCTX_INPROC,
            IID_IDirectMusicPerformance,
            (void**)&pPerf
        )))
    {
        pPerf = NULL;
    }
    return pPerf;
}

You can use this function to initialize a global performance pointer that will be used in later steps:

IDirectMusicPerformance* g_pPerf = CreatePerformance();
if (g_pPerf == NULL)
{
    // Failure -- performance not created
}

Once the performance has been created, you need to initialize it by calling the IDirectMusicPerformance::Init method. The method creates a DirectMusic object to manage the default port. Because you don't need to access the IDirectMusic methods directly, you don't need to retrieve a pointer to it, so you pass NULL as the first parameter to Init. You also pass NULL as the IDirectSound pointer and as the window handle, so that DirectMusic will create a DirectSound object and pass the current focus window to it when setting the cooperative level.

if (FAILED(g_pPerf->Init(NULL, NULL, NULL)))
{
    // Failure -- performance not initialized
};

Now you need to add a port to the performance. Calling the IDirectMusicPerformance::AddPort method with a NULL parameter automatically adds the default port (normally the Microsoft Software Synthesizer) with one channel group, and assigns PChannels 0-15 to the group's MIDI channels.

if (FAILED(pPerf->AddPort(NULL)))
{
    // Failure -- port not initialized
}


Step 3: Creating the Loader

In order to load any object from disk, you first need to create the DirectMusicLoader object. This is done just as for any other COM object, as shown in the following sample function:

IDirectMusicLoader* CreateLoader(void)
{
    IDirectMusicLoader* pLoader;

    if (FAILED(CoCreateInstance(
            CLSID_DirectMusicLoader,
            NULL,
            CLSCTX_INPROC,
            IID_IDirectMusicLoader,
            (void**)&pLoader
        )))
    {
        pLoader = NULL;
    }
    return pLoader;
}

You'll use this function to initialize a global variable:

IDirectMusicLoader* g_pLoader = CreateLoader();
if (g_pLoader == NULL)
{
    // Failure -- loader not created
}


Step 4: Loading the MIDI File

In this step you will implement a function, LoadMIDISegment, that takes a pointer to the IDirectMusicLoader created in the last step and uses it to create a segment object encapsulating the data from a MIDI file.

IDirectMusicSegment* LoadMIDISegment(IDirectMusicLoader* pLoader,
        WCHAR wszMidiFileName )
{
    DMUS_OBJECTDESC ObjDesc;
    IDirectMusicSegment* pSegment = NULL;

Let's assume that all the MIDI files you want to play are in the current working directory. You need to let the loader know this, by setting the search directory. (If the search directory is not being changed elsewhere, in order to load objects from other directories, this actually has to be done only once, not each time you load a file.)

    char szDir[_MAX_PATH];
    WCHAR wszDir[_MAX_PATH];

    if(_getcwd( szDir, _MAX_PATH ) == NULL)
    {
        return NULL;
    }

/*
Convert from multibyte format to Unicode using the following macro:
#define MULTI_TO_WIDE( x,y )  MultiByteToWideChar( CP_ACP, \
        MB_PRECOMPOSED, y, -1, x, _MAX_PATH );
*/

    MULTI_TO_WIDE(wszDir, szDir);
    HRESULT hr = pLoader->SetSearchDirectory(GUID_DirectMusicAllTypes,
        wszDir, FALSE);
    if (FAILED(hr))
    {
        return NULL;
    }

You then describe the object to be loaded, in a DMUS_OBJECTDESC structure:

    ObjDesc.guidClass = CLSID_DirectMusicSegment;
    ObjDesc.dwSize = sizeof(DMUS_OBJECTDESC);
    wcscpy( ObjDesc.wszFileName, wszMidiFileName );
    ObjDesc.dwValidData = DMUS_OBJ_CLASS | DMUS_OBJ_FILENAME;

Now load the object and query it for the IDirectMusicSegment interface. This is done in a single call to IDirectMusicLoader::GetObject. Note that loading the object also initializes the tracks and does everything else necessary to get the MIDI data ready for playback.

    pLoader->GetObject(&ObjDesc,
            IID_IDirectMusicSegment, (void**) &pSegment);

To ensure that the segment plays as a standard MIDI file, you now need to set a parameter on the band track. Use the IDirectMusicSegment::SetParam method and let DirectMusic find the track, by passing -1 (or 0xFFFFFFFF) in the dwGroupBits method parameter.

    g_pMIDISeg->SetParam(GUID_StandardMIDIFile,
            -1, 0, 0, (void*)g_pPerf);

This step is necessary because DirectMusic handles program changes and bank selects differently for standard MIDI files than it does for MIDI content authored specifically for DirectMusic. The GUID_StandardMIDIFile parameter must be set before the instruments are downloaded.

The next step is to download the instruments. This is necessary even for playing a simple MIDI file, because the default software synthesizer needs the DLS data for the General MIDI instrument set. If you skip this step, the MIDI file will play silently. Again, you call SetParam on the segment, this time specifying the GUID_Download parameter:

    g_pMIDISeg->SetParam(GUID_Download, -1, 0, 0, (void*)g_pPerf);

Note that there's no harm in requesting the download even though this might already have been done in a previous call to the LoadMIDISegment function. A redundant request is simply ignored. Eventually you have to unload the instruments, but that can wait until you're ready to shut down DirectMusic.

The function now returns a pointer to the segment, which is ready to be played.

    return pSegment;

} // End of LoadSegment()

Before loading a new segment, clean up any existing one. Then pass a file name to the LoadMIDISegment function.

if (g_pMIDIseg)
{
    g_pMIDIseg->Release();
    g_pMIDIseg = NULL;
}

if (g_pLoader)
{
    IDirectMusicSegment* g_pMIDIseg = LoadMIDISegment(g_pLoader,
            L"tune.mid");
}


Step 5: Playing the MIDI File

Now that all of the preparatory work has been done, playing the music is simplicity itself.

IDirectMusicSegmentState* g_pSegState;
if (g_pMIdiSEG)
{
    g_pPerf->PlaySegment(g_pMIDISeg, 0, 0, &g_pSegState);
}

The call to IDirectMusicPerformance::PlaySegment takes the following parameters:

  • The segment you created in the previous step.
  • A set of timing flags and a start time (not needed here because you simply want the segment to play as soon as possible).
  • The address of a pointer to a segment state object. You can use the returned pointer in order to retrieve information about the segment. This parameter can be NULL if you won't be needing the segment state.

If you want the file to be played more than once, before calling PlaySegment you must call the IDirectMusicSegment::SetRepeats method.

If you want to stop the music before it has played to the end or finished its repeats, you do so by using the IDirectMusicPerformance::Stop method. The simplest way to use this method is simply to request that all music currently playing or cued to play be stopped immediately:

g_pPerf->Stop(NULL, NULL, 0, 0)

Alternatively, you can supply a pointer to the current segment or segment state in order to stop playback of just one segment, or one instance of that segment.


Step 6: Shutting Down DirectMusic

Before exiting, the program must unload the instruments, release all the objects that have been created, and dereference COM (remember, every call to CoInitialize must have a matching call to CoUninitialize).

The following function performs the necessary cleanup:

HRESULT FreeDirectMusic()
{
    // If there is any music playing, stop it. This is
    // not really necessary, because the music will stop when
    // the instruments are unloaded or the performance is
    // closed down.
    g_pPerf->Stop( NULL, NULL, 0, 0 );

    // Unload instruments – this will cause silence.
    // CloseDown unloads all instruments, so this call is also not
    // strictly necessary.
    g_pMIDISeg->SetParam(GUID_Unload, -1, 0, 0, (void*)g_pPerf);

    // Release the segment.
    g_pMIDISeg->Release();

    // CloseDown and Release the performance object.
    g_pPerf->CloseDown();
    g_pPerf->Release();

    // Release the loader object.
    g_pLoader->Release();

    // Release COM.
    CoUninitialize();

    return S_OK;
}


Tutorial 2: Using Tools

This tutorial shows how a tool might be implemented as a C++ class and used in a DirectMusic application. The CEchoTool class enables an application to add one or more echoes to every music note in a performance.

The sample code is based on the EchoTool sample application included with the DirectX Programmer's Reference.

The tutorial is broken down into the following steps:

  • Step 1: Declaring the Tool Class
  • Step 2: Defining the IUnknown Methods
  • Step 3: Specifying Message Types
  • Step 4: Defining the ProcessPMsg Method
  • Step 5: Defining the Class Methods
  • Step 6: Adding the Tool to the Performance


Step 1: Declaring the Tool Class

The first step in creating a tool for DirectMusic in C++ is to declare a class derived from IDirectMusicTool.

Here is the declaration for the sample CEchoTool class:

class CEchoTool : public IDirectMusicTool
{
public:
  CEchoTool();
  ~CEchoTool();

public:
// IUnknown
  virtual STDMETHODIMP QueryInterface(const IID &iid, void **ppv);
  virtual STDMETHODIMP_(ULONG) AddRef();
  virtual STDMETHODIMP_(ULONG) Release();

// IDirectMusicTool
  HRESULT STDMETHODCALLTYPE Init(
          IDirectMusicGraph* pGraph);
  HRESULT STDMETHODCALLTYPE GetMsgDeliveryType(
          DWORD* pdwDeliveryType);
  HRESULT STDMETHODCALLTYPE GetMediaTypeArraySize(
          DWORD* pdwNumElements);
  HRESULT STDMETHODCALLTYPE GetMediaTypes(
          DWORD** padwMediaTypes,
          DWORD dwNumElements);
  HRESULT STDMETHODCALLTYPE ProcessPMsg(
          IDirectMusicPerformance* pPerf,
          DMUS_PMSG* pDMUS_PMSG);
  HRESULT STDMETHODCALLTYPE Flush(
         IDirectMusicPerformance* pPerf,
         DMUS_PMSG* pDMUS_PMSG,
         REFERENCE_TIME rtTime);
private:
  long m_cRef;                // Reference counter
  DWORD m_dwEchoNum;          // Number of echoes to generate
  MUSIC_TIME m_mtDelay;       // Delay time between echoes
  CRITICAL_SECTION m_CrSec;   // To make SetEchoNum()
                              //   and SetDelay() thread-safe
public:
// Public class methods
  void SetEchoNum(DWORD);
  void SetDelay(MUSIC_TIME);
};


Step 2: Defining the IUnknown Methods

The inherited IUnknown methods of the sample CEchoTool class are implemented as follows:

STDMETHODIMP CEchoTool::QueryInterface(const IID &iid, void **ppv)
{
  if (iid == IID_IUnknown || iid == IID_IDirectMusicTool)
  {
    *ppv = static_cast<IDirectMusicTool*>(this);
  } else
  {
    *ppv = NULL;
    return E_NOINTERFACE;
  }

  reinterpret_cast<IUnknown*>(this)->AddRef();
  return S_OK;
}

STDMETHODIMP_(ULONG) CEchoTool::AddRef()
{
    return InterlockedIncrement(&m_cRef);
}

STDMETHODIMP_(ULONG) CEchoTool::Release()
{
    if( 0 == InterlockedDecrement(&m_cRef) )
    {
        delete this;
        return 0;
    }
    return m_cRef;
}


Step 3: Specifying Message Types

The CEchoTool class needs to define all the IDirectMusicTool methods. But because it does not need to perform any work in Init or Flush, it simply returns E_NOTIMPL from those methods.

The following methods are used to specify what messages will get passed to the tool for processing:

  • GetMsgDeliveryType specifies when messages should be passed to the tool—as soon as they are available, at the exact time they are stamped for, or just in time to be processed and put in the port buffer. These three "delivery types" are represented respectively by the DMUS_PMSGF_TOOL_IMMEDIATE, DMUS_PMSGF_TOOL_ATTIME, and DMUS_PMSGF_TOOL_QUEUE flags in the dwFlags member of the DMUS_PMSG structure.
  • GetMediaTypes establishes what type of messages should be passed to the tool, based on the content of the message. CEchoTool processes only music notes and patch changes, so it will accept MIDI short messages, music note messages, and DirectMusic patch messages. These messages are identified by flags of the DMUS_PMSGT_TYPES enumerated type in the DMUS_PMSG message structure.
  • GetMediaTypeArraySize returns the number of elements in the media type array.

CEchoTool implements these methods in the following sample code:

HRESULT STDMETHODCALLTYPE CEchoTool::GetMsgDeliveryType(
        DWORD* pdwDeliveryType )
{
    // This tool wants messages immediately.
    // This is the default, so returning E_NOTIMPL
    // would work. The other method is to specifically
    // set *pdwDeliveryType to the delivery type,
// DMUS_PMSGF_TOOL_IMMEDIATE, DMUS_PMSGF_TOOL_QUEUE,
// or DMUS_PMSGF_TOOL_ATTIME.

    *pdwDeliveryType = DMUS_PMSGF_TOOL_IMMEDIATE;
  return S_OK;
}

HRESULT STDMETHODCALLTYPE CEchoTool::GetMediaTypeArraySize(
        DWORD* pdwNumElements)
{
  *pdwNumElements = 3;
  return S_OK;
}

HRESULT STDMETHODCALLTYPE CEchoTool::GetMediaTypes(
        DWORD** padwMediaTypes,
        DWORD dwNumElements)
{
  if (dwNumElements == 3)
  {
    (*padwMediaTypes)[0] = DMUS_PMSGT_NOTE;
    (*padwMediaTypes)[1] = DMUS_PMSGT_MIDI;
    (*padwMediaTypes)[2] = DMUS_PMSGT_PATCH;
    return S_OK;
  }
  else
  {
    // This should never happen.
    return E_FAIL;
  }
}


Step 4: Defining the ProcessPMsg Method

The actual work of the tool is performed in the method derived from IDirectMusicTool::ProcessPMsg. This method will be called for every message of the type listed in the array returned by IDirectMusicTool::GetMediaTypes.

The CEchoTool::ProcessPMsg method first performs some initialization of local variables:

HRESULT STDMETHODCALLTYPE CEchoTool::ProcessPMsg(
  IDirectMusicPerformance* pPerf,
  DMUS_PMSG* pMsg)
{
  DMUS_NOTE_PMSG* pNote;
  DWORD dwCount;
  DWORD dwEchoNum;
  MUSIC_TIME mtDelay;

  // SetEchoNum() and SetDelay() use these member variables,
  // so use a critical section to make them thread-safe.
  EnterCriticalSection(&m_CrSec);
  dwEchoNum = m_dwEchoNum;
  mtDelay = m_mtDelay;
  LeaveCriticalSection(&m_CrSec);

Next the method calls the IDirectMusicGraph::StampPMsg method on the message. If there is another tool to which this message must be directed after we're finished with it here, StampPMsg succeeds. (Note that DirectMusic provides a final output tool, so StampPMsg should succeed even if there are no other application-specific tools to which the message must be routed.) If it fails, our method returns S_FREE so that the message will automatically be discarded.

  if ((NULL == pMsg->pGraph) ||
    FAILED(pMsg->pGraph->StampPMsg(pMsg)))
  {
    return DMUS_S_FREE;
  }

Now it's time for CEchoTool to perform its work on the message. Remember, it is set up to receive messages only of type DMUS_PMSGT_NOTE, DMUS_PMSGT_MIDI; or DMUS_PMSGT_PATCH. (These types are part of the DMUS_PMSGT_TYPES enumeration.)

For each successive echo to be created, the tool does the following:

  • Creates a new message by calling the IDirectMusicPerformance::AllocPMsg method.
  • Copies the DMUS_PMSG structure for the original message into the new one and updates some members for COM management.
  • Assigns the new message to a different performance channel.
  • In the case of a music note, progressively reduces the volume of each echo.
  • Adds the delay time to the time at which the message is to be played.
  • Puts the new message in the pipeline by calling the IDirectMusicPerformance::SendPMsg method. Note that because IDirectMusicGraph::StampPMsg is not called on the message, it will not be routed to any tools other than the default final output tool.

Here's the sample code that deals with MIDI notes:

  if( pPMsg->dwType == DMUS_PMSGT_MIDI )
  {
    // copy MIDI messages into the echo channels.
    for( dwCount = 1; dwCount <= dwEchoNum; dwCount++ )
    {
      DMUS_MIDI_PMSG* pMidi;
      if( SUCCEEDED( pPerf->AllocPMsg( sizeof(DMUS_MIDI_PMSG),
        (DMUS_PMSG**)&pMidi )))
      {
        // Copy the original message into this message.
        memcpy( pMidi, pPMsg, sizeof(DMUS_MIDI_PMSG) );

        // Addref or clear out any fields that contain
        // or may contain pointers to objects.
        if( pMidi->pTool ) pMidi->pTool->AddRef();
        if( pMidi->pGraph ) pMidi->pGraph->AddRef();
        pMidi->punkUser = NULL;

        // Set the PChannel so the message goes to the
        // next higher group.
        pMidi->dwPChannel = pMidi->dwPChannel +
                (16*dwCount);

        // Add to the time of the echoed message.
        pMidi->mtTime += (dwCount * mtDelay);

        // Set the message so only MUSIC_TIME is valid.
        // REFERENCE_TIME will be recomputed inside
        // SendPMsg().
        pMidi->dwFlags = DMUS_PMSGF_MUSICTIME;

        // Send the message
        pPerf->SendPMsg( (DMUS_PMSG*)pMidi );
      }
    }
  }

Patch changes are also copied and sent to all possible echo channels, even those not currently being used, so that if echoes are added later they will be played by the correct instruments. Note that in the sample Echotool application, MAX_ECHOES is defined in Echotool.h.

  else if( pPMsg->dwType == DMUS_PMSGT_PATCH )
  {
    for( dwCount = 1; dwCount <= MAX_ECHOES; dwCount++ )
    {
      DMUS_PATCH_PMSG* pPatch;
      if( SUCCEEDED( pPerf->AllocPMsg( sizeof(DMUS_PATCH_PMSG),
        (DMUS_PMSG**)&pPatch )))
      {
        // Copy the original message into this message,
        memcpy( pPatch, pPMsg, sizeof(DMUS_PATCH_PMSG) );

        // Addref or clear out any fields that contain
        // or may contain pointers to objects
        if( pPatch->pTool ) pPatch->pTool->AddRef();
        if( pPatch->pGraph ) pPatch->pGraph->AddRef();
        pPatch->punkUser = NULL;

        // Set the PChannel so the message goes to the
        // next higher group.
        pPatch->dwPChannel = pPatch->dwPChannel +
          (16*dwCount);

        // Add to the time of the echoed message.
        pPatch->mtTime += (dwCount * mtDelay);

        // Set the message so only MUSIC_TIME is valid.
        // REFERENCE_TIME will be recomputed inside
        // SendPMsg()
        pPatch->dwFlags = DMUS_PMSGF_MUSICTIME;

        // Send the message.
        pPerf->SendPMsg( (DMUS_PMSG*)pPatch );
      }
    }
  }

The method deals with music notes much as it did with MIDI notes, but taking the additional step of reducing the volume:

  else if( pPMsg->dwType == DMUS_PMSGT_NOTE )
  {
    // Create a variable to track the next note's velocity
    BYTE bVelocity;
    pNote = (DMUS_NOTE_PMSG*)pPMsg;
    bVelocity = pNote->bVelocity;

    for( dwCount = 1; dwCount <= dwEchoNum; dwCount++ )
    {
      if( SUCCEEDED( pPerf->AllocPMsg( sizeof(DMUS_NOTE_PMSG),
              (DMUS_PMSG**)&pNote )))
      {
        // Copy the original note into this message.
        memcpy( pNote, pPMsg, sizeof(DMUS_NOTE_PMSG) );

        // Addref or clear out any fields that contain
        // or may contain pointers to objects.
        if( pNote->pTool ) pNote->pTool->AddRef();
        if( pNote->pGraph ) pNote->pGraph->AddRef();
        pNote->punkUser = NULL;

        // Add to the time of the echoed note.
        pNote->mtTime += (dwCount * mtDelay);

        // Reduce the volume of the echoed note.
        bVelocity = (BYTE) (bVelocity -
                ((bVelocity * (dwCount * 15))/100));
        pNote->bVelocity = bVelocity;

        // Set the note so only MUSIC_TIME is valid.
        // REFERENCE_TIME will be recomputed inside
        // SendPMsg().
        pNote->dwFlags = DMUS_PMSGF_MUSICTIME;
        pNote->dwPChannel = pNote->dwPChannel +
          (16*dwCount);

        // Send the message.
        pPerf->SendPMsg( (DMUS_PMSG*)pNote );
      }
    }
  }

Finally, the ProcessPMsg method returns DMUS_S_REQUEUE so the original message will be put back in the pipeline.

  return DMUS_S_REQUEUE;
} // End CEchoTool::ProcessPMsg()


Step 5: Defining the Class Methods

Besides its inherited IUnknown and IDirectMusicTool methods, the sample CEchoTool class has a constructor and destructor as well as two public methods for setting the parameters of the echo. The definition of these methods is somewhat peripheral to this tutorial, but is included here for completeness.

CEchoTool::CEchoTool()
{
  m_cRef = 1;               // So one Release() will free this
  m_dwEchoNum = 3;          // Default to 3 echoes per note
  m_mtDelay = DMUSPPQ / 2;  // Default to 8th-note echoes
  InitializeCriticalSection(&m_CrSec);
}

CEchoTool::~CEchoTool()
{
  DeleteCriticalSection(&m_CrSec);
}

void CEchoTool::SetEchoNum(DWORD dwEchoNum)
{
  // ProcessPMsg() uses m_dwEchoNum, so use a critical
  // section to make it thread-safe.
  if( dwEchoNum <= MAX_ECHOES )
  {
    EnterCriticalSection(&m_CrSec);
    m_dwEchoNum = dwEchoNum;
    LeaveCriticalSection(&m_CrSec);
  }
}

void CEchoTool::SetDelay(MUSIC_TIME mtDelay)
{
  // ProcessPMsg() uses m_mtDelay, so use a critical
  // section to make it thread-safe.
  EnterCriticalSection(&m_CrSec);
  m_mtDelay = mtDelay;
  LeaveCriticalSection(&m_CrSec);
}


Step 6: Adding the Tool to the Performance

Once it has defined the CEchoTool class, the application can create a tool object, insert it into a graph, and add it to the performance so that it will intercept appropriate messages in the pipeline.

The following code creates an instance of the CEchoTool class, initializes the number of echoes to be produced by the tool, creates a graph to contain the tool, and adds the graph to the performance. (In the Echotool sample application, some of this work is done in a helper function, AddTool. The code has been modified here to make it easier to follow.)

/* It is assumed that pPerf is a valid pointer to the
   IDirectMusicPerformance interface of a performance object. */

CEchoTool         *pEchoTool;
IDirectMusicGraph* pGraph;

pEchoTool = new CEchoTool;
if (pEchoTool)
{
    pEchoTool->SetEchoNum(0);

    // Create an IDirectMusicGraph object to hold the tool.
    if (SUCCEEDED(CoCreateInstance(
            CLSID_DirectMusicGraph,
            NULL,
            CLSCTX_INPROC,
            IID_IDirectMusicGraph,
            (void**)&pGraph)))
    {
        // Add the tool to the graph.
        if (SUCCEEDED(pGraph->InsertTool(
                (IDirectMusicTool*)pCEchoTool,
                NULL,   // Apply to all PChannels
                0,      // How many PChannels otherwise
                0)))    // Index of tool in graph
        {
        // Add the graph to the performance. This increments the
        // reference count, so the original graph can then be
        // released.
        pPerf->SetGraph(pGraph);
        }
        pGraph->Release();
    }
}

Note that setting the graph on the performance ensures that messages from all segments will have the opportunity to be processed by its tools. Alternatively, you could use the IDirectMusicSegment::SetGraph method to apply tools only to a particular segment.


Tutorial 3: Using Compositions

This tutorial shows how to set up a music performance that is based on elements authored in DirectMusic Producer, and how to have the music performed interactively—that is, in such as way that it responds to program events.

The code samples are based on the DMDonuts sample in the DirectX Programmer's Reference. Because DMDonuts is a large and complex application, only the main points will be covered here. For the complete DirectMusic implementation, see the Donuts.cpp source file and its included headers, where all the relevant code is delimited by DMUSIC BEGIN and DMUSIC END comments.

The tutorial is broken down into the following steps:

  • Step 1: Defines and Globals
  • Step 2: Initializing the Performance
  • Step 3: Loading the Music Elements
  • Step 4: Setting Up Notifications
  • Step 5: Creating Primary Segments
  • Step 6: Playing a Primary Segment
  • Step 7: Transitioning to Another Primary Segment
  • Step 8: Playing a Motif
  • Step 9: Handling Notifications
  • Step 10: Shutting Down DirectMusic


Step 1: Defines and Globals

The following defines and global variables are declared at the beginning of Donuts.cpp. They are given here for you to refer to as you work through the tutorial.

BOOL          bMusicEnabled = TRUE;

// Various constants
const  GUID guidZero =    {0};
#define MOTIF_BOUNCE       0
#define MOTIF_DEATH        1
#define MOTIF_SHIELD       2
#define MOTIF_BLOWUP       4
#define MOTIF_BLOWUPLITE   3
#define NUM_MOTIFS         5
#define NUM_STYLES         2
#define SEGMENT_1          0
#define SEGMENT_2          1
#define SEGMENT_TRANS_1    2
#define SEGMENT_TRANS_2    3
#define NUM_SEGMENTS       4
#define NUM_CHORDMAP       4
#define BLOWUPS_PER_BEAT   2
#define MEASURE_LENGTH     DMUS_PPQ * 4
// parts/quarter * quarters/measure (assumes 4/4)

// Global interfaces
IDirectMusicStyle*        gapStyle[NUM_STYLES];
IDirectMusicChordMap*     gapChordMap[NUM_STYLES] [NUM_CHORDMAP];
IDirectMusicSegment*      gapMotif[NUM_STYLES] [NUM_MOTIFS];
IDirectMusicSegment*      gapSegment[NUM_SEGMENTS] =
                          {NULL, NULL, NULL, NULL};
IDirectMusicComposer *    gpComposer = NULL;
IDirectMusicPerformance*  gpPerformance = NULL;
IDirectMusic*             gpDirectMusic = NULL;
IDirectMusicLoader*       gpLoader = NULL;
IDirectMusicSegment*      gpIntroTemplate = NULL;
IDirectMusicSegment*      gpGameTemplate = NULL;
IDirectMusicSegment*      gapShieldSegment[NUM_STYLES] = {NULL, NULL};
IDirectMusicSegment*      gapDefaultSegment[NUM_STYLES] =
                                  {NULL, NULL};
IDirectMusicBand*         gapShieldBand[NUM_STYLES] = {NULL, NULL};
IDirectMusicBand*         gapDefaultBand[NUM_STYLES] = {NULL, NULL};

// Global variables
BOOL        bAnyHits = FALSE;
int         gnCurrentStyle = 0;
int         gnCurrentChordMap = 0;
int         gnLastStyle = 0;
int         gnLastChordMap = 0;

BOOL        gbShieldsOn = FALSE;
static int  snLastTempo;
static int  snSubLevel;
static int  snMaxBlowUps = BLOWUPS_PER_BEAT;


Step 2: Initializing the Performance

The DirectMusic performance is set up in the InitializeGame function in Donuts.cpp.

First the application queries the registry to obtain the search path for the DirectX sample music files, by calling the GetSearchPath function. Then it creates COM objects for the composer and the performance, as follows:

CoInitialize(NULL);

if ( !SUCCEEDED(::CoCreateInstance(
        CLSID_DirectMusicComposer,
        NULL,
        CLSCTX_INPROC,
        IID_IDirectMusicComposer,
        (void**)&gpComposer
)))
{
    return CleanupAndExit("Couldn't create a composer object");
}

if ( !SUCCEEDED( CoCreateInstance( CLSID_DirectMusicPerformance,
        NULL,
        CLSCTX_INPROC,
        IID_IDirectMusicPerformance,
        (void**)&gpPerformance )))
{
    return CleanupAndExit("Couldn't create a performance object");
}

The application then initializes the performance by calling IDirectMusicPerformance::Init, which creates a DirectMusic object that can be used to create and activate its ports. Depending on whether or not DirectSound is being used for other sound effects, the call either attaches the existing DirectSound object to the performance by passing in lpDS or creates one by passing in NULL.

#ifdef USE_DSOUND
    if( !SUCCEEDED(gpPerformance->Init(&gpDirectMusic,
           lpDS, hWndMain)))
    {
        return CleanupAndExit("Couldn't initialize the performance");
    }
#else
    if( !SUCCEEDED(gpPerformance->Init(&gpDirectMusic,
            NULL, hWndMain)))
    {
        return CleanupAndExit("Couldn't initialize the performance");
    }
#endif

The application now gets the default port, creates an instance of it with one channel group, and retrieves its capabilities:

IDirectMusicPort* pPort = NULL;
DMUS_PORTPARAMS dmos;
DMUS_PORTCAPS dmpc;
GUID guidSynthGUID;
HRESULT hr = S_OK;

if ( !SUCCEEDED(gpDirectMusic->GetDefaultPort(&guidSynthGUID)))
{
    return CleanupAndExit("Could't GetDefaultPort on IDirectMusic");
}

ZeroMemory(&dmos, sizeof(dmos));
dmos.dwSize = sizeof(DMUS_PORTPARAMS);
dmos.dwChannelGroups = 1;
dmos.dwValidParams = DMUS_PORTPARAMS_CHANNELGROUPS;

if( !SUCCEEDED(gpDirectMusic->CreatePort(guidSynthGUID,
            &dmos,
            &pPort,
            NULL)))
{
    return CleanupAndExit("Couldn't CreatePort on IDirectMusic");
}

ZeroMemory(&dmpc, sizeof(dmpc));
dmpc.dwSize = sizeof(DMUS_PORTCAPS);

if( !SUCCEEDED(pPort->GetCaps(&dmpc)))
{
    if (pPort) pPort->Release();
    return CleanupAndExit("Couldn't GetCaps on IDirectMusicPort");
}

The behavior of the application now varies depending on whether _SOFTWARE_SYNTH_ is defined. If it is, a synthesizer with DLS capabilities is wanted, so the application checks for the DMUS_PC_DLS capabilities flag on the default port. If it fails to find that flag, it goes on to free the default port and enumerate available ports until if finds an output port that has the DMUS_PC_DLS capability. Finally, it creates an instance of that port.

if ((dmpc.dwClass != DMUS_PC_OUTPUTCLASS)
        || !(dmpc.dwFlags & DMUS_PC_DLS))
{
    pPort->Release();
    pPort = NULL;
}

if (!pPort)
{
    for (DWORD index = 0; hr == S_OK; index++)
    {
        ZeroMemory(&dmpc, sizeof(dmpc));
        dmpc.dwSize = sizeof(DMUS_PORTCAPS);

        hr = gpDirectMusic->EnumPort(index, &dmpc);
        if(hr == S_OK)
        {
            if ( (dmpc.dwClass == DMUS_PC_OUTPUTCLASS) &&
                 (dmpc.dwFlags & DMUS_PC_DLS) )
            {
                CopyMemory(&guidSynthGUID, &dmpc.guidPort,
                        sizeof(GUID));

                ZeroMemory(&dmos, sizeof(dmos));
                dmos.dwSize = sizeof(DMUS_PORTPARAMS);
                dmos.dwChannelGroups = 1;
                dmos.dwValidParams = DMUS_PORTPARAMS_CHANNELGROUPS;

                hr = gpDirectMusic->CreatePort(guidSynthGUID,
                        &dmos, &pPort, NULL);
                break;
            }
        }
    }
    if (hr != S_OK)
    {
        if (pPort) pPort->Release();
        return CleanupAndExit("Couldn't initialize the Synth port");
    }
}

If, on the other hand, _SOFTWARE_SYNTH_ is not defined, a legacy hardware port is wanted, and the application goes on to enumerate ports until it finds the MIDI mapper. (That code is omitted here.)

Now the port is activated and attached to the performance.

pPort->Activate(TRUE);
gpPerformance->AddPort(pPort);

The next call maps PChannels 0-15 to the first group of MIDI channels on the port. Note that this step is necessary because the application did not pass NULL to AddPort.

gpPerformance->AssignPChannelBlock(0, pPort, 1);

The original reference to the port can now be released. This call doesn't remove the port from the performance.

if (pPort) pPort->Release();


Step 3: Loading the Music Elements

The next step in setting up the DirectMusic functionality of the DMDonuts sample application is to load the music elements—styles, templates, motifs, chordmaps, and bands—from file. Like the previous step, this one is carried out in the InitializeGame function.

First the application creates the loader object:

if (!SUCCEEDED(::CoCreateInstance(
            CLSID_DirectMusicLoader,
            NULL,
            CLSCTX_INPROC,
            IID_IDirectMusicLoader,
            (void**)&gpLoader
        )))
{
    return CleanupAndExit("Couldn't create a loader object");
}

Then it sets the search directory for all object types and enables the object cache. This second call simply confirms the default cache status.

hr = E_FAIL;

/ * The GetSearchPath function gets the media directory
    from the registry and returns it in wszSearchPath. */

if (GetSearchPath(wszSearchPath))
{
    hr = gpLoader->SetSearchDirectory(
           GUID_DirectMusicAllTypes, wszSearchPath, FALSE);
}

/* If that directory doesn't exist, try the current directory. */

if (FAILED(hr))
{
    hr = gpLoader->SetSearchDirectory(GUID_DirectMusicAllTypes,
            L".", FALSE);
}
if (FAILED(hr))
{
    return CleanupAndExit("Couldn't set the search directory \
            for the DirectMusic loader");
}
gpLoader->EnableCache(GUID_DirectMusicAllTypes, TRUE);

The following code snippet loads the style named "Donuts", which is in the Donuts.sty file. Note that because the application hasn't called IDirectMusicLoader::ScanDirectory to build a database of objects that can be loaded by internal name, the first call to IDirectMusicLoader::GetObject will fail. The fallback procedure is to identify the object by file name and call GetObject again.

IDirectMusicObject* pObject = NULL;
DMUS_OBJECTDESC ObjectDescript;

ObjectDescript.dwSize = sizeof(DMUS_OBJECTDESC);
ObjectDescript.guidClass = CLSID_DirectMusicStyle;
wcscpy(ObjectDescript.wszName, L"Donuts");
ObjectDescript.dwValidData = DMUS_OBJ_CLASS | DMUS_OBJ_NAME;

if (!SUCCEEDED(gpLoader->GetObject(&ObjectDescript,
        IID_IDirectMusicStyle, (void**)&gapStyle[1])))
{
    wcscpy(ObjectDescript.wszFileName, L"Donuts.sty");
    ObjectDescript.dwValidData = DMUS_OBJ_CLASS | DMUS_OBJ_FILENAME;
    if (!SUCCEEDED(gpLoader->GetObject(&ObjectDescript,
            IID_IDirectMusicStyle, (void**)&gapStyle[1])))
    {
        return CleanupAndExit("Couldn't load style object 1");
    }
}

The InitializeGame function then goes on to load another style and two templates in similar fashion.

The next step is to initialize an array of motifs that will be used to mark certain events in the game. Each motif is contained in a style and is obtained by calling the IDirectMusicStyle::GetMotif method, which creates a segment for the motif. The method must be supplied with the internal name of the motif, as in the following example from Donuts.cpp.

WCHAR awszMotifs[NUM_MOTIFS][64];

wcscpy(awszMotifs[MOTIF_BOUNCE], L"Bounce");
.
.
.
hr = gapStyle[0]->GetMotif(awszMotifs[MOTIF_BOUNCE],
        &(gapMotif[0][MOTIF_BOUNCE]));

If you look at the complete code, you'll see that the application loads two sets of motifs with the same names, one set from the "Donuts" style and the other from "Donutz." DMDonuts switches between these two styles as the player moves from level to level. When a gapMotif is played, its first index is determined by the value of the global gnCurrentStyle, ensuring that it is the correct motif for that level.

The application now initializes four chordmaps for each style. These are obtained from separate files.

WCHAR awszChordMap[NUM_STYLES][NUM_CHORDMAP][64];
wcscpy(awszChordMap[0][0], L"minaeo.per");
wcscpy(awszChordMap[0][1], L"minfunc.per");
wcscpy(awszChordMap[0][2], L"mipedpt.per");
wcscpy(awszChordMap[0][3], L"tension.per");
wcscpy(awszChordMap[1][0], L"dianoble.per");
wcscpy(awszChordMap[1][1], L"minpedpt.per");
wcscpy(awszChordMap[1][2], L"mippjazz.per");
wcscpy(awszChordMap[1][3], L"minjazz.per");

ObjectDescript.guidClass = CLSID_DirectMusicChordMap;
ObjectDescript.dwValidData = DMUS_OBJ_CLASS | DMUS_OBJ_FILENAME;

for (short n = 0; n < NUM_STYLES; n++)
{
    for (short m = 0; m < NUM_CHORDMAP; m++)
    {
        if (hr == S_OK)
        {
            wcscpy(ObjectDescript.wszFileName,
                    awszChordMap[n][m]);
            hr = gpLoader->GetObject(&ObjectDescript,
                    IID_IDirectMusicChordMap,
                   (void**)&gapChordMap[n][m]);
        }
    }
}

if (hr != S_OK)
{
    return CleanupAndExit("Couldn't load a ChordMap");
}

The last elements to be retrieved from the styles are the bands. Each style has two different bands: one for when the player's ship isn't shielded and one for when it is. Note that the names of the bands are allocated differently than were the motifs and chordmaps—each is a BSTR rather than a local array of WCHAR—but the effect is the same, because in the Win32® API a BSTR is a pointer to a WCHAR array.

As each band is loaded, it is downloaded to the performance, making available the DLS data for its instruments.

BSTR bstrDefault = SysAllocString(L"Default 2");
BSTR bstrShields = SysAllocString(L"Shields");

for (n = 0; n < NUM_STYLES; n++)
{
    if (hr == S_OK)
    {
        hr = gapStyle[n]->GetBand(bstrShields, &gapShieldBand[n]);
    }
    if (hr == S_OK)
    {
        hr = gapShieldBand[n]->Download(gpPerformance);
    }
    if (hr == S_OK)
    {
        hr = gapStyle[n]->GetBand(bstrDefault, &gapDefaultBand[n]);
    }
    if (hr == S_OK)
    {
        hr = gapDefaultBand[n]->Download(gpPerformance);
    }
}

SysFreeString(bstrDefault);
SysFreeString(bstrShields);

After some error-checking code, the InitializeGame function goes on to create segments from the four bands it has obtained. These segments will be used to "play" the band changes at the appropriate times. Once the segments have been created, the band interfaces are released.

for (n = 0; n < NUM_STYLES; n++)
{
    if (hr == S_OK)
    {
        hr = gapShieldBand[n]->CreateSegment(&gapShieldSegment[n]);
    }
    if (hr == S_OK)
    {
        hr = gapDefaultBand[n]->CreateSegment(&gapDefaultSegment[n]);
    }
    apShieldBand[n]->Release();
    apDefaultBand[n]->Release();
}


Step 4: Setting Up Notifications

The last bit of DirectMusic code inside the InitializeGame function is a request for notification when playback of the primary segment reaches a beat boundary or the end of the segment. As you'll see later in this tutorial, the notification mechanism is used to limit the number of "blowup" motifs that can be played at the same time.

The following code adds the notification types. Note that the notification GUIDs have to be placed in a variable, because they are passed by reference.

GUID guid;
guid = GUID_NOTIFICATION_SEGMENT;
gpPerformance->AddNotificationType( guid );
guid = GUID_NOTIFICATION_MEASUREANDBEAT;
gpPerformance->AddNotificationType( guid );


Step 5: Creating Primary Segments

The one-time initialization of DirectMusic in the DMDonuts sample application is now complete. Further initialization is done in the setup_game function each time the game is started or the player advances to the next level.

The setup_game function first calls another function called ComposeNewSegments, which selects a style and chordmap based on the current game level, releases any previously created segments, and then composes two new segments based on the templates previously loaded from file. One of these segments is an introductory theme that plays until a donut has been hit; the other plays from that point until the player beats the level. The snSubLevel variable tracks which part of the level we are in and is used elsewhere to determine which segment should be played when music is toggled on with the F7 key.

snSubLevel = 1;
snLastTempo = 0;
gnLastStyle = gnCurrentStyle;
gnLastChordMap = gnCurrentChordMap;
gnCurrentStyle = level % NUM_STYLES;
gnCurrentChordMap = ((level - 1) / 2) % NUM_CHORDMAP;
HRESULT hr = S_OK;
MUSIC_TIME mtSegmentLength;
if (gapSegment[SEGMENT_1])
{
    gapSegment[SEGMENT_1]->Release();
}
hr = gpComposer->ComposeSegmentFromTemplate(
        gapStyle[gnCurrentStyle],
        gpIntroTemplate, 0,
        gapChordMap[gnCurrentStyle][gnCurrentChordMap],
        &gapSegment[SEGMENT_1]
);
if (!SUCCEEDED(hr))
{
    CleanupAndExit("Segment 1 composition failed");
}

We happen to know that the template has a signpost on the last measure that matches the signpost on the first measure, for graceful looping. Once the segment is composed, the last measure is lopped off. Note that the value of MEASURE_LENGTH was calculated in Step 1: Defines and Globals as (DMUS_PPQ * 4)—that is, four quarter-notes of music time. This is valid because the time signature is 4/4.

gapSegment[SEGMENT_1]->GetLength(&mtSegmentLength);
gapSegment[SEGMENT_1]->SetLength(
        mtSegmentLength - MEASURE_LENGTH);

Finally, the segment is set to loop repeatedly.

gapSegment[SEGMENT_1]->SetRepeats(999);

The second segment, based on gpGameTemplate, is composed and set up the same way.


Step 6: Playing a Primary Segment

In the previous step, the setup_game function in Donuts.cpp called the ComposeNewSegments function, which created two primary segments to be used for the current game level. Now the setup_game function plays the first of these segments:

gpPerformance->PlaySegment(
    gapSegment[SEGMENT_1], 0, 0, NULL);

Note that the absence of any flag causes the segment to be played immediately.

The function now plays the default band segment that was created for the current style. (Remember, there are two different styles that alternate when the game level changes. Each style has two bands, the default band and the "shield" band.) Playing the band segment ensures that the correct set of instruments is playing the music. Note that the band segment must be flagged as secondary. No start time is given in the third parameter because the changes are to be made immediately, and the last parameter is NULL because we don't require a pointer to the segment state.

gpPerformance->PlaySegment(
    gapDefaultSegment[gnCurrentStyle],
    DMUS_SEGF_SECONDARY,
    0, NULL);

The default band for the style is used when the player's ship is unshielded, which is always the case at the beginning of a level. The application plays the second band inside the UpdateDisplayList function in response to the shields being turned on, and plays the default band again when the shields are turned off.


Step 7: Transitioning to Another Primary Segment

DMDonuts cues a different primary segment in two places: when the game level changes, and when the first hit is made on a donut on any level. The following code is from the CheckForHits function. When the function finds that a hit is the first to have occurred on this level, it tells the DirectMusic composer to create a transition from the current (introductory) theme to the action theme. The call to IDirectMusicComposer::AutoTransition also cues the transition and the following action segment so that they play automatically; in this case, the transition will start on the next measure boundary.

if (gapSegment[SEGMENT_TRANS_1])
{
    gapSegment[SEGMENT_TRANS_1]->Release();
}
gpComposer->AutoTransition(
        gpPerformance,                 // The performance
        gapSegment[SEGMENT_2],         // The next primary segment
        DMUS_COMMANDT_FILL,            // Embellishment type
        DMUS_COMPOSEF_MODULATE |       // Modulate to new key
        DMUS_COMPOSEF_MEASURE,         // and start on measure
        gapChordMap[gnCurrentStyle] [gnCurrentChordMap],
                                       // Use current chordmap
        &gapSegment[SEGMENT_TRANS_1],  // Created transition segment
        NULL, NULL                     // No segment states needed
);

Note that you don't have to stop the first segment. It stops automatically when a transition or new primary segment is played.


Step 8: Playing a Motif

DMDonuts uses several motifs to accent the game action: for example, when the player's ship bounces off the edge of the screen and when an object is hit by the player's fire.

Playing a motif is very simple, as the following code from the CheckForHits function shows. The MOTIF_BLOWUP motif is played whenever a donut is hit.

gpPerformance->PlaySegment(
        gapMotif[gnCurrentStyle][MOTIF_BLOWUP],
        DMUS_SEGF_SECONDARY | DMUS_SEGF_GRID, 0, NULL);

The motif must be played as a secondary segment so that it does not interrupt the main theme being played as the primary segment. It is cued to play on a grid boundary, the lowest resolution at which it can play without being out of step with the primary segment. The rtStartTime parameter is 0, indicating that the segment should play as soon as the first boundary is reached, and the ppSegmentState parameter is NULL because there's no need to access the segment while it is playing.


Step 9: Handling Notifications

Back in Step 4: Setting Up Notifications we saw how DMDonuts requests notification whenever a segment ends and whenever a beat or measure boundary is reached. The purpose of this notification is to help limit the number of "blowup" motifs playing at any one time.

Notifications are retrieved in the WinMain function. After dealing with any messages in the queue, the application checks to see if there are any pending notifications. It does this by calling the IDirectMusicPerformance::GetNotificationPMsg method. If no notification message is pending, the method returns S_FALSE and no further action is needed. A return of S_OK indicates that a notification message has been placed in *pEvent. Because it has only requested notifications relevant to the beat, the application doesn't actually need to examine the message, which is immediately discarded. It then resets snMaxBlowUps, which tracks how many more blowup motifs can be played till the next beat.

if (gpPerformance)
{
    DMUS_NOTIFICATION_PMSG* pEvent;
    while ( S_OK == gpPerformance->GetNotificationPMsg(&pEvent))
    {
        gpPerformance->FreePMsg((DMUS_PMSG*)pEvent);
        snMaxBlowUps = BLOWUPS_PER_BEAT;
    }
}


Step 10: Shutting Down DirectMusic

Closing down DirectMusic is a matter of clearing the loader cache, stopping the performance, releasing all the objects that have been created, and finally dereferencing COM (remember, every call to CoInitialize must have a matching call to CoUninitialize).

The following function performs the necessary cleanup in Donuts.cpp:

void CleanUpDMusic()
{
    if (gpLoader)
    {
        gpLoader->ClearCache(GUID_DirectMusicAllTypes);
        gpLoader->Release();
    }

    if (gpComposer)
    {
        gpComposer->Release();
    }

    if (gpIntroTemplate)
    {
        gpIntroTemplate->Release();
    }

    if (gpGameTemplate)
    {
        gpGameTemplate->Release();
    }

    for (short n = 0; n < NUM_STYLES; n++)
    {
        if (gapShieldBand[n])
        {
            gapShieldBand[n]->Unload(gpPerformance);
            gapShieldBand[n]->Release();
        }
        if (gapDefaultBand[n])
        {
            gapDefaultBand[n]->Unload(gpPerformance);
            gapDefaultBand[n]->Release();
        }
        if (gapShieldSegment[n])
        {
            gapShieldSegment[n]->Release();
        }

        if (gapDefaultSegment[n])
        {
            gapDefaultSegment[n]->Release();
        }

        if (gapStyle[n])
        {
            gapStyle[n]->Release();
        }

        for (short m = 0; m < NUM_CHORDMAP; m++)
        {
            if (gapChordMap[n][m])
            {
                gapChordMap[n][m]->Release();
            }
        }

        for (m = 0; m < NUM_MOTIFS; m++)
        {
            if (gapMotif[n][m])
            {
                gapMotif[n][m]->Release();
            }
        }
    }

    if (gpPerformance)
    {
        gpPerformance->Stop( NULL, NULL, 0, 0 );
        gpPerformance->CloseDown();
        gpPerformance->Release();
    }

    for (n = 0; n < NUM_SEGMENTS; n++)
    {
        if (gapSegment[n])
        {
            gapSegment[n]->Release();
        }
    }

    if (gpDirectMusic)
    {
        gpDirectMusic->Release();
    }

    CoUninitialize();
}


DirectMusic Reference

This section contains reference information for the API elements of DirectMusic™. Reference material is divided into the following categories.

  • Interfaces
  • Messages
  • Structures
  • File Structures
  • DLS Structures
  • Enumerated Types
  • Return Values


Interfaces

This section contains references for the following DirectMusic interfaces:

  • IDirectMusic
  • IDirectMusicBand
  • IDirectMusicBuffer
  • IDirectMusicChordMap
  • IDirectMusicCollection
  • IDirectMusicComposer
  • IDirectMusicDownload
  • IDirectMusicDownloadedInstrument
  • IDirectMusicGetLoader
  • IDirectMusicGraph
  • IDirectMusicInstrument
  • IDirectMusicLoader
  • IDirectMusicObject
  • IDirectMusicPerformance
  • IDirectMusicPort
  • IDirectMusicPortDownload
  • IDirectMusicSegment
  • IDirectMusicSegmentState
  • IDirectMusicStyle
  • IDirectMusicThru
  • IDirectMusicTool
  • IDirectMusicTrack
  • IKsControl
  • IReferenceClock


IDirectMusic

The IDirectMusic interface provides methods for managing buffers, ports, and the master clock. There should not be more than one instance of this interface per application.

Note There is no helper function to create this interface. Applications use the COM CoCreateInstance function or the IDirectMusicPerformance::Init method to create a DirectMusic object.

The methods of the DirectDraw interface can be organized into the following groups:

Activation | Activate
Buffers | CreateMusicBuffer
Linkage | SetDirectSound
Ports | CreatePort
 | EnumPort
 | GetDefaultPort
Timing | EnumMasterClock
 | GetMasterClock
 | SetMasterClock

All COM interfaces inherit the IUnknown interface methods. This interface supports the following three methods:

IUnknown | AddRef
 | QueryInterface
 | Release

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicc.h.


IDirectMusic::Activate

The IDirectMusic::Activate method activates or deactivates all output ports created from this interface.

HRESULT Activate(
  BOOL fEnable
);

Parameters

fEnable
Switch to activate (TRUE) or deactivate (FALSE) all port objects created in this instance of DirectMusic.

Return Values

If the method succeeds, the return value is S_OK.

Remarks

Applications should call IDirectMusic::Activate(FALSE) when they lose input focus if they do not need to play music in the background. This will allow another application that may have the input focus to have access to the ports. Once the application has input focus again, it should call Activate(TRUE) to enable all of its allocated ports.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicc.h.

See Also

IDirectMusicPort::Activate


IDirectMusic::CreateMusicBuffer

The IDirectMusic::CreateMusicBuffer method creates a DirectMusicBuffer object to hold music messages being sequenced to the port. Most applications do not need to call this method directly, as buffer management is handled by the performance when a port is added.

HRESULT CreateMusicBuffer(
  LPDMUS_BUFFERDESC pBufferDesc,
  LPDIRECTMUSICBUFFER *ppBuffer,
  LPUNKNOWN pUnkOuter
);

Parameters

pBufferDesc
Address of the DMUS_BUFFERDESC structure that contains the description of the music buffer to be created. The application must initialize the dwSize member of this structure before passing the pointer. See Remarks.
ppBuffer
Address of a variable to receive the IDirectMusicBuffer interface pointer.
pUnkOuter
Address of the controlling object's IUnknown interface for COM aggregation. Aggregration is not currently supported, so this value must be set to NULL.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return one of the following error values:

E_INVALIDARG
E_NOAGGREGATION
E_NOINTERFACE
E_OUTOFMEMORY
E_POINTER

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicc.h.


IDirectMusic::CreatePort

The IDirectMusic::CreatePort method is used to create an object for a particular DirectMusic port.

HRESULT CreatePort(
  REFCLSID rclsidPort,
  LPDMUS_PORTPARAMS pPortParams,
  LPDIRECTMUSICPORT *ppPort,
  LPUNKNOWN pUnkOuter
);

Parameters

rclsidPort
Reference to (C++) or address of (C) the GUID that identifies the port for which the IDirectMusicPort interface is to be created. The GUID is retrieved through the IDirectMusic::EnumPort method. If it is GUID_NULL, then the returned port will be the default port. For more information, see Default Port.
pPortParams
Address of a DMUS_PORTPARAMS structure containing parameters for the port. The dwSize member of this structure must be initialized before the method is called.
ppPort
Address of a variable to receive an IDirectMusicPort interface pointer.
pUnkOuter
Address of the controlling object's IUnknown interface for COM aggregation. Aggregation is not currently supported, so this value must be NULL.

Return Values

If the method succeeds, the return value is S_OK, or S_FALSE if a requested parameter is not available.

If it fails, the method may return one of the following error values:

DMUS_E_DSOUND_NOT_SET
E_INVALIDARG
E_NOAGGREGATION
E_NOINTERFACE
E_OUTOFMEMORY
E_POINTER

Remarks

By default, the port is inactive when it is created. It must be activated by a call to IDirectMusic::Activate or IDirectMusicPort::Activate.

If not all parameters could be obtained, then the DMUS_PORTPARAMS structure will be changed as follows to match the available parameters of the port.

On entry, the dwValidParams member of the structure indicates which members in the structure are valid. If the flag is not set for a member of the structure, then a default value is set for that parameter when the port is created.

On return, the flags in dwValidParams show which port parameters were set. If a particular parameter was not requested but was set to the default, then that flag is added to those passed in.

If the port supports a specified parameter, but the given value for the parameter is out of range, then the parameter value in *pPortParams will be changed. In this case, the flag in dwValidParams remains set, but S_FALSE will be returned to indicate that the value has been changed.

The following code shows how an application can request reverb capabilities and determine if they were obtained. (For an alternative way of checking and setting port properties, see Port Property Sets.)

DMUS_PORTPARAMS params;

ZeroMemory(&params, sizeof(params));
params.dwSize = sizeof(params);
params.dwValidParams = DMUS_PORTPARAMS_EFFECTS;
params.dwEffectFlags = DMUS_EFFECT_REVERB;
HRESULT hr = pDirectMusic->CreatePort(guidPort, &params,
        &port, NULL);
if (SUCCEEDED(hr))
{
    fGotReverb = TRUE;
    if (hr == S_FALSE)
    {
        if (!(params.dwValidParams & DMUS_PORTPARAMS_EFFECTS))
        {
            // Device does not support any effects
            fGotReverb = FALSE;
        }
        else if (!(params.dwEffectFlags & DMUS_EFFECT_REVERB))
        {
            // Device understands effects,
            // but could not allocate reverb
            fGotReverb = FALSE;
        }
    }
}

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicc.h.


IDirectMusic::EnumMasterClock

The IDirectMusic::EnumMasterClock method is used to enumerate and get the description of the clocks that DirectMusic can use as the master clock. Each time it is called, this method retrieves information about a single clock.

HRESULT EnumMasterClock(
  DWORD dwIndex,
  LPDMUS_CLOCKINFO lpClockInfo
);

Parameters

dwIndex
Index of the clock for which the description is to be returned. This parameter should be 0 on the first call and then incremented by 1 in each subsequent call until S_FALSE is returned.
lpClockInfo
Address of a DMUS_CLOCKINFO structure to receive the description of the clock. The application must initialize the dwSize member of this structure before passing the pointer.

Return Values

If the method succeeds, the return value is S_OK, or S_FALSE if there is no clock with that index number.

If it fails, the method may return one of the following error values:

E_INVALIDARG
E_NOINTERFACE
E_POINTER

Remarks

Applications should not rely on or store the index number of a clock. Rebooting or adding and removing hardware could cause the index number of a clock to change.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicc.h.

See Also

IDirectMusic::SetMasterClock, IDirectMusic::GetMasterClock


IDirectMusic::EnumPort

The IDirectMusic::EnumPort method is used to enumerate and get the capabilities of the DirectMusic ports connected to the system. Each time it is called, this method retrieves information about a single port.

HRESULT EnumPort(
  DWORD dwIndex,
  LPDMUS_PORTCAPS pPortCaps
);

Parameters

dwIndex
Index of the port for which the capabilities are to be returned. This parameter should be 0 on the first call and then incremented by 1 in each subsequent call until S_FALSE is returned.
pPortCaps
Address of the DMUS_PORTCAPS structure to receive the capabilities of the port. The dwSize member of this structure must be initialized before the pointer is passed.

Return Values

If the method succeeds, the return value is S_OK, or S_FALSE if there is no port with that index value.

If it fails, the method may return one of the following error values:

E_INVALIDARG
E_NOINTERFACE
E_POINTER

Remarks

Applications should not rely on or store the index number of a port. Rebooting or adding or removing ports could cause the index number of a port to change.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicc.h.


IDirectMusic::GetDefaultPort

The IDirectMusic::GetDefaultPort method retrieves the GUID of the default output port. This is the port that will be created if GUID_NULL is passed to IDirectMusic::CreatePort.

HRESULT GetDefaultPort(
  LPGUID pguidPort
);

Parameters

pguidPort
Address of a variable to receive the default port GUID.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return E_POINTER.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicc.h.

See Also

Default Port


IDirectMusic::GetMasterClock

The IDirectMusic::GetMasterClock method returns the GUID and a pointer to the IReferenceClock interface for the clock that is currently set as the DirectMusic master clock.

HRESULT GetMasterClock(
  LPGUID pguidClock,
  IReferenceClock **ppReferenceClock
);

Parameters

pguidClock
Address of a variable to receive the master clock's GUID. The application can pass NULL if this value is not desired.
ppReferenceClock
Address of a variable to receive the IReferenceClock interface pointer for this clock. The application can pass NULL if this value is not desired.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return one of the following error values:

E_NOINTERFACE
E_POINTER

Remarks

The IReferenceClock interface pointer must be released once the application has finished using the interface.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicc.h.

See Also

IDirectMusic::SetMasterClock


IDirectMusic::SetDirectSound

The IDirectMusic::SetDirectSound method connects DirectMusic to a DirectSound object for wave output.

HRESULT SetDirectSound(
  LPDIRECTSOUND pDirectSound,
  HWND hWnd
);

Parameters

pDirectSound
IDirectSound interface to use for output. If this parameter is NULL, the method creates a DirectSound object and sets the DSSCL_PRIORITY cooperative level. (See Remarks.) If this parameter contains an IDirectSound pointer, the caller is responsible for setting the cooperative level.
hWnd
Window handle associated with the DirectSound object created by this call. If this value is NULL, the current foreground window is set as the focus window. See Remarks.

If pDirectSound is a valid interface, this parameter is ignored, as it is the caller's responsibility to supply a valid window handle in the call to IDirectSound::SetCooperativeLevel.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return DMUS_E_DSOUND_ALREADY_SET.

Remarks

The specified DirectSound object will be the one used for rendering audio on all ports. This default can be overridden by using the IDirectMusicPort::SetDirectSound method.

Whenever the IDirectMusic::SetDirectSound method is called, any existing DirectSound object is released.

When pDirectSound is NULL, a new DirectSound object is not created until a port that uses DirectSound is activated, and the DirectSound object is automatically released when the last port using it is deactivated.

If you created the DirectSound object yourself, you can release it by calling this method with NULL in the pDirectSound parameter after deactivating all ports. (It is an error to call SetDirectSound on an active port.)

You can pass NULL in the hWnd parameter in order to pass the current foreground window handle to DirectSound. However, it is not wise to assume that the application window will be in the foreground during initialization. In general, the top-level application window handle should be passed to DirectMusic, DirectSound, and DirectDraw. See the Remarks for IDirectSound::SetCooperativeLevel.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicc.h.

See Also

Integrating DirectMusic and DirectSound


IDirectMusic::SetMasterClock

The IDirectMusic::SetMasterClock method sets the DirectMusic master clock to a clock identified by a GUID obtained through the IDirectMusic::EnumMasterClock call. There is only one master clock for all DirectMusic applications.

HRESULT SetMasterClock(
  REFGUID rguidClock
);

Parameters

rguidClock
Reference to (C++) or address of (C) the GUID that identifies the clock to set as the master clock for DirectMusic. This parameter must be a GUID returned by the IDirectMusic::EnumMasterClock method.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return DMUS_E_PORTS_OPEN.

Remarks

If another running application is also using DirectMusic, it is not possible to change the master clock until that application is shut down.

Most applications will not need to call SetMasterClock. It should not be called unless there is a need to synchronize tightly with a hardware timer other than the system clock.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicc.h.

See Also

IDirectMusic::GetMasterClock, IDirectMusic::EnumMasterClock


IDirectMusicBand

The IDirectMusicBand interface represents a DirectMusic band object. A band is used to set the instrument choices and mixer settings for a set of PChannels. For an overview, see Using Bands.

Bands can come from several places. They can be stored directly in their own files, or embedded in a style's band list or a segment's band track.

The DirectMusicBand object also supports the IPersistStream and IDirectMusicObject interfaces for loading its data.

The IDirectMusicBand interface has the following methods:

Segment creation | CreateSegment
Instrument data | Download
 | Unload

All COM interfaces inherit the IUnknown interface methods. This interface supports the following three methods:

IUnknown | AddRef
 | QueryInterface
 | Release

The LPDMUS_BAND type is defined as a pointer to the IDirectMusicBand interface.

typedef IDirectMusicBand __RPC_FAR *LPDMUS_BAND;

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.


IDirectMusicBand::CreateSegment

The IDirectMusicBand::CreateSegment method creates a DirectMusicSegment object that can be used to perform the volume, pan, transposition, and patch change commands in the band dynamically using the IDirectMusicPerformance::PlaySegment method.

HRESULT CreateSegment(
  IDirectMusicSegment** ppSegment
);

Parameters

ppSegment
Address of a variable to receive a pointer to the created segment.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return one of the following error values:

E_FAIL
E_OUTOFMEMORY
E_POINTER

Remarks

For an example of creating a segment from a band, see Making Band Changes Programmatically.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.


IDirectMusicBand::Download

The IDirectMusicBand::Download method downloads the DLS data for instruments in the band to a performance object. The method downloads each instrument in the band by calling the IDirectMusicPerformance::DownloadInstrument method. DownloadInstrument, in turn, uses the PChannel of the instrument to find the appropriate port, and then calls the IDirectMusicPort::DownloadInstrument method on that port.

Once a band has been downloaded, the instruments in the band may be selected, either individually with program change MIDI messages, or all at once by playing a band segment created through a call to the IDirectMusicBand::CreateSegment method.

HRESULT Download(
  IDirectMusicPerformance* pPerformance
);

Parameters

pPerformance
Performance to which instruments are to be downloaded. The performance manages the mapping of PChannels to DirectMusic ports.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return one of the following error values:

E_OUTOFMEMORY
E_POINTER

Remarks

Because a downloaded band uses synthesizer resources, it should be unloaded when no longer needed, by using the IDirectMusicBand::Unload method.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicBand::Unload


IDirectMusicBand::Unload

The IDirectMusicBand::Unload method unloads the DLS data for instruments in the band previously downloaded by IDirectMusicBand::Download.

HRESULT Unload(
  IDirectMusicPerformance* pPerformance
);

Parameters

pPerformance
Performance from which to unload instruments.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return E_POINTER.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicBand::Download, IDirectMusicPort::UnloadInstrument


IDirectMusicBuffer

The IDirectMusicBuffer interface represents a buffer containing timestamped data (typically in the form of MIDI messages) to be sequenced by a port. Unlike a segment, the buffer contains a small amount of data (typically less than 200 milliseconds) over which the application has control at event granularity.

Unless your application is doing its own sequencing, you will not need to use the methods of this interface.

Buffer objects are completely independent of port objects until the buffer is passed to the port by a call to the IDirectMusicPort::PlayBuffer or IDirectMusicPort::Read method. The application is then free to reuse the buffer.

The methods of the IDirectMusicBuffer interface can be organized in the following groups:

Data | Flush
 | GetNextEvent
 | GetRawBufferPtr
 | PackStructured
 | PackUnstructured
 | ResetReadPtr
Parameters | GetBufferFormat
 | GetMaxBytes
 | GetUsedBytes
 | SetUsedBytes
Time | GetStartTime
 | SetStartTime
 | TotalTime

All COM interfaces inherit the IUnknown interface methods. This interface supports the following three methods:

IUnknown | AddRef
 | QueryInterface
 | Release

The LPDIRECTMUSICBUFFER type is defined as a pointer to the IDirectMusicBuffer interface:

typedef IDirectMusicBuffer *LPDIRECTMUSICBUFFER;

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicc.h.


IDirectMusicBuffer::Flush

The IDirectMusicBuffer::Flush method discards all data in the buffer.

HRESULT Flush();

Parameters

None.

Return Values

The method always returns S_OK.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicc.h.


IDirectMusicBuffer::GetBufferFormat

The IDirectMusicBuffer::GetBufferFormat method retrieves the GUID representing the buffer format.

HRESULT GetBufferFormat(
  LPGUID pGuidFormat
);

Parameters

pGuidFormat
Address of a variable to receive the GUID of the buffer format.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return E_POINTER.

Remarks

If the format was not specified when the buffer was created, then KSDATAFORMAT_SUBTYPE_DIRECTMUSIC is returned in *pGuidFormat.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicc.h.

See Also

IDirectMusic::CreateMusicBuffer, DMUS_EVENTHEADER


IDirectMusicBuffer::GetMaxBytes

The IDirectMusicBuffer::GetMaxBytes method retrieves the number of bytes that can be stored in the buffer.

HRESULT GetMaxBytes(
  LPDWORD pcb
);

Parameters

pcb
Address of a variable to contain the maximum number of bytes the buffer can hold.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return E_POINTER.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicc.h.


IDirectMusicBuffer::GetNextEvent

The IDirectMusicBuffer::GetNextEvent method returns information about the next message in the buffer and advances the read pointer.

HRESULT GetNextEvent(
  LPREFERENCE_TIME prt,
  LPDWORD pdwChannelGroup,
  LPDWORD pdwLength,
  LPBYTE* ppData
);

Parameters

prt
Address of a variable to receive the time of the message.
pdwChannelGroup
Address of a variable to receive the channel group of the message.
pdwLength
Address of a variable to receive the length, in bytes, of the message.
ppData
Address of a variable to receive a pointer to the message data.

Return Values

If the method succeeds, the return value is S_OK, or S_FALSE if there are no messages in the buffer.

If it fails, the method may return E_POINTER.

Remarks

Any of the passed pointers can be NULL if the item is not needed.

The pointer returned in ppData is valid only for the lifetime of the buffer object.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicc.h.

See Also

IDirectMusicBuffer::ResetReadPtr


IDirectMusicBuffer::GetRawBufferPtr

The IDirectMusicBuffer::GetRawBufferPtr method returns a pointer to the underlying buffer data structure.

HRESULT GetRawBufferPtr(
  LPBYTE* ppData
);

Parameters

ppData
Address of a variable to receive a pointer to the buffer's data.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return E_POINTER.

Remarks

This method returns a pointer to the raw data of the buffer. The format of the data depends on the implementation. The lifetime of the data is the same as the lifetime of the buffer object; therefore, the returned pointer should not be held after the next call to the IDirectMusicBuffer::Release method.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicc.h.


IDirectMusicBuffer::GetStartTime

The IDirectMusicBuffer::GetStartTime method retrieves the start time of the data in the buffer, relative to the master clock.

HRESULT GetStartTime(
  LPREFERENCE_TIME prt
);

Parameters

prt
Address of a variable to receive the start time.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return one of the following error values:

DMUS_E_BUFFER_EMPTY
E_POINTER

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicc.h.

See Also

IDirectMusicBuffer::SetStartTime, IDirectMusicBuffer::TotalTime


IDirectMusicBuffer::GetUsedBytes

The IDirectMusicBuffer::GetUsedBytes method retrieves the number of bytes of data in the buffer.

HRESULT GetUsedBytes(
  LPDWORD pcb
);

Parameters

pcb
Address of a variable to receive the number of used bytes.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return E_POINTER.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicc.h.

See Also

IDirectMusicBuffer::SetUsedBytes


IDirectMusicBuffer::PackStructured

The IDirectMusicBuffer::PackStructured method inserts fixed-length data (typically a MIDI channel message), along with timing and routing information, into the buffer.

HRESULT PackStructured(
  REFERENCE_TIME rt,
  DWORD dwChannelGroup,
  DWORD dwChannelMessage
);

Parameters

rt
Absolute time of the message. See Remarks.
dwChannelGroup
Channel group to which the data belongs.
dwChannelMessage
Data (MIDI message) to pack.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return one of the following error values:

DMUS_E_INVALID_EVENT
E_OUTOFMEMORY

Remarks

At least 32 bytes (the size of DMUS_EVENTHEADER plus dwChannelMessage) must be free in the buffer.

The rt parameter must contain the absolute time at which the data is to be sent to the port. To play a message "now," retrieve the time from the latency clock and use this as rt. See IDirectMusicPort::GetLatencyClock.

Messages stamped with the same time do not necessarily play in the same order in which they were placed in the buffer.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicc.h.

See Also

IDirectMusicBuffer::PackUnstructured


IDirectMusicBuffer::PackUnstructured

The IDirectMusicBuffer::PackUnstructured method inserts unstructured data (typically a MIDI system exclusive message), along with timing and routing information, into the buffer.

HRESULT PackUnstructured(
  REFERENCE_TIME rt,
  DWORD dwChannelGroup,
  DWORD cb,
  LPBYTE lpb
);

Parameters

rt
Absolute time of the message.
dwChannelGroup
Channel group to which the message belongs.
cb
Size of the data, in bytes.
lpb
Pointer to the data.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return one of the following error values:

E_OUTOFMEMORY
E_POINTER

Remarks

This method can be used to send any kind of data to the port.

At least 28 bytes (the size of DMUS_EVENTHEADER) plus the size of the data, padded to a multiple of four bytes, must be free in the buffer. The buffer space required can be obtained by using the macro DMUS_EVENT_SIZE(cb), where cb is the size of the data.

The rt parameter must contain the absolute time at which the data is to be sent to the port. To play a message "now," retrieve the time from the latency clock and use this as rt. See IDirectMusicPort::GetLatencyClock.

Messages stamped with the same time do not necessarily play in the same order in which they were placed in the buffer.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicc.h.

See Also

IDirectMusicBuffer::PackStructured


IDirectMusicBuffer::ResetReadPtr

The IDirectMusicBuffer::ResetReadPtr method sets the read pointer to the start of the data in the buffer.

HRESULT ResetReadPtr()

Parameters

None.

Return Values

The method always returns S_OK.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicc.h.

See Also

IDirectMusicBuffer::GetNextEvent


IDirectMusicBuffer::SetStartTime

The IDirectMusicBuffer::SetStartTime method sets the start time of the data in the buffer, relative to the master clock.

HRESULT SetStartTime(
  REFERENCE_TIME rt
);

Parameters

rt
New start time for the buffer.

Return Values

The method always returns S_OK.

Remarks

Events already in the buffer are timestamped relative to the start time, and will play at the same offset from the new start time.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicc.h.

See Also

IDirectMusicBuffer::GetStartTime


IDirectMusicBuffer::SetUsedBytes

The IDirectMusicBuffer::SetUsedBytes method sets the number of bytes of data in the buffer.

HRESULT SetUsedBytes(
  DWORD cb
);

Parameters

cb
The number of valid data bytes in the buffer.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return DMUS_E_BUFFER_FULL.

Remarks

This method allows an application to repack a buffer manually. Normally this should only be done if the data format in the buffer is different from the default format provided by DirectMusic.

The method fails if the specified number of bytes exceeds the maximum buffer size as returned by the IDirectMusicBuffer::GetMaxBytes method.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicc.h.

See Also

IDirectMusicBuffer::GetUsedBytes


IDirectMusicBuffer::TotalTime

The IDirectMusicBuffer::TotalTime method returns the total time spanned by the data in the buffer.

HRESULT TotalTime(
  LPREFERENCE_TIME prtTime
);

Parameters

prtTime
Address of a variable to receive the total time spanned by the buffer, in units of 100 nanoseconds.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return E_POINTER.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicc.h.

See Also

IDirectMusicBuffer::GetStartTime


IDirectMusicChordMap

The IDirectMusicChordMap interface represents a chordmap. Chordmaps provide the composer (represented by the IDirectMusicComposer interface) with the information it needs to compose chord progressions, which it uses to build segments and automatic transitions. Chordmaps can also be used to change the chords in an existing segment.

The DirectMusicChordMap object also supports the IDirectMusicObject and IPersistStream interfaces for loading its data.

The interface has the following method:

IDirectMusicChordMap GetScale

All COM interfaces inherit the IUnknown interface methods. This interface supports the following three methods:

IUnknown | AddRef
 | QueryInterface
 | Release

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.


IDirectMusicChordMap::GetScale

The IDirectMusicChordMap::GetScale method retrieves the scale associated with the chordmap.

HRESULT GetScale(
  DWORD* pdwScale
);

Parameters

pdwScale
Address of a variable to receive the scale value.

Return Values

If the method succeeds, the return value is S_OK.

If the method fails, the return value may be E_POINTER.

Remarks

The scale is defined by the bits in a DWORD, split into a scale pattern (lower 24 bits) and a root (upper 8 bits). For the scale pattern, the low bit (0x0001) is the lowest note in the scale, the next higher (0x0002) is a semitone higher, and so on for two octaves. The upper 8 bits give the root of the scale as an integer between 0 and 23 (low C to middle B).

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.


IDirectMusicCollection

The IDirectMusicCollection interface manages an instance of a DLS file. The collection provides methods to access instruments and download them to the synthesizer by means of the IDirectMusicPort interface.

The DirectMusicCollection object also supports the IDirectMusicObject and IPersistStream interfaces for loading its data.

For more information on how to work with collections, see Using Downloadable Sounds.

The IDirectMusicCollection interface has the following methods:

Instruments | EnumInstrument
 | GetInstrument

All COM interfaces inherit the IUnknown interface methods. This interface supports the following three methods:

IUnknown | AddRef
 | QueryInterface
 | Release

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicc.h.


IDirectMusicCollection::EnumInstrument

The IDirectMusicCollection::EnumInstrument method retrieves the patch and name of an instrument by its index in the collection.

HRESULT EnumInstrument(
  DWORD dwIndex,
  DWORD* pdwPatch,
  LPWSTR pwszName,
  DWORD dwNameLen
);

Parameters

dwIndex
Index of the instrument in the collection.
pdwPatch
Address of a variable to receive the patch number.
pwszName
Address of a buffer to receive the instrument name. Can be NULL if the name is not wanted.
dwNameLen
Size of the instrument name buffer, in WCHARs.

Return Values

If the method succeeds, the return value is S_OK, or S_FALSE if there is no instrument with that index number.

If it fails, the method may return one of the following error values:

E_FAIL
E_OUTOFMEMORY
E_POINTER

Remarks

To enumerate all instruments in a collection, start with a dwIndex of 0 and increment until EnumInstrument returns S_FALSE.

The patch number returned in pdwPatch describes the full patch address, including the MIDI parameters for MSB and LSB bank select. For more information, see MIDI Channel Messages.

Although the ordering of the enumeration is consistent within one instance of a DLS collection, it has no relationship to the ordering of instruments in the file, their patch numbers, or their names.

For an example of instrument enumeration, see Working with Instruments.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicc.h.


IDirectMusicCollection::GetInstrument

The IDirectMusicCollection::GetInstrument method retrieves an instrument from a collection by its patch number.

HRESULT GetInstrument(
  DWORD dwPatch,
  IDirectMusicInstrument** ppInstrument
);

Parameters

dwPatch
Instrument patch number.
ppInstrument
Address of a variable to receive a pointer to the IDirectMusicInstrument interface.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return one of the following error values:

DMUS_E_INVALIDPATCH
E_FAIL
E_OUTOFMEMORY
E_POINTER

Remarks

The patch number passed in dwPatch describes the full patch address, including the MIDI parameters for MSB and LSB bank select. MSB is shifted left 16 bits and LSB is shifted left 8 bits. For more information, see MIDI Channel Messages.

In addition, the high bit must be set (0x80000000) if the instrument is specifically a drum kit, intended to be played on MIDI channel 10. Note that this a special tag for DLS Level 1, which always puts drums on MIDI channel 10.

For an example of how this method is used, see Working with Instruments.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicc.h.


IDirectMusicComposer

The IDirectMusicComposer interface permits access to the composition engine. In addition to building new segments from templates and chordmaps, the composer can generate transitions between different segments. It can also apply a chordmap to an existing segment, thus altering the chord progression and the mood of the music.

For an overview, see Music Composition.

The methods of the IDirectMusicComposer interface can be grouped as follows:

Changing chords | ChangeChordMap
Composing segments | ComposeSegmentFromShape
 | ComposeSegmentFromTemplate
Composing templates | ComposeTemplateFromShape
Composing transitions | AutoTransition
 | ComposeTransition

All COM interfaces inherit the IUnknown interface methods. This interface supports the following three methods:

IUnknown | AddRef
 | QueryInterface
 | Release

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.


IDirectMusicComposer::AutoTransition

The IDirectMusicComposer::AutoTransition method composes a transition from inside a performance's primary segment (or from silence) to another segment, and then cues the transition and the second segment to play.

HRESULT AutoTransition(
  IDirectMusicPerformance* pPerformance,
  IDirectMusicSegment* pToSeg,
  WORD wCommand,
  DWORD dwFlags,
  IDirectMusicChordMap* pChordMap,
  IDirectMusicSegment** ppTransSeg,
  IDirectMusicSegmentState** ppToSegState,
  IDirectMusicSegmentState** ppTransSegState
);

Parameters

pPerformance
Performance in which to do the transition.
pToSeg
Segment to which the transition should smoothly flow. See Remarks.
wCommand
Embellishment to use when composing the transition. See DMUS_COMMANDT_TYPES. If this value is DMUS_COMMANDT_ENDANDINTRO, the method will compose a segment containing both an ending to the primary segment and an intro to pToSeg.
dwFlags
Composition options. See DMUS_COMPOSEF_FLAGS.
pChordMap
Chordmap to be used when composing the transition.
ppTransSeg
Address of a variable to receive a pointer to the created segment. This value may be NULL, in which case the pointer is not returned.
ppToSegState
Address of a variable to receive a pointer to the segment state created by the performance (pPerformance) for the segment following the transition (pToSeg). See Remarks.
ppTransSegState
Address of a variable to receive a pointer to receive the segment state created by the performance (pPerformance) for the created segment (ppTransSeg). See Remarks.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return E_POINTER.

Remarks

The value in pToSeg can be NULL as long as dwFlags does not include DMUS_COMPOSEF_MODULATE. If pToSeg is NULL or doesn't contain a style track, intro embellishments are not valid. If the currently playing segment is NULL or doesn't contain a style track, then fill, break, end, and groove embellishments are not valid.

It is possible for both the currently playing segment and pToSeg to be NULL or segments that don't contain style tracks (such as segments based on MIDI files). If so, all embellishments are invalid and no transition occurs between the currently playing segment and pToSeg. Both ppTransSeg and ppTransSegState will return NULL, but the method succeeds and cues the segment represented by pToSeg.

The value in pChordMap can be NULL. If so, an attempt is made to obtain a chordmap from a chordmap track, first from pToSeg, and then from the performance's primary segment. If neither of these segments contains a chordmap track, the chord occurring at the current time in the primary segment is used as the chord in the transition.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicComposer::ComposeTransition, Using Transitions


IDirectMusicComposer::ChangeChordMap

The IDirectMusicComposer::ChangeChordMap method modifies the chords and scale pattern of an existing segment to reflect a new chordmap.

HRESULT ChangeChordMap(
  IDirectMusicSegment* pSectionSeg,
  BOOL fTrackScale,
  IDirectMusicChordMap* pChordMap
);

Parameters

pSectionSeg
Segment in which to change the chordmap.
fTrackScale
If TRUE, the method transposes all the chords to be relative to the root of the new chordmap's scale, rather than leaving their roots as they were.
pChordMap
The new chordmap for the segment.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return E_POINTER.

Remarks

The method can be called while the segment is playing.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.


IDirectMusicComposer::ComposeSegmentFromShape

The IDirectMusicComposer::ComposeSegmentFromShape method creates an original segment from a style and chordmap based on a predefined shape. The shape represents the way chords and embellishments occur over time across the segment.

HRESULT ComposeSegmentFromShape(
  IDirectMusicStyle* pStyle,
  WORD wNumMeasures,
  WORD wShape,
  WORD wActivity,
  BOOL fIntro,
  BOOL fEnd,
  IDirectMusicChordMap* pChordMap,
  IDirectMusicSegment** ppSectionSeg
);

Parameters

pStyle
Style from which to compose the segment.
wNumMeasures
Length, in measures, of the segment to be composed.
wShape
Shape of the segment to be composed. Possible values are of the DMUS_SHAPET_TYPES enumerated type.
wActivity
Rate of harmonic motion. Valid values are 0 through 3. Lower values mean more chord changes.
fIntro
TRUE if an introduction is to be composed for the segment.
fEnd
TRUE if an ending is to be composed for the segment.
pChordMap
Chordmap from which to create the segment.
ppSectionSeg
Address of a variable to receive a pointer to the created segment.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return E_POINTER.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicComposer::ComposeSegmentFromTemplate, IDirectMusicComposer::ComposeTemplateFromShape


IDirectMusicComposer::ComposeSegmentFromTemplate

The IDirectMusicComposer::ComposeSegmentFromTemplate method creates an original segment from a style, chordmap, and template.

HRESULT ComposeSegmentFromTemplate(
  IDirectMusicStyle* pStyle,
  IDirectMusicSegment* pTempSeg,
  WORD wActivity,
  IDirectMusicChordMap* pChordMap,
  IDirectMusicSegment** ppSectionSeg
);

Parameters

pStyle
Style from which to create the segment.
pTempSeg
Template from which to create the segment.
wActivity
Rate of harmonic motion. Valid values are 0 through 3. Lower values mean more chord changes.
pChordMap
Chordmap from which to create the segment.
ppSectionSeg
Address of a variable to receive a pointer to the created segment.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return one of the following error values:

E_INVALIDARG
E_POINTER

Remarks

If pStyle is non-NULL, it is used in composing the segment; if it is NULL, a style is retrieved from the template specified in pTempSeg. Similarly, if pChordMap is non-NULL, it is used in composing the segment; if it is NULL, a chordmap is retrieved from the template.

If pStyle is NULL and there is no style track in the template, or pChordMap is NULL and there is no chordmap track, the method returns E_INVALIDARG.

The length of the segment is equal to the length of the template passed in.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicComposer::ComposeSegmentFromShape, IDirectMusicComposer::ComposeTemplateFromShape, Using Templates


IDirectMusicComposer::ComposeTemplateFromShape

The IDirectMusicComposer::ComposeTemplateFromShape method creates a new template segment based on a predefined shape.

HRESULT ComposeTemplateFromShape(
  WORD wNumMeasures,
  WORD wShape,
  BOOL fIntro,
  BOOL fEnd,
  WORD wEndLength,
  IDirectMusicSegment** ppTempSeg
);

Parameters

wNumMeasures
Length, in measures, of the segment to be composed. This value must be greater than 0.
wShape
Shape of the segment to be composed. Possible values are of the DMUS_SHAPET_TYPES enumerated type.
fIntro
TRUE if an introduction is to be composed for the segment.
fEnd
TRUE if an ending is to be composed for the segment.
wEndLength
Length in measures of the ending, if one is to be composed. If fEnd is TRUE, this value must be greater than 0 and equal to or less than the number of measures available (that is, not used in the introduction). See also Remarks.
ppTempSeg
Address of a variable to receive a pointer to the created template segment.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return one of the following error values:

E_INVALIDARG
E_OUTOFMEMORY
E_POINTER

Remarks

The value of wEndLength should not be greater than the length of the longest ending available in any style likely to be associated with this template through the IDirectMusicComposer::ComposeSegmentFromTemplate method. The ending will start playing at wEndLength measures before the end of the segment, and if the ending is less than wEndLength measures long, the music will then revert to the regular groove.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicComposer::ComposeSegmentFromShape, IDirectMusicComposer::ComposeSegmentFromTemplate, Using Templates


IDirectMusicComposer::ComposeTransition

The IDirectMusicComposer::ComposeTransition method composes a transition from a measure inside one segment to another.

HRESULT ComposeTransition(
  IDirectMusicSegment* pFromSeg,
  IDirectMusicSegment* pToSeg,
  MUSIC_TIME mtTime,
  WORD wCommand,
  DWORD dwFlags,
  IDirectMusicChordMap* pChordMap,
  IDirectMusicSegment** ppSectionSeg
);

Parameters

pFromSeg
Segment from which to compose the transition.
pToSeg
Segment to which the transition should smoothly flow. Can be NULL if dwFlags does not include DMUS_COMPOSEF_MODULATE.
mtTime
The time in pFromSeg from which to compose the transition.
wCommand
Embellishment to use when composing the transition. See DMUS_COMMANDT_TYPES. If this value is DMUS_COMMANDT_ENDANDINTRO, the method will compose a segment containing both an ending to pFromSeg and an intro to pToSeg.
dwFlags
Composition options. This parameter can contain one or more of the DMUS_COMPOSEF_FLAGS enumerated type values.
pChordMap
Chordmap to be used when composing the transition. See Remarks.
ppSectionSeg
Address of a variable to receive a pointer to the created segment.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return one of the following error values:

E_INVALIDARG
E_OUTOFMEMORY
E_POINTER

Remarks

The value in pChordMap can be NULL. If so, an attempt is made to obtain a chordmap from a chordmap track, first from pToSeg, and then from pFromSeg. If neither of these segments contains a chordmap track, the chord occurring at mtTime in pFromSeg is used as the chord in the transition.

The composer looks for a tempo first in pFromSeg and then in pToSeg. If neither of those segments contains a tempo track, the tempo for the transition segment is taken from the style.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicComposer::AutoTransition, Using Transitions


IDirectMusicDownload

The IDirectMusicDownload interface represents a contiguous memory chunk, used for downloading to a DLS synthesizer port.

The IDirectMusicDownload interface and its contained memory chunk are created by the IDirectMusicPortDownload::AllocateBuffer method. The memory can then be accessed by using the single method of this interface.

The interface has the following method:

IDirectMusicDownload GetBuffer

All COM interfaces inherit the IUnknown interface methods. This interface supports the following three methods:

IUnknown | AddRef
 | QueryInterface
 | Release

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicc.h.


IDirectMusicDownload::GetBuffer

The IDirectMusicDownload::GetBuffer method retrieves a pointer to a buffer containing data to be downloaded.

HRESULT GetBuffer(
  void** ppvBuffer,
  DWORD* pdwSize
);

Parameters

ppvBuffer
Address of a variable to receive a pointer to the data buffer.
pdwSize
Address of a variable to receive the size of the returned buffer, in bytes.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return one of the following error values:

DMUS_E_BUFFERNOTAVAILABLE
E_POINTER

Remarks

The method returns DMUS_E_BUFFERNOTAVAILABLE if the buffer has already been downloaded.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicc.h.


IDirectMusicDownloadedInstrument

The IDirectMusicDownloadedInstrument interface is used to identify an instrument that has been downloaded to the synthesizer by using the IDirectMusicPort::DownloadInstrument or IDirectMusicPerformance::DownloadInstrument method. The interface is then used to unload the instrument through a call to IDirectMusicPort::UnloadInstrument. Once the instrument has been unloaded, the interface pointer must be released by the application.

For an example, see Working with Instruments.

The IDirectMusicDownloadedInstrument interface has no methods of its own. Like all COM interfaces, it inherits the IUnknown interface methods. This interface supports the following three methods:

IUnknown | AddRef
 | QueryInterface
 | Release

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicc.h.


IDirectMusicGetLoader

The IDirectMusicGetLoader interface is used by an object parsing a stream when the object needs to load another object referenced by the stream. If a stream supports the loader, it must provide an IDirectMusicGetLoader interface.

For an example of how to obtain the IDirectMusicGetLoader interface from the stream, see IDirectMusicGetLoader::GetLoader.

The IDirectMusicGetLoader interface has the following method:

IDirectMusicGetLoader GetLoader

All COM interfaces inherit the IUnknown interface methods. This interface supports the following three methods:

IUnknown | AddRef
 | QueryInterface
 | Release

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicLoader, DirectMusic Loader, Custom Loading


IDirectMusicGetLoader::GetLoader

The IDirectMusicGetLoader::GetLoader method retrieves a pointer to the loader object that created the stream.

HRESULT GetLoader(
  IDirectMusicLoader ** ppLoader
);

Parameters

ppLoader
Address of a variable to receive the IDirectMusicLoader interface pointer. The reference count of the interface is incremented.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return E_NOINTERFACE.

Remarks

The following code is from a file parser that comes across a reference to an object that needs to be accessed by the loader.

HRESULT myGetReferencedObject(
    DMUS_OBJECTDESC *pDesc,          // Descriptor already prepared.
    IStream *pIStream,               // Stream being parsed.
    IDirectMusicObject **ppIObject)  // Object to be accessed.
{
    IDirectMusicGetLoader *pIGetLoader;
    IDirectMusicLoader *pILoader;
    ppIObject = NULL;
    HRESULT hr = pIStream->QueryInterface(
           IID_IDirectMusicGetLoader,
           (void **) &pIGetLoader );
    if (SUCCEEDED(hr))
    {
        hr = pIGetLoader->GetLoader(&pILoader);
        if (SUCCEEDED(hr))
        {
            hr = pILoader->GetObject(pDesc, IID_DirectMusicLoader,
                  (void**) ppIObject);
            pILoader->Release();
        }
        pIGetLoader->Release();
    }
    return hr;
}

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

Custom Loading


IDirectMusicGraph

The IDirectMusicGraph interface manages the loading and message flow of tools.

Graphs can occur in two places: performances and segments. The graph of tools in a performance is global in nature, in that it processes messages from all segments. A graph in a segment exists only for playback of that segment.

The IDirectMusicGraph interface has the following methods:

Routing | StampPMsg
Tools | GetTool
 | InsertTool
 | RemoveTool

All COM interfaces inherit the IUnknown interface methods. This interface supports the following three methods:

IUnknown | AddRef
 | QueryInterface
 | Release

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.


IDirectMusicGraph::GetTool

The IDirectMusicGraph::GetTool method retrieves a tool by index.

HRESULT GetTool(
  DWORD dwIndex,
  IDirectMusicTool** ppTool
);

Parameters

dwIndex
Zero-based index of the requested tool in the graph.
ppTool
Address of a variable to receive a pointer to the tool.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return one of the following values:

DMUS_E_NOT_FOUND
E_POINTER

Remarks

The application is responsible for releasing the retrieved tool.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.


IDirectMusicGraph::InsertTool

The IDirectMusicGraph::InsertTool method inserts a tool in the graph.

HRESULT InsertTool(
  IDirectMusicTool * pTool,
  DWORD * pdwPChannels,
  DWORD cPChannels,
  LONG lIndex
);

Parameters

pTool
Tool to insert.
pdwPChannels
Array of PChannels on which the tool accepts messages. If the tool accepts messages on all PChannels, pass NULL.
cPChannels
Count of how many PChannels are pointed to by pdwPChannels. Ignored if pdwPChannels is NULL.
lIndex
Position at which to place the tool. This is a zero-based index from either the start or (if it is negative) the end of the current tool list. If lIndex is out of range, the tool will be placed at the very beginning or end of the list. To place a tool at the end of the list, use a number for lIndex that is larger than the number of tools in the current tool list.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return one of the following error values:

DMUS_E_ALREADY_EXISTS
E_OUTOFMEMORY
E_POINTER

Remarks

The reference count of the tool is incremented.

This method calls IDirectMusicTool::Init.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.


IDirectMusicGraph::RemoveTool

The IDirectMusicGraph::RemoveTool method removes a tool from the graph.

HRESULT RemoveTool(
  IDirectMusicTool * pTool
);

Parameters

pTool
Tool to be removed.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return one of the following error values:

DMUS_E_NOT_FOUND
E_POINTER

Remarks

The graph's reference to the tool object is released.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.


IDirectMusicGraph::StampPMsg

The IDirectMusicGraph::StampPMsg method stamps a message with a pointer to the next tool that is to receive it. After processing a message, a tool must call StampPMsg.

HRESULT StampPMsg(
  DMUS_PMSG* pPMSG
);

Parameters

pPMSG
Address of a structure containing the message to stamp. This structure is of a type derived from DMUS_PMSG. For an overview of message types, see Messages.

Return Values

If the method succeeds, the return value is S_OK or DMUS_S_LAST_TOOL. See Remarks.

If it fails, the method may return E_POINTER.

Remarks

The value of pPMSG->pTool (see DMUS_PMSG) on entry equals the current tool. StampPMsg uses this member to determine the current tool in order to find the next in the graph. It will be NULL to find the first tool in the graph.

The value of pPMSG->pGraph equals the graph that contains the tool. This is stamped inside StampPMsg along with the tool itself, and may change during the message's traversal from the segment state to the performance, as there may be multiple tool graphs.

The value of pPMSG->dwType equals the media type of the message, and is also used to find the next tool. The media types supported are those returned by the IDirectMusicTool::GetMediaTypes method.

The value of pPMSG->dwPChannel is used to determine which track the tool must be capable of processing. Tracks are identified by unique numbers when a segment is authored.

This method calls Release on the current pPMSG->pTool, replaces it with the next tool in the graph, and calls AddRef on the new tool.

It also flags the message with the correct delivery type according to what type the next tool returns in its IDirectMusicTool::GetMsgDeliveryType method. This flag determines when the message is delivered to the next tool.

The implementations of this method in the DirectMusicSegmentState and DirectMusicPerformance objects always return S_OK on success. The implementation in DirectMusicGraph returns DMUS_S_LAST_TOOL if there is no tool other than the output tool waiting to receive the message.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

DirectMusic Tools


IDirectMusicInstrument

The IDirectMusicInstrument interface represents an individual instrument from a DLS collection.

The only way to create a DirectMusicInstrument object for downloading an instrument is to first create a DirectMusicCollection object, then call the IDirectMusicCollection::GetInstrument method. GetInstrument creates a DirectMusicInstrument object and returns its IDirectMusicInstrument interface pointer.

To download the instrument, pass its interface pointer to the IDirectMusicPort::DownloadInstrument or IDirectMusicPerformance::DownloadInstrument method. If the method succeeds, it returns a pointer to an IDirectMusicDownloadedInstrument interface, which is used only to unload the instrument.

It is important to note that the methods of IDirectMusicInstrument only operate on an instrument that has not been downloaded. Any instances of the instrument that have been downloaded to a port are not affected by the IDirectMusicInstrument::GetPatch and IDirectMusicInstrument::SetPatch methods.

The interface has the following methods:

IDirectMusicInstrument | GetPatch
 | SetPatch

All COM interfaces inherit the IUnknown interface methods. This interface supports the following three methods:

IUnknown | AddRef
 | QueryInterface
 | Release

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicc.h.


IDirectMusicInstrument::GetPatch

The IDirectMusicInstrument::GetPatch method retrieves the patch number for the instrument. The patch number is an address composed of the MSB and LSB bank selects and the MIDI patch (program change) number. An optional flag bit indicates that the instrument is a drum rather than a melodic instrument.

HRESULT GetPatch(
  DWORD* pdwPatch
);

Parameters

pdwPatch
Address of a variable to receive the patch number.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return E_POINTER.

Remarks

The patch number returned at pdwPatch describes the full patch address, including the MIDI parameters for MSB and LSB bank select. In addition, the high bit is set if the instrument is specifically a drum kit, intended to be played on MIDI channel 10. This is a special tag for DLS Level 1, since DLS Level 1 always plays drums on MIDI channel 10. For more information, see MIDI Channel Messages.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicc.h.


IDirectMusicInstrument::SetPatch

The IDirectMusicInstrument::SetPatch method sets the patch number for the instrument. Although each instrument in a DLS collection has a predefined patch number, the patch number can be reassigned once the IDirectMusicCollection::GetInstrument method has been used to retrieve the instrument from the collection. For more information on DirectMusic patch numbers, see IDirectMusicInstrument::GetPatch.

HRESULT SetPatch(
  DWORD dwPatch
);

Parameters

dwPatch
New patch number to assign to instrument.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return DMUS_E_INVALIDPATCH.

Remarks

The following example gets an instrument from a collection, remaps its MSB bank select to a different bank, then downloads the instrument.

HRESULT myRemappedDownload(
    IDirectMusicCollection *pCollection,
    IDirectMusicPort *pPort,
    IDirectMusicDownloadedInstrument **ppDLInstrument,
    BYTE bMSB,       // Requested MIDI MSB for patch bank select.
    DWORD dwPatch)   // Requested patch.

{
    HRESULT hr;
    IDirectMusicInstrument* pInstrument;
    hr = pCollection->GetInstrument(dwPatch, &pInstrument);
    if (SUCCEEDED(hr))
    {
        dwPatch &= 0xFF00FFFF;  // Clear MSB.
        dwPatch |= bMSB << 16;  // Stick in new MSB value.
        pInstrument->SetPatch(dwPatch);
        hr = pPort->DownloadInstrument(pInstrument,
                ppDLInstrument,
                NULL, 0);       // Download all regions
        pInstrument->Release();
    }
    return hr;
}

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicc.h.


IDirectMusicLoader

The IDirectMusicLoader interface is used for finding, enumerating, caching, and loading objects. For an overview, see DirectMusic Loader.

The methods of the IDirectMusicLoader interface can be organized into the following groups:

Searching | EnumObject
 | ScanDirectory
 | SetSearchDirectory
Caching | CacheObject
 | ClearCache
 | EnableCache
Object management | GetObject
 | ReleaseObject
 | SetObject

All COM interfaces inherit the IUnknown interface methods. This interface supports the following three methods:

IUnknown | AddRef
 | QueryInterface
 | Release

The LPDMUS_LOADER type is defined as a pointer to the IDirectMusicLoader interface.

typedef IDirectMusicLoader __RPC_FAR *LPDMUS_LOADER;

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.


IDirectMusicLoader::CacheObject

The IDirectMusicLoader::CacheObject method tells the loader to keep a reference to the object. This guarantees that the object will not be loaded twice.

HRESULT CacheObject(
  IDirectMusicObject * pObject
);

Parameters

pObject
The IDirectMusicObject interface of the object to cache.

Return Values

If the method succeeds, the return value is S_OK, or S_FALSE if the object is already cached.

If it fails, the method may return one of the following error values:

E_POINTER
DMUS_E_LOADER_OBJECTNOTFOUND

Remarks

If you have an object that will be accessed in multiple places throughout the life of your program, letting the loader cache the object can significantly speed up performance. For an overview, see Caching Objects.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicLoader::EnableCache, IDirectMusicLoader::ClearCache, IDirectMusicLoader::ReleaseObject


IDirectMusicLoader::ClearCache

The IDirectMusicLoader::ClearCache method tells the loader to release all references to a particular type of object.

HRESULT ClearCache(
  REFGUID rguidClass
);

Parameters

rguidClass
Address of (C) or reference to (C++) the identifier of class of objects to clear. Optionally, GUID_DirectMusicAllTypes specifies all types.

Return Values

The method returns S_OK.

Remarks

This method clears all objects that are currently being held, but does not turn off caching. Use the IDirectMusicLoader::EnableCache method to turn off automatic caching.

To clear a single object from the cache, call the IDirectMusicLoader::ReleaseObject method.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicLoader::CacheObject, Caching Objects


IDirectMusicLoader::EnableCache

The IDirectMusicLoader::EnableCache method tells the loader to enable or disable automatic caching of all objects it loads. By default, caching is enabled for all classes.

HRESULT EnableCache(
  REFGUID rguidClass,
  BOOL fEnable
);

Parameters

rguidClass
Address of (C) or reference to (C++) the identifier of the class of objects to cache. Optionally, GUID_DirectMusicAllTypes specifies all types.
fEnable
TRUE to enable caching, FALSE to clear and disable.

Return Values

The method returns S_OK if the cache state is changed, or S_FALSE if the cache is already in the desired state.

Remarks

To clear the cache without disabling caching, call the IDirectMusicLoader::ClearCache method.

The following example disables caching just for segment objects, so they don't stay in memory after the application releases them. Other objects that should be shared, like styles, chordmaps and DLS collections, continue to be cached. Note that the first call to EnableCache would normally be unnecessary, because caching is enabled for all objects by default.

void myPrepareLoader(IDirectMusicLoader *pILoader)

{
    pILoader->EnableCache(GUID_DirectMusicAllTypes, TRUE);
    pILoader->EnableCache(CLSID_DirectMusicSegment, FALSE);
}

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicLoader::CacheObject, IDirectMusicLoader::ClearCache, Caching Objects


IDirectMusicLoader::EnumObject

The IDirectMusicLoader::EnumObject method enumerates all available objects of the requested type. Objects are available if they have been loaded or if IDirectMusicLoader::ScanDirectory has been called on the search directory.

HRESULT EnumObject(
  REFGUID rguidClass,
  DWORD dwIndex,
  LPDMUS_OBJECTDESC pDesc
);

Parameters

rguidClass
Reference to (C++) or address of (C) the identifier for the class of objects to view.
dwIndex
Index into list. Typically, starts with 0 and increments.
pDesc
DMUS_OBJECTDESC structure to be filled with data about the object.

Return Values

If the method succeeds, the return value is S_OK, or S_FALSE if dwIndex is past the end of the list.

Remarks

For an example of the use of this method, see Enumerating Objects.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicLoader::ScanDirectory


IDirectMusicLoader::GetObject

The IDirectMusicLoader::GetObject method retrieves the specified object from a file or resource and returns the desired interface.

HRESULT GetObject(
  LPDMUS_OBJECTDESC pDESC,
  REFIID riid,
  LPVOID FAR * ppv
);

Parameters

pDESC
Address of a DMUS_OBJECTDESC structure describing the object.
riid
Unique identifier of the interface. See the IID defines in Dmusici.h. All the standard interfaces have a defined identifier consisting of "IID_" plus the name of the interface. For example, the identifier of IDirectMusicTrack is IID_IDirectMusicTrack.
ppv
Address of a variable to receive a pointer to the desired interface of the object.

Return Values

If the method succeeds, the return value is S_OK or DMUS_S_PARTIALLOAD.

If it fails, the method may return one of the following error values:

E_FAIL
E_INVALIDARG
E_OUTOFMEMORY
E_POINTER
DMUS_E_LOADER_NOCLASSID
DMUS_E_LOADER_FAILEDOPEN
DMUS_E_LOADER_FAILEDCREATE
DMUS_E_LOADER_FORMATNOTSUPPORTED
REGDB_E_CLASSNOTREG

Remarks

A return value of DMUS_S_PARTIALLOAD may mean that the default instrument collection file, Gm.dls, is not available.

The current version of DirectMusic does not support loading from URLs. If the dwValidData member of the DMUS_OBJECTDESC structure contains DMUS_OBJ_URL, the method returns DMUS_E_LOADER_FORMATNOTSUPPORTED.

The method does not require that all valid members of the DMUS_OBJECTDESC structure match before retrieving an object. It searches in the following order:

  1. DMUS_OBJ_OBJECT
  2. DMUS_OBJ_MEMORY
  3. DMUS_OBJ_FILENAME and DMUS_OBJ_FULLPATH
  4. DMUS_OBJ_NAME and DMUS_OBJ_CATEGORY
  5. DMUS_OBJ_NAME
  6. DMUS_OBJ_FILENAME

In other words, the highest priority goes to a unique GUID, followed by a resource, followed by the full file path name, followed by internal name plus category, followed by internal name, followed by local file name.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicLoader::ReleaseObject, IDirectMusicLoader::ScanDirectory, Loading Objects


IDirectMusicLoader::ReleaseObject

The IDirectMusicLoader::ReleaseObject method releases the loader's reference to the object.

HRESULT ReleaseObject(
  IDirectMusicObject * pObject
);

Parameters

pObject
Object to release.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return one of the following error values:

E_POINTER
DMUS_E_LOADER_OBJECTNOTFOUND

Remarks

ReleaseObject is the reciprocal of IDirectMusicLoader::CacheObject.

Objects can be cached explicitly by using the CacheObject method, or automatically by using the IDirectMusicLoader::EnableCache method.

To tell the loader to flush all objects of a particular type, call the IDirectMusicLoader::ClearCache method.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicLoader::GetObject, Caching Objects


IDirectMusicLoader::ScanDirectory

The IDirectMusicLoader::ScanDirectory method searches a directory on disk for all files of a requested class type and file extension. For each file found, it calls the the IDirectMusicObject::ParseDescriptor method to extract the GUID and name of the object. This information is stored in an internal database. Once a directory has been scanned, all files of the requested type become available for enumeration through the IDirectMusicLoader::EnumObject method; in addition, an object can be retrieved by using IDirectMusicLoader::GetObject even without a filename.

HRESULT ScanDirectory(
  REFGUID rguidClass,
  WCHAR* pwzFileExtension,
  WCHAR* pwzScanFileName
);

Parameters

rguidClass
Address of (C) or reference to (C++) the identifier of the class of objects this pertains to.
pwzFileExtension
File extension for type of file to look for—for example, L"sty" for style files. Use L"*" to look in files with any or no extension.
pwzScanFileName
Optional storage file to store and retrieve cached file information. This file is created by the first call to ScanDirectory and used by subsequent calls. Pass NULL if a cache file is not wanted.

Return Values

If the method succeeds, the return value is S_OK, or S_FALSE if no files were found.

If it fails, the method may return one of the following error values:

DMUS_E_NOT_FOUND
E_FAIL
E_OUTOFMEMORY
E_POINTER
REGDB_E_CLASSNOTREG

Remarks

The IDirectMusicLoader::SetSearchDirectory method must be called first to set the location to search.

Optionally, the scanned information can be stored in a cache file, defined by pwzScanFileName. Once it has been so stored, subsequent calls to ScanDirectory are much quicker, because only files that have changed are scanned (the cache file stores the file size and date for each object, so it can identify if a file has changed).

If the file type has more than one extension, call ScanDirectory once for each file extension.

GUID_DirectMusicAllTypes is not a valid value for rguidClass.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

Scanning a Directory for Objects


IDirectMusicLoader::SetObject

The IDirectMusicLoader::SetObject method tells the loader where to find an object when it is later referenced by another object being loaded. For an overview, see Setting Objects.

HRESULT SetObject(
  LPDMUS_OBJECTDESC pDESC
);

Parameters

pDESC
Address of a DMUS_OBJECTDESC structure describing the object.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return one of the following error values:

E_FAIL
E_INVALIDARG
E_OUTOFMEMORY
E_POINTER
DMUS_E_LOADER_NOCLASSID
DMUS_E_LOADER_FAILEDOPEN
DMUS_E_LOADER_FAILEDCREATE
DMUS_E_LOADER_FORMATNOTSUPPORTED
REGDB_E_CLASSNOTREG

Remarks

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicLoader::GetObject


IDirectMusicLoader::SetSearchDirectory

The IDirectMusicLoader::SetSearchDirectory method sets a search path for finding object files. The search path can be set for one object file type or for all files.

HRESULT SetSearchDirectory(
  REFGUID rguidClass,
  WCHAR* pwszPath,
  BOOL fClear
);

Parameters

rguidClass
Address of (C) or reference to (C++) the identifier of the class of objects the call pertains to. Optionally, GUID_DirectMusicAllTypes specifies all objects.
pwszPath
File path for directory. Must be a valid directory and must be less than MAX_PATH in length.
fClear
If TRUE, clears all information about objects before setting the directory. This helps avoid accessing objects from the previous directory that may have the same name. However, objects are not removed from the cache.

Return Values

If the method succeeds, the return value is S_OK, or S_FALSE if the search directory is already set to pwszPath.

If it fails, the method may return one of the following error values:

E_OUTOFMEMORY
E_POINTER
DMUS_E_LOADER_BADPATH

Remarks

Once a search path is set, the loader does not need a full path every time it is given an object to load by file name. This enables objects that reference other objects to find them by file name without knowing the full path.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicLoader::ScanDirectory, Setting the Loader's Search Directory


IDirectMusicObject

All DirectMusic objects that can be loaded from a file support the IDirectMusicObject interface in order to work with the DirectMusic loader. In addition to providing a standard interface with which the loader can communicate, this interface provides a generic mechanism that allows an application to query an object for information about it, including its name, GUID, file path, and version.

The IDirectMusicObject interface must be obtained by calling another interface's QueryInterface method. It cannot be obtained by using CoCreateInstance.

The IDirectMusicObject interface has the following methods:

Descriptor | GetDescriptor
 | ParseDescriptor
 | SetDescriptor

All COM interfaces inherit the IUnknown interface methods. This interface supports the following three methods:

IUnknown | AddRef
 | QueryInterface
 | Release

The LPDMUS_OBJECT type is defined as a pointer to the IDirectMusicObject interface.

typedef IDirectMusicObject __RPC_FAR *LPDMUS_OBJECT;

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

DirectMusic Loader, Custom Loading


IDirectMusicObject::GetDescriptor

The IDirectMusicObject::GetDescriptor method retrieves the object's internal description.

The method takes a DMUS_OBJECTDESC structure and fills in everything the object knows about itself.

HRESULT GetDescriptor(
  LPDMUS_OBJECTDESC pDesc
);

Parameters

pDesc
Address of a DMUS_OBJECTDESC structure to be filled with data about the object. Depending on the implementation of the object and how it was loaded from a file, some or all of the standard parameters will be filled by GetDescriptor. Check the flags in the dwValidData member to know which other members are valid.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return E_POINTER.

Remarks

For an example, see Getting Object Descriptors.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicObject::SetDescriptor


IDirectMusicObject::ParseDescriptor

Given a file stream, the IDirectMusicObject::ParseDescriptor method scans the file for data which it can store in the DMUS_OBJECTDESC structure. All members that are supplied are marked with the appropriate flags in dwValidData.

This method is primarily used by the loader when scanning a directory for objects, and typically will not be used directly by an application. However, if an application implements an object type in DirectMusic, it should support this method.

HRESULT ParseDescriptor(
  LPSTREAM pStream,
  LPDMUS_OBJECTDESC pDesc
);

Parameters

pStream
Stream source for file.
pDesc
Address of a DMUS_OBJECTDESC structure to receive data about the file.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return one of the following error values:

DMUS_E_CHUNKNOTFOUND
DMUS_E_INVALID_BAND
DMUS_E_INVALIDFILE
DMUS_E_NOTADLSCOL
E_POINTER

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicObject::SetDescriptor


IDirectMusicObject::SetDescriptor

The IDirectMusicObject::SetDescriptor method sets some or all members of the object's internal description.

HRESULT SetDescriptor(
  LPDMUS_OBJECTDESC pDesc
);

Parameters

pDesc
Address of a DMUS_OBJECTDESC structure to receive data about the object. Data is copied to all members that are enabled in the dwValidData member

Return Values

If the method succeeds, the return value is S_OK or S_FALSE (see Remarks).

If it fails, the method may return one of the following error values:

E_INVALIDARG
E_POINTER

Remarks

Members that are not copied keep their previous values. For example, an object might already have its name and GUID stored internally. A call to its SetDescriptor method with a new name and file path (and DMUS_OBJ_NAME | DMUS_OBJ_FILENAME in the dwValidData member) would replace the name, supply a file name, and leave the GUID alone.

This method is primarily used by the loader when creating an object. However, it can be used by an application to rename an object.

If the object is unable to set one or more members, it sets the members that it does support, clears the flags in dwValidData that it does not support, and returns S_FALSE.

If nothing else, an object should support DMUS_OBJ_NAME and DMUS_OBJ_OBJECT.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicObject::ParseDescriptor, IDirectMusicObject::GetDescriptor


IDirectMusicPerformance

The IDirectMusicPerformance interface is the overall manager of music playback. It is used for adding and removing ports, mapping performance channels to ports, playing segments, dispatching messages and routing them through tools, requesting and receiving event notification, and setting and retrieving music parameters. It also has several methods for getting information about timing and for converting time and music values from one system to another.

If an application would like to have two complete sets of music playing at the same time, it can do so by creating more than one performance. Separate performances obey separate tempo maps and so play completely asynchronously, whereas all segments within one performance play in lock step.

The methods of the IDirectMusicPerformance interface can be organized into the following groups:

Channels | AssignPChannel
 | AssignPChannelBlock
 | PChannelInfo
Instruments | DownloadInstrument
Messages | AllocPMsg
 | FreePMsg
 | SendPMsg
MIDI conversion | MIDIToMusic
 | MusicToMIDI
Notification | AddNotificationType
 | GetNotificationPMsg
 | RemoveNotificationType
 | SetNotificationHandle
Parameters | GetGlobalParam
 | GetParam
 | SetGlobalParam
 | SetParam
Ports | AddPort
 | RemovePort
Segments | GetSegmentState
 | IsPlaying
 | PlaySegment
 | Stop
Timing | AdjustTime
 | GetBumperLength
 | GetLatencyTime
 | GetPrepareTime
 | GetQueueTime
 | GetResolvedTime
 | GetTime
 | MusicToReferenceTime
 | ReferenceToMusicTime
 | RhythmToTime
 | SetBumperLength
 | SetPrepareTime
 | TimeToRhythm
Tools | GetGraph
 | SetGraph
Miscellaneous | CloseDown
 | Init
 | Invalidate

All COM interfaces inherit the IUnknown interface methods. This interface supports the following methods:

IUnknown | AddRef
 | QueryInterface
 | Release

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.


IDirectMusicPerformance::AddNotificationType

The IDirectMusicPerformance::AddNotificationType method adds a notification type to the performance. All segments and tracks are automatically updated with the new notification by calling their AddNotificationType methods.

HRESULT AddNotificationType(
  REFGUID rguidNotificationType
);

Parameters

rguidNotificationType
Reference to (C++) or address of (C) the identifier of the notification type to add. For the defined types, see DMUS_NOTIFICATION_PMSG. Applications can also define their own types for custom tracks.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return one of the following error values:

E_OUTOFMEMORY
E_POINTER

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicPerformance::RemoveNotificationType, IDirectMusicSegment::AddNotificationType, IDirectMusicTrack::AddNotificationType, Notification and Event Handling


IDirectMusicPerformance::AddPort

The IDirectMusicPerformance::AddPort method assigns a port to the performance.

HRESULT AddPort(
  IDirectMusicPort* pPort
);

Parameters

pPort
Port to add. If NULL, the default port is added. See Remarks.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return one of the following error values:

DMUS_E_NOT_INIT
DMUS_E_CANNOT_OPEN_PORT
E_OUTOFMEMORY
E_POINTER

Remarks

If you wish to pass NULL to this method, you must first pass NULL to IDirectMusicPerformance::Init.

When the default port is specified by passing NULL in pPort, it is assigned one channel group, and if no PChannels have been set up for any other port, PChannels 0-15 are assigned to MIDI channels 0-15.

If pPort is not NULL, the port must be activated by a call to IDirectMusicPort::Activate, and a block of channels must be assigned by a call to IDirectMusicPerformance::AssignPChannelBlock.

This method creates a reference to IDirectMusicPort that is released by IDirectMusicPerformance::RemovePort or IDirectMusicPerformance::CloseDown.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicPerformance::RemovePort, Default Port


IDirectMusicPerformance::AdjustTime

The IDirectMusicPerformance::AdjustTime method adjusts the internal performance time forward or backward. This is mostly used to compensate for drift when synchronizing to another source.

HRESULT AdjustTime(
  REFERENCE_TIME rtAmount
);

Parameters

rtAmount
The amount of time to add or subtract. This may be a number from –10,000,000 to 10,000,000 (–1 second to +1 second).

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return E_INVALIDARG.

Remarks

The adjusted time is used internally by DirectMusic. It is not reflected in the time retrieved by the IDirectMusicPerformance::GetTime method.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicPerformance::GetTime, Timing


IDirectMusicPerformance::AllocPMsg

The IDirectMusicPerformance::AllocPMsg method allocates a performance message.

HRESULT AllocPMsg(
  ULONG cb,
  DMUS_PMSG** ppPMSG
);

Parameters

cb
Size of the message structure. For the various types, see Messages.
ppPMSG
Address of a variable to receive the pointer to the allocated message structure.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return one of the following error values:

E_INVALIDARG
E_OUTOFMEMORY
E_POINTER

Remarks

The memory returned is not initialized to any particular state, with the exception of the pTool member of the DMUS_PMSG structure, which is initialized to zero.

Once the message is sent by IDirectMusicPerformance::SendPMsg, the application no longer owns the memory and is not responsible for freeing the message. However, a tool can free a message within its IDirectMusicTool::Flush or IDirectMusicTool::ProcessPMsg method. Applications are also responsible for freeing notification messages.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicPerformance::FreePMsg, IDirectMusicPerformance::SendPMsg, DirectMusic Messages


IDirectMusicPerformance::AssignPChannel

The IDirectMusicPerformance::AssignPChannel method assigns a single performance channel (PChannel) to the performance and maps it to a port, group, and MIDI channel.

HRESULT AssignPChannel(
  DWORD dwPChannel,
  IDirectMusicPort* pPort,
  DWORD dwGroup,
  DWORD dwMChannel
);

Parameters

dwPChannel
PChannel to assign.
pPort
Port to which the PChannel is assigned.
dwGroup
Channel group on the port.
dwMChannel
Channel in the group. Must be in the range 0-15.

Return Values

If the method succeeds, the return value is S_OK or S_FALSE (see Remarks).

If it fails, the method may return one of the following error values:

E_INVALIDARG
E_POINTER

Remarks

The method returns S_FALSE if dwGroup is out of the range of the port. The channel has been assigned, but the port cannot play this group.

The method returns E_INVALIDARG if dwMChannel is out of range or the port hasn't been added to the performance through a call to the IDirectMusicPerformance::AddPort method.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicPerformance::AssignPChannelBlock, IDirectMusicPerformance::PChannelInfo, Channels


IDirectMusicPerformance::AssignPChannelBlock

The IDirectMusicPerformance::AssignPChannelBlock method assigns a block of 16 performance channels (PChannels) to the performance and maps them to a port and channel group. This method must be called when a port has been added to a performance, except when the default port has been added by passing NULL to IDirectMusicPerformance::AddPort.

HRESULT AssignPChannelBlock(
  DWORD dwBlockNum,
  IDirectMusicPort* pPort,
  DWORD dwGroup
);

Parameters

dwBlockNum
Block number, where 0 represents channels 0-15, 1 represents channels 16-31, and so on.
pPort
Port to which the channels are assigned.
dwGroup
Channel group on the port. Must be 1 or greater.

Return Values

If the method succeeds, the return value is S_OK or S_FALSE (see Remarks).

If it fails, the method may return one of the following error values:

E_INVALIDARG
E_POINTER

Remarks

The method returns S_FALSE if dwGroup is out of the range of the port. The channels have been assigned, but the port cannot play this group.

The method returns E_INVALIDARG if the port hasn't been added to the performance through a call to the IDirectMusicPerformance::AddPort method.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicPerformance::AssignPChannel, IDirectMusicPerformance::PChannelInfo, Channels


IDirectMusicPerformance::CloseDown

The IDirectMusicPerformance::CloseDown method closes down the performance object. An application that created the performance object and called IDirectMusicPerformance::Init on it must call CloseDown before the performance is released.

HRESULT CloseDown();

Parameters

None.

Return Values

The method returns S_OK.

Remarks

Failure to call CloseDown may cause memory leaks or crashes.

CloseDown handles the release of the IDirectMusic interface in the case where the application passed NULL, or a pointer to NULL, to IDirectMusicPerformance::Init, causing a DirectMusic object to be created by that call. In other cases, where the application explicitly created the DirectMusic object and passed the pointer to Init, the application is responsible for releasing the IDirectMusic interface.

CloseDown also releases any downloaded instruments that have not been unloaded.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicPerformance::Init


IDirectMusicPerformance::DownloadInstrument

The IDirectMusicPerformance::DownloadInstrument method downloads DLS data for an instrument to a port.

HRESULT DownloadInstrument(
  IDirectMusicInstrument* pInst,
  DWORD dwPChannel,
  IDirectMusicDownloadedInstrument** ppDownInst,
  DMUS_NOTERANGE* pNoteRanges,
  DWORD dwNumNoteRanges,
  IDirectMusicPort** ppPort,
  DWORD* pdwGroup,
  DWORD* pdwMChannel
);

Parameters

pInst
Instrument to download.
dwPChannel
PChannel to which the instrument is assigned.
ppDownInst
Address of a variable to receive a pointer to the downloaded instrument.
pNoteRanges
Array of DMUS_NOTERANGE structures. Each entry in the array specifies a contiguous range of MIDI note messages to which the instrument must respond. An instrument region will be downloaded only if at least one note in that region is specified in the DMUS_NOTERANGE structures.
dwNumNoteRanges
Number of DMUS_NOTERANGE structures in the array pointed to by pNoteRanges. If this value is set to 0, the pNoteRanges parameter is ignored and all regions and wave data for the instrument are downloaded.
ppPort
Address of a variable to receive the port to which the instrument was downloaded.
pdwGroup
Address of a variable to receive the group to which the instrument was assigned.
pdwMChannel
Address of a variable to receive the MIDI channel to which the instrument was assigned.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return one of the following error values:

E_INVALIDARG
E_POINTER

Remarks

Most applications will not need to use this method, as instrument downloading is normally handled by bands. See Downloading Bands.

The method will return E_INVALIDARG if the PChannel isn't assigned to a port.

To prevent loss of resources, the instrument should be unloaded by using the IDirectMusicPort::UnloadInstrument method when it is no longer needed.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicPort::DownloadInstrument, IDirectMusicPort::UnloadInstrument, Working with Instruments


IDirectMusicPerformance::FreePMsg

The IDirectMusicPerformance::FreePMsg method frees a message.

HRESULT FreePMsg(
  DMUS_PMSG* pPMSG
);

Parameters

pPMSG
Address of a message to free. This message must have been allocated using the IDirectMusicPerformance::AllocPMsg method.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return one of the following error values:

DMUS_E_CANNOT_FREE
E_POINTER

Remarks

Most messages are released automatically by the performance once they have been processed, and IDirectMusicPerformance::FreePMsg must not be called on a message that has been sent by using IDirectMusicPerformance::SendPMsg. However, IDirectMusicPerformance::FreePMsg can be used within IDirectMusicTool::ProcessPMsg or IDirectMusicTool::Flush to free a message that is no longer needed. It must also be used to free notification messages.

The method returns DMUS_E_CANNOT_FREE if pPMSG is not a message allocated by AllocPMsg, if it is currently in the performance queue because IDirectMusicPerformance::SendPMsg was called on it, or if it has already been freed.

If there is a value in the pTool, pGraph, or punkUser members (see DMUS_PMSG), each referenced object is released.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicPerformance::AllocPMsg, DirectMusic Messages


IDirectMusicPerformance::GetBumperLength

The IDirectMusicPerformance::GetBumperLength method retrieves the amount of time to buffer ahead of the port's latency for MIDI messages to be sent to the port for rendering. For an overview of this topic, see Timing.

HRESULT GetBumperLength(
  DWORD* pdwMilliSeconds
);

Parameters

pdwMilliSeconds
The amount of preplay time.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return E_POINTER.

Remarks

The default value is 50 milliseconds.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicPerformance::SetBumperLength


IDirectMusicPerformance::GetGlobalParam

The IDirectMusicPerformance::GetGlobalParam method retrieves global values from the performance.

HRESULT GetGlobalParam(
  REFGUID rguidType,
  void* pParam,
  DWORD dwSize
);

Parameters

rguidType
Reference to (C++) or address of (C) the identifier of the type of data.
pParam
Allocated memory to receive a copy of the data. This must be the correct size, which is constant for each type of data, and was also passed into the IDirectMusicPerformance::SetGlobalParam method.
dwSize
Size of the data. This is constant for each rguidType.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return one of the following error values:

E_INVALIDARG
E_POINTER

Remarks

If rguidType isn't in the list of global data being handled by this performance, the method returns E_INVALIDARG. Make sure to call SetGlobalParam first.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicPerformance::SetGlobalParam, IDirectMusicPerformance::GetParam, Music Parameters


IDirectMusicPerformance::GetGraph

The IDirectMusicPerformance::GetGraph method retrieves the performance's tool graph.

HRESULT GetGraph(
  IDirectMusicGraph** ppGraph
);

Parameters

ppGraph
Address of a variable to receive a pointer to the tool graph.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return one of the following error values:

DMUS_E_NOT_FOUND
E_POINTER

Remarks

The reference count of the graph is incremented.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicPerformance::SetGraph, IDirectMusicSegment::GetGraph, IDirectMusicPerformance::SendPMsg


IDirectMusicPerformance::GetLatencyTime

The IDirectMusicPerformance::GetLatencyTime method retrieves the current latency time. If "now" is the time being heard from the speakers, "latency time" is "now" plus the time required to queue and render messages into the IDirectMusicPort. For an overview of this topic, see Timing.

HRESULT GetLatencyTime(
  REFERENCE_TIME * prtTime
);

Parameters

prtTime
Address of a variable to receive the current latency time.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return one of the following error values:

E_POINTER
DMUS_E_NO_MASTER_CLOCK

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.


IDirectMusicPerformance::GetNotificationPMsg

The IDirectMusicPerformance::GetNotificationPMsg method is called by the application to retrieve pending notification messages.

HRESULT GetNotificationPMsg(
  DMUS_NOTIFICATION_PMSG** ppNotificationPMsg
);

Parameters

ppNotificationPMsg
Address of a variable to receive a pointer to a DMUS_NOTIFICATION_PMSG structure. The application retrieving this message is responsible for calling IDirectMusicPerformance::FreePMsg on it.

Return Values

If the method succeeds, the return value is S_OK or, if there are no more notification events to return, S_FALSE.

If it fails, the method may return E_POINTER.

Remarks

For an example, see Handling Notifications in the tutorial on Using Compositions.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

Notification and Event Handling


IDirectMusicPerformance::GetParam

The IDirectMusicPerformance::GetParam method retrieves data from a track inside the control segment.

HRESULT GetParam(
  REFGUID rguidType,
  DWORD dwGroupBits,
  DWORD dwIndex,
  MUSIC_TIME mtTime,
  MUSIC_TIME* pmtNext,
  void* pParam
);

Parameters

rguidType
Address of (C) or reference to (C++) the identifier of the type of data to obtain. See Track Parameter Types.
dwGroupBits
Group the desired track is in (see Remarks). Set this value to 0xFFFFFFFF for all groups.
dwIndex
Index of the track in the group from which to obtain the data.
mtTime
The time from which to obtain the data, in performance time.
pmtNext
Address of a variable to receive the time (relative to mtTime) until which the data is valid. If this returns a value of 0, it means either that the data will always be valid, or that it is unknown when it will become invalid. If this information is not needed, pmtNext can be set to NULL. See Remarks.
pParam
Address of an allocated structure in which the data is to be returned. The structure must be of the appropriate kind and size for the data type identified by rguidType.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return one of the following error values:

DMUS_E_NO_MASTER_CLOCK
DMUS_E_GET_UNSUPPORTED
DMUS_E_TRACK_NOT_FOUND
E_POINTER

Remarks

Normally the primary segment is the control segment. However, a secondary segment can be designated as a control segment when it is played. For more information on control segments, see Segments and DMUS_SEGF_FLAGS.

The data returned in *pParam can become invalid before the time returned in *pmtNext if another control segment is cued.

Each track belongs to one or more groups, each group being represented by a bit in dwGroupBits. For more information, see IDirectMusicSegment::InsertTrack and Identifying the Track.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicPerformance::SetParam, IDirectMusicSegment::GetParam, IDirectMusicTrack::GetParam, IDirectMusicPerformance::SetGlobalParam, IDirectMusicPerformance::GetTime, Music Parameters


IDirectMusicPerformance::GetPrepareTime

The IDirectMusicPerformance::GetPrepareTime method retrieves the amount of time ahead that IDirectMusicTrack::Play is called before the messages should actually be heard through the speaker. This interval allows sufficient time for the message to be processed by tools.

HRESULT GetPrepareTime(
  DWORD* pdwMilliSeconds
);

Parameters

pdwMilliSeconds
Address of a variable to receive the amount of prepare time.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return E_POINTER.

Remarks

The default value is 1000 milliseconds.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicPerformance::SetPrepareTime, Timing


IDirectMusicPerformance::GetQueueTime

The IDirectMusicPerformance::GetQueueTime method retrieves the current flush time, which is the earliest time in the queue at which messages can be flushed. Messages that have timestamps earlier than this time have already been sent to the port and cannot be invalidated.

HRESULT GetQueueTime(
  REFERENCE_TIME * prtTime
);

Parameters

prtTime
Address of a variable to receive the current flush time.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return one of the following error values:

E_POINTER
DMUS_E_NO_MASTER_CLOCK

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

Latency and Bumper Time


IDirectMusicPerformance::GetResolvedTime

The IDirectMusicPerformance::GetResolvedTime method resolves a given time to a given boundary.

HRESULT GetResolvedTime(
  REFERENCE_TIME rtTime,
  REFERENCE_TIME* prtResolved,
  DWORD dwTimeResolveFlags
);

Parameters

rtTime
Time to resolve.
prtResolved
Address of a variable to receive the resolved time.
dwTimeResolveFlags
One or more DMUS_TIME_RESOLVE_FLAGS describing the resolution desired.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return E_POINTER.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

Timing


IDirectMusicPerformance::GetSegmentState

The IDirectMusicPerformance::GetSegmentState method retrieves the currently playing primary segment state, or the primary segment state that is playing at a given time.

HRESULT GetSegmentState(
  IDirectMusicSegmentState ** ppSegmentState,
  MUSIC_TIME mtTime
);

Parameters

ppSegmentState
Address of a variable to receive a pointer to the segment state. The caller is responsible for calling Release on this pointer.
mtTime
Time for which the segment state is to be retrieved; that is, the segment state that will be playing at this time is to be returned. To get the currently playing segment state, pass the time retrieved by using the IDirectMusicPerformance::GetTime method.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return one of the following error values:

DMUS_E_NOT_FOUND
E_POINTER

Remarks

This function is intended for routines that need to access the currently playing segment state, for example to obtain the chord or command track. "Currently playing" in this context means that it is being called into to perform messages. Because of latency, the currently playing segment state is not necessarily the one actually being heard.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.


IDirectMusicPerformance::GetTime

The IDirectMusicPerformance::GetTime method retrieves the current time of the performance.

HRESULT GetTime(
  REFERENCE_TIME* prtNow,
  MUSIC_TIME* pmtNow
);

Parameters

prtNow
Address of a variable to receive the current time in REFERENCE_TIME format. Can be NULL.
pmtNow
Address of a variable to receive the current time in MUSIC_TIME format. Can be NULL.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return one of the following error values:

DMUS_E_NO_MASTER_CLOCK
E_POINTER

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

Timing


IDirectMusicPerformance::Init

The IDirectMusicPerformance::Init method associates the performance with a DirectMusic object and a DirectSound object.

HRESULT Init(
  IDirectMusic** ppDirectMusic,
  LPDIRECTSOUND pDirectSound,
  HWND hWnd
);

Parameters

ppDirectMusic
Address of a variable containing the IDirectMusic interface pointer to be assigned to the performance, if one already exists. The reference count of the interface is incremented. Ports passed to the IDirectMusicPerformance::AddPort method must be created from this DirectMusic object.

If the variable contains NULL, a DirectMusic object is created and the interface pointer returned.

If ppDirectMusic is NULL, a DirectMusic object is created and used internally by the performance.

See Remarks.

pDirectSound
IDirectSound interface to use by default for wave output. If this value is NULL, DirectMusic will create a DirectSound object. Note, however, that there should only be one DirectSound object per process. If your application uses DirectSound separately, it should pass in that interface here, or to IDirectMusic::SetDirectSound if the application creates the DirectMusic object explicitly.
hWnd
Window handle to be used for the creation of DirectSound. This parameter can be NULL, in which case the foreground window will be used. See Remarks.

This parameter is ignored if pDirectSound is not NULL, in which case the application is responsible for setting the window handle in a call to IDirectSound::SetCooperativeLevel.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return one of the following error values:

DMUS_E_ALREADY_INITED
E_OUTOFMEMORY
E_POINTER

Remarks

This method should be called only once, and must be called before the performance can play.

There are three different ways of associating a DirectMusic object with the performance:

  1. The application creates its own DirectMusic object and gives it to the performance by passing the address of the IDirectMusic pointer in ppDirectMusic. In this case, the pDirectSound and hWnd parameters are ignored, because the application is responsible for calling IDirectMusic::SetDirectSound.
  2. The application wants the performance to do the work of creating the DirectMusic object, and wants a pointer to that object. In this case, *ppDirectMusic is NULL on entry and contains the IDirectMusic pointer on exit.
  3. The application has no use for a DirectMusic object pointer, and just wants the performance to initialize itself. In this case, ppDirectMusic is NULL.

The performance must be terminated by using the IDirectMusicPerformance::CloseDown method before being released.

You can pass NULL in the hWnd parameter in order to pass the current foreground window handle to DirectSound. However, it is not wise to assume that the application window will be in the foreground during initialization. In general, the top-level application window handle should be passed to DirectMusic, DirectSound, and DirectDraw. See the Remarks for IDirectSound::SetCooperativeLevel.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

Creating the Performance, Integrating DirectMusic and DirectSound


IDirectMusicPerformance::Invalidate

The IDirectMusicPerformance::Invalidate method flushes all queued messages from the supplied time forward, and causes all tracks of all segments to resend their data from the given time forward.

HRESULT Invalidate(
  MUSIC_TIME mtTime,
  DWORD dwFlags
);

Parameters

mtTime
The time from which to invalidate, adjusted by dwFlags. Setting this value to 0 causes immediate invalidation.
dwFlags
Adjusts mtTime to align to measures, beats, or grids. This value can be 0 or one of the following members of the DMUS_SEGF_FLAGS enumeration:

DMUS_SEGF_MEASURE
DMUS_SEGF_BEAT
DMUS_SEGF_GRID

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return DMUS_E_NO_MASTER_CLOCK.

Remarks

If mtTime is so long ago that it is impossible to invalidate that time, the earliest possible time will be used.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

Prepare Time, Segment Timing


IDirectMusicPerformance::IsPlaying

The IDirectMusicPerformance::IsPlaying method determines whether a particular segment or segment state is currently playing at the speakers.

HRESULT IsPlaying(
  IDirectMusicSegment* pSegment,
  IDirectMusicSegmentState* pSegState
);

Parameters

pSegment
The segment to check. If NULL, check only pSegState.
pSegState
The segment state to check. If NULL, check only pSegment.

Return Values

If the method succeeds and either the segment or segment state is playing, the return value is S_OK. If neither is playing, the return value is S_FALSE.

If it fails, the method may return one of the following error values:

E_POINTER
DMUS_E_NO_MASTER_CLOCK

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.


IDirectMusicPerformance::MIDIToMusic

The IDirectMusicPerformance::MIDIToMusic method converts a MIDI note value to a DirectMusic music value, using a supplied chord, subchord level, and play mode.

HRESULT MIDIToMusic(
  BYTE bMIDIValue,
  DMUS_CHORD_KEY* pChord,
  BYTE bPlayMode,
  BYTE bChordLevel,
  WORD *pwMusicValue
);

Parameters

bMIDIValue
MIDI note value to convert, in the range 0 to 127.
pChord
DMUS_CHORD_KEY structure containing information about the chord and key structure to be used in translating the note. This includes the underlying scale. For example, if the chord is a CM7, the note is interpreted against the chord positions for root note C, chord intervals of a major 7. The structure carries up to eight parallel subchords, with chord intervals, root, scale, and inversion flags for each. It also carries the overall key root.
bPlayMode
Play mode determining how the music value is derived from the chord. For a list of values, see DMUS_PLAYMODE_FLAGS.
bChordLevel
Subchord level, defining which subchords can be used. See DMUS_SUBCHORD.
pwMusicValue
Address of a variable to receive the music value. For information on this value, see DMUS_NOTE_PMSG.

Return Values

If the method succeeds, the return value is one of the following. See Remarks.

S_OK
DMUS_S_DOWN_OCTAVE
DMUS_S_UP_OCTAVE

If it fails, the method may return one of the following error values:

DMUS_E_CANNOT_CONVERT
E_INVALIDARG

Remarks

If the method fails, *pwMusicValue is not changed.

If the return value is DMUS_S_UP_OCTAVE or DMUS_DOWN_OCTAVE, the note conversion generated a note value that is less than 0 or greater than 127, so it has been bumped up or down one or more octaves to be in the proper MIDI range of 0 through 127. This may occur when using play modes DMUS_PLAYMODE_FIXEDTOCHORD and DMUS_PLAYMODE_FIXEDTOKEY, both of which return MIDI values in *pwMusicValue.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicPerformance::MusicToMIDI, Music Values and MIDI Notes


IDirectMusicPerformance::MusicToMIDI

The IDirectMusicPerformance::MusicToMIDI method converts a DirectMusic music value to a MIDI note value.

HRESULT MusicToMIDI(
  WORD wMusicValue,
  DMUS_CHORD_KEY* pChord,
  BYTE bPlayMode,
  BYTE bChordLevel,
  BYTE *pbMIDIValue
);

Parameters

wMusicValue
Music value to convert. For information on music values, see DMUS_NOTE_PMSG.
pChord
DMUS_CHORD_KEY structure containing information about the chord and key structure to be used in translating the note. This includes the underlying scale. For example, if the chord is a CM7, the note is interpreted against the chord positions for root note C, chord intervals of a major 7. The structure carries up to eight parallel subchords, with chord intervals, root, scale, and inversion flags for each. It also carries the overall key root.
bPlayMode
Play mode determining how the music value is related to the chord. For a list of values, see DMUS_PLAYMODE_FLAGS.
bChordLevel
Subchord level, defining which subchords can be used. See DMUS_SUBCHORD.
pbMIDIValue
Address of a variable to receive the MIDI value, in the range 0 to 127.

Return Values

If the method succeeds, the return value is one of the following. See Remarks.

S_OK
DMUS_S_OVER_CHORD
DMUS_S_DOWN_OCTAVE
DMUS_S_UP_OCTAVE

If it fails, the method may return one of the following error values:

DMUS_E_CANNOT_CONVERT
E_INVALIDARG

Remarks

If the method fails or returns DMUS_S_OVER_CHORD, *pwMIDIValue is not changed.

The method returns DMUS_S_OVER_CHORD if no note has been calculated because the music value has the note at a position higher than the top note of the chord. This applies only to DMUS_PLAYMODE_NORMALCHORD play mode. The caller should not do anything with the note, which is not meant to be played against this chord.

If the return value is DMUS_S_UP_OCTAVE or DMUS_DOWN_OCTAVE, the note conversion generated a note value that is less than 0 or greater than 127, so it has been bumped up or down one or more octaves to be in the proper MIDI range of 0 through 127. This may occur when using any play mode except DMUS_PLAYMODE_FIXED.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicPerformance::MIDIToMusic, Music Values and MIDI Notes


IDirectMusicPerformance::MusicToReferenceTime

The IDirectMusicPerformance::MusicToReferenceTime method converts time in MUSIC_TIME format to time in REFERENCE_TIME format.

HRESULT MusicToReferenceTime(
  MUSIC_TIME mtTime,
  REFERENCE_TIME* prtTime
);

Parameters

mtTime
The time in MUSIC_TIME format to convert.
prtTime
Address of a variable to receive the converted time in REFERENCE_TIME format.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return one of the following error values:

E_POINTER
DMUS_E_NO_MASTER_CLOCK

Remarks

Because reference time has a greater precision than music time, a time that has been converted from reference time to music time, and then back again, will likely not have its original value.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicPerformance::ReferenceToMusicTime, Reference Time vs. Music Time


IDirectMusicPerformance::PChannelInfo

The IDirectMusicPerformance::PChannelInfo method retrieves the port, group, and MIDI channel for a given performance channel (PChannel).

HRESULT PChannelInfo(
  DWORD dwPChannel,
  IDirectMusicPort** ppPort,
  DWORD* pdwGroup,
  DWORD* pdwMChannel
);

Parameters

dwPChannel
The PChannel for which information is wanted.
ppPort
Address of a variable to receive an IDirectMusicPort pointer. This value can be NULL if the pointer is not wanted. If a non-NULL pointer is returned, the reference count is incremented, and it is the responsibility of the application to call Release on the pointer. See also Remarks.
pdwGroup
Address of a variable to receive the group on the port. Can be NULL if this value is not wanted.
pdwMChannel
Address of a variable to receive the MIDI channel on the group. Can be NULL if this value is not wanted.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return one of the following error values:

E_INVALIDARG
E_POINTER

Remarks

A NULL pointer is returned in *ppPort if the port has been removed by a call to IDirectMusicPerformance::RemovePort, but the method succeeds.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicPerformance::AssignPChannel, IDirectMusicPerformance::AssignPChannelBlock


IDirectMusicPerformance::PlaySegment

The IDirectMusicPerformance::PlaySegment method begins playback of a segment.

HRESULT PlaySegment(
  IDirectMusicSegment* pSegment,
  DWORD dwFlags,
  __int64 i64StartTime,
  IDirectMusicSegmentState** ppSegmentState
);

Parameters

pSegment
Address of the segment to play.
dwFlags
Flags that modify the method's behavior. See DMUS_SEGF_FLAGS.
i64StartTime
The time at which to begin playing the segment, adjusted to any resolution boundary specified in dwFlags. The time is in music time, unless the DMUS_SEGF_REFTIME flag is set. A value of 0 causes the segment to start playing as soon as possible.
ppSegmentState
Address of a variable to receive the segment state for this instance of the playing segment. This field may be NULL. If it is non-NULL, the segment state pointer is returned, and the application must call Release on it.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return one of the following error values:

E_OUTOFMEMORY
E_POINTER
DMUS_E_NO_MASTER_CLOCK
DMUS_E_SEGMENT_INIT_FAILED
DMUS_E_TIME_PAST

Remarks

Segments should be greater than 250 milliseconds in length.

The boundary resolutions in dwFlags are relative to the currently playing primary segment.

If a primary segment is scheduled to play while another primary segment is playing, the first one will stop, unless you set the DMUS_SEGF_QUEUE flag for the second segment, in which case it will play as soon as the first one reaches its end.

For more information on the exact start time of segments, see Segment Timing. For information on how the start time of segments can be affected by tempo changes, see Reference Time vs. Music Time.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

Segments


IDirectMusicPerformance::ReferenceToMusicTime

The IDirectMusicPerformance::ReferenceToMusicTime method converts time in REFERENCE_TIME format to time in MUSIC_TIME format.

HRESULT ReferenceToMusicTime(
  REFERENCE_TIME rtTime,
  MUSIC_TIME* pmtTime
);

Parameters

rtTime
The time in REFERENCE_TIME format.
pmtTime
Address of a variable to receive the converted time in MUSIC_TIME format.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return one of the following error values:

E_POINTER
DMUS_E_NO_MASTER_CLOCK

Remarks

If a master tempo has been set for the performance (see Setting and Retrieving Global Parameters), it is taken into account when converting to music time.

Because music time is less precise than reference time, rounding off will occur.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicPerformance::MusicToReferenceTime, Reference Time vs. Music Time


IDirectMusicPerformance::RemoveNotificationType

The IDirectMusicPerformance::RemoveNotificationType method removes a previously added notification type from the performance. All segments and tracks are updated by a call to their RemoveNotificationType methods.

HRESULT RemoveNotificationType(
  REFGUID rguidNotificationType
);

Parameters

rguidNotificationType
Reference to (C++) or address of (C) the identifier of the notification type to remove. (For the defined types, see DMUS_NOTIFICATION_PMSG.) If this value is GUID_NULL, all notifications are to be removed.

Return Values

If the method succeeds, the return value is S_OK or S_FALSE (see Remarks).

If it fails, the method may return E_POINTER.

Remarks

S_FALSE is returned when rguidNotificationType isn't an active notification.

If a notification was added to a segment that has now stopped playing, the performance cannot remove the notification type from that segment, because it no longer has a reference to the segment.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicPerformance::AddNotificationType, IDirectMusicSegment::RemoveNotificationType, IDirectMusicTrack::RemoveNotificationType, Notification and Event Handling


IDirectMusicPerformance::RemovePort

The IDirectMusicPerformance::RemovePort method removes a port from the performance. Any PChannels that map to this port are invalidated and messages stamped with them will not play.

HRESULT RemovePort(
  IDirectMusicPort* pPort
);

Parameters

pPort
The port to remove.

Return Values

If the method succeeds, the return value is S_OK.

If the method fails, it may return one of the following error values:

E_INVALIDARG
E_POINTER

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicPerformance::AddPort


IDirectMusicPerformance::RhythmToTime

The IDirectMusicPerformance::RhythmToTime method converts rhythm time to music time.

HRESULT RhythmToTime(
  WORD wMeasure,
  BYTE bBeat,
  BYTE bGrid,
  short nOffset,
  DMUS_TIMESIGNATURE *pTimeSig,
  MUSIC_TIME *pmtTime)
);

Parameters

wMeasure
Measure of the time to convert.
bBeat
Beat of the time to convert.
bGrid
Grid of the time to convert.
nOffset
Offset from the grid, in music time ticks, of the time to convert.
pTimeSig
DMUS_TIMESIGNATURE structure containing information about the time signature.
pmtTime
Address of a variable to receive the music time.

Return Values

If the method succeeds, the return value is S_OK.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicPerformance::TimeToRhythm


IDirectMusicPerformance::SendPMsg

The IDirectMusicPerformance::SendPMsg method sends a performance message. This method is called by tracks when they are played. It might also be called by a tool in order to inject new data into a performance.

HRESULT SendPMsg(
  DMUS_PMSG* pPMSG
);

Parameters

pPMSG
Address of a message allocated by IDirectMusicPerformance::AllocPMsg.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return one of the following error values:

DMUS_E_NO_MASTER_CLOCK
DMUS_E_ALREADY_SENT
E_INVALIDARG
E_POINTER

Remarks

The dwFlags member (see DMUS_PMSG) must be set to either DMUS_PMSGF_MUSICTIME or DMUS_PMSGF_REFTIME, depending on the time stamp in either rtTime or mtTime. Also, the dwFlags member should be set to the appropriate delivery type—DMUS_PMSGF_TOOL_QUEUE, DMUS_PMSGF_TOOL_ATTIME, or DMUS_PMSGF_TOOL_IMMEDIATE—depending on the type of message. If none is selected, DMUS_PMSGF_TOOL_IMMEDIATE is used by default.

If the time of the message is set to 0 and the dwFlags member is set to DMUS_PMSGF_REFTIME, it is assumed that this message is cued to go out now.

The IDirectMusicGraph::StampPMsg method should in most cases be called on the message before SendPMsg is called. However, when sending a message directly to the main output tool, this step can be skipped. If you want the message to pass only through the performance graph, you obtain the IDirectMusicGraph interface by calling IDirectMusicPerformance::QueryInterface. Otherwise obtain it by calling IDirectMusicSegment::QueryInterface. Do not attempt to obtain the interface by calling IDirectMusicPerformance::GetGraph or IDirectMusicSegment::GetGraph; these methods return a pointer to the graph object rather than to the implementation of the IDirectMusicGraph interface on the performance or segment.

Normally the performance will free the message after it has been processed. For more information, see the Remarks for IDirectMusicPerformance::FreePMsg.

The follow sample code shows how to allocate and send a sysex message and a tempo message:

/* Assume that pPerformance is a valid IDirectMusicPerformance pointer
   and that mtTime is an initialized MUSIC_TIME variable. */

IDirectMusicGraph* pGraph;

// Get the graph pointer from the performance. If we wanted the
// message to go through a segment graph, we would QueryInterface a
// segment object instead.

if ( SUCCEEDED( pPerformance->QueryInterface(
        IID_IDirectMusicGraph, (void**)&pGraph )))
{
    // Allocate a DMUS_SYSEX_PMSG of the appropriate size and read
    // the sysex data into it

    DMUS_SYSEX_PMSG* pSysEx;

    if ( SUCCEEDED( pPerformance->AllocPMsg(
            sizeof(DMUS_SYSEX_PMSG) + m_dwSysExLength,
            (DMUS_PMSG**)&pSysEx )))
    {
        // All fields are initialized to zero from the
        // AllocPMsg method.
        // Assume m_pbSysExData is a pointer to an array
        //  containing data of length m_dwSysExLength.

        memcpy( pSysEx->abData, m_pbSysExData, m_dwSysExLength );
        pSysEx->dwSize = sizeof(DMUS_SYSEX_PMSG);
        pSysEx->dwLen = dwSysExLength;
        pSysEx->mtTime = mtTime;
        pSysEx->dwFlags = DMUS_PMSGF_MUSICTIME;
        pSysEx->dwType = DMUS_PMSGT_SYSEX;

        pGraph->StampPMsg( (DMUS_PMSG*)pSysEx );
        if (FAILED(pPerformance->SendPMsg( (DMUS_PMSG*)pSysEx )))
        {
            pPerformance->FreePMsg( (DMUS_PMSG*)pSysEx );
        }
    }

    // Change the tempo at time mtTime to 120 bpm.

    DMUS_TEMPO_PMSG* pTempo;

    if( SUCCEEDED( pPerformance->AllocPMsg( sizeof(DMUS_TEMPO_PMSG),
            (DMUS_PMSG**)&pTempo )))
    {
        pTempo->dwSize = sizeof(DMUS_TEMPO_PMSG);
        pTempo->dblTempo = 120;
        pTempo->mtTime = mtTime;
        pTempo->dwFlags = DMUS_PMSGF_MUSICTIME;
        pTempo->dwType = DMUS_PMSGT_TEMPO;
        pGraph->StampPMsg( (DMUS_PMSG*)pTempo );
        if (FAILED(pPerformance->SendPMsg( (DMUS_PMSG*)pTempo )))
        {
            pPerformance->FreePMsg( (DMUS_PMSG*)pTempo );
        }
    }

    pGraph->Release();
}

The next example shows a function that sends a note message associated with the track identified by dwTrackID. Note that the virtual track ID should be 0 if the message is not being generated from a DirectMusicTrack object.

HRESULT CreateNotePMsg(IDirectMusicPerformance* pPerformance,
        MUSIC_TIME mtTime, DWORD dwTrackID)
{

    // Allocate a Note PMessage.
    DMUS_NOTE_PMSG* pNote = NULL;
    HRESULT hr = pPerformance->AllocPMsg( sizeof(DMUS_NOTE_PMSG),
            (DMUS_PMSG**) &pNote);
    if (FAILED(hr)) return hr;

    pNote->dwSize = sizeof(DMUS_NOTE_PMSG); // Size of a Note PMessage
    pNote->rtTime = 0;                      // Will be ignored
    pNote->mtTime = mtTime;                 // When to play the note
    pNote->dwFlags = DMUS_PMSGF_MUSICTIME;  // Use the mtTime field
    pNote->dwPChannel = 5;                  // play on PChannel 5
    pNote->dwVirtualTrackID = dwTrackID;    // Track ID from parameter

    // The following two fields should be set to NULL when a
    // message is initially sent. They will be updated in
    // IDirectMusicGraph::StampPMsg.
    pNote->pTool = NULL;
    pNote->pGraph = NULL;
    pNote->dwType = DMUS_PMSGT_NOTE;
    pNote->dwVoiceID = 0;           // For DirectX 6.1, always 0
    pNote->dwGroupID = 0xFFFFFFFF;  // All track groups
    pNote->punkUser = NULL;         // Always NULL

    // Get the current time signature from the performance
    // to compute measure/beat info
    DMUS_TIMESIGNATURE TimeSig;
    MUSIC_TIME mtNext;
    hr = pPerformance->GetParam(GUID_TimeSignature, 0xFFFFFFFF,
            0, mtTime, &mtNext, &TimeSig);
    if (FAILED(hr)) return hr;

    // Recompute TimeSig.mtTime to have the value expected
    // by pPerformance->TimeToRhythm
    TimeSig.mtTime += mtTime;

    // Get the current chord from the performance
    // to create a note value
    DMUS_CHORD_KEY Chord;
    hr = pPerformance->GetParam(GUID_ChordParam, 0xFFFFFFFF, 0,
            mtTime, &mtNext, &Chord);
    if (FAILED(hr)) return hr;

    // Create a note with octave 5, chord tone 2 (fifth), scale
    // offset 1 (=> sixth), and no accidentals
    WORD wMusicValue = 0x5210;

    // We'll use DMUS_PLAYMODE_PEDALPOINT as our play mode
    // in pPerformance->MusicToMIDI
    BYTE bPlayModeFlags = DMUS_PLAYMODE_PEDALPOINT;

    // Fill in the fields specific to DMUS_NOTE_PMSG
    pNote->wMusicValue = wMusicValue;
    hr = pPerformance->MusicToMIDI(
        wMusicValue,
        &Chord,
        bPlayModeFlags,
        0,
        &(pNote->bMidiValue));
    if (FAILED(hr)) return hr;

    hr = pPerformance->TimeToRhythm(
        TimeSig.mtTime,
        &TimeSig,
        &(pNote->wMeasure),
        &(pNote->bBeat),
        &(pNote->bGrid),
        &(pNote->nOffset));
    if (FAILED(hr)) return hr;

    pNote->mtDuration = DMUS_PPQ;       // Quarter note duration
    pNote->bVelocity = 120;             // MIDI velocity (0 - 127)
    pNote->bFlags = DMUS_NOTEF_NOTEON;  // Always set to this value
    pNote->bTimeRange = 250;            // Randomize start time a lot
    pNote->bDurRange = 5;               // Randomize duration a little
    pNote->bVelRange = 0;               // Don't randomize velocity
    pNote->bPlayModeFlags = bPlayModeFlags;
    pNote->bSubChordLevel = 0;          // Note uses subchord level 0
    pNote->cTranspose = 0;              // No transposition

    // Stamp the message with the performance graph
    IDirectMusicGraph* pGraph;
    hr = pPerformance->QueryInterface( IID_IDirectMusicGraph,
            (void**)&pGraph );
    if (FAILED(hr)) return hr;

    pGraph->StampPMsg( (DMUS_PMSG*)pNote );
    pGraph->Release();

    // Finally, send the message.
    hr = pPerformance->SendPMsg( (DMUS_PMSG*)pNote);
    if (FAILED(hr))
    {
        pPerformance->FreePMsg( (DMUS_PMSG*)pNote);
        return hr;
    }

    return S_OK;

}

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicTool::ProcessPMsg, Messages, DirectMusic Messages, DirectMusic Tools


IDirectMusicPerformance::SetBumperLength

The IDirectMusicPerformance::SetBumperLength method sets the amount of time to buffer ahead of the port's latency for messages to be sent to the port for rendering. For an overview of this topic, see Timing.

HRESULT SetBumperLength(
  DWORD dwMilliSeconds
);

Parameters

dwMilliSeconds
Amount of preplay time, in milliseconds. The default value is 50.

Return Values

The method returns S_OK.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicPerformance::GetBumperLength, IDirectMusicPerformance::SetPrepareTime


IDirectMusicPerformance::SetGlobalParam

The IDirectMusicPerformance::SetGlobalParam method sets global values for the performance.

HRESULT SetGlobalParam(
  REFGUID rguidType,
  void* pParam,
  DWORD dwSize
);

Parameters

rguidType
Reference to (C++) or address of (C) the identifier of the type of data.
pParam
Pointer to the data to be copied and stored by the performance.
dwSize
Size of the data. This is constant for each rguidType.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return one of the following error values:

E_FAIL
E_POINTER
E_OUTOFMEMORY

Remarks

The dwSize parameter is needed because the performance doesn't know about all types of data. New types can be created as needed.

For the parameters defined by DirectMusic and their associated data types, see Setting and Retrieving Global Parameters.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicPerformance::GetGlobalParam, IDirectMusicPerformance::SetParam, Music Parameters


IDirectMusicPerformance::SetGraph

The IDirectMusicPerformance::SetGraph method replaces the performance's tool graph.

HRESULT SetGraph(
  IDirectMusicGraph* pGraph
);

Parameters

pGraph
Tool graph. Can be set to NULL to clear the graph from the performance.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return E_POINTER.

Remarks

Any messages flowing through tools in the current tool graph are deleted.

The graph's reference count is incremented by this method, so it is safe to release the original reference.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicSegment::SetGraph, IDirectMusicPerformance::GetGraph, IDirectMusicPerformance::SendPMsg


IDirectMusicPerformance::SetNotificationHandle

The IDirectMusicPerformance::SetNotificationHandle method sets the event handle (created by the Win32® CreateEvent function) for notifications. The application should use the Win32 WaitForSingleObject function on this handle. When signaled, the application should call the IDirectMusicPerformance::GetNotificationPMsg method to retrieve the notification event.

HRESULT SetNotificationHandle(
  HANDLE hNotification,
  REFERENCE_TIME rtMinimum
);

Parameters

hNotification
Event handle created by CreateEvent, or 0 to clear out an existing handle.
rtMinimum
Minimum time that the performance should hold onto old notify events before discarding them. The value 0 means to use the default minimum time of 20,000,000 reference time units, which is 2 seconds, or the previous value if this method has been called previously. If the application hasn't called GetNotificationPMsg by this time, the event is discarded to free the memory.

Return Values

The method returns S_OK.

Remarks

It is the application's responsibility to call Win32 CloseHandle function on the notification handle when it is no longer needed.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

Notification and Event Handling


IDirectMusicPerformance::SetParam

The IDirectMusicPerformance::SetParam method sets data on a track inside the control segment.

HRESULT SetParam(
  REFGUID rguidType,
  DWORD dwGroupBits,
  DWORD dwIndex,
  MUSIC_TIME mtTime,
  void* pParam
);

Parameters

rguidType
Address of (C) or reference to (C++) the identifier of the type of data to set. See Track Parameter Types.
dwGroupBits
Group the desired track is in.
dwIndex
Index of the track in the group identified by dwGroupBits where data is to be set.
mtTime
Time at which to set the data. Unlike IDirectMusicSegment::SetParam, this time is in performance time. The start time of the segment is subtracted from this time, and the result is passed to IDirectMusicSegment::SetParam.
pParam
Address of structure containing the data. This structure must be of the appropriate kind and size for the data type identified by rguidType.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return one of the following error values:

DMUS_E_NO_MASTER_CLOCK
DMUS_E_SET_UNSUPPORTED
DMUS_E_TRACK_NOT_FOUND
E_POINTER

Remarks

Normally the primary segment is the control segment. However, a secondary segment can be designated as the control segment when it is played. See DMUS_SEGF_FLAGS.

For an explanation of dwGroupBits and dwIndex, see Identifying the Track.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicPerformance::GetParam, IDirectMusicPerformance::SetGlobalParam, IDirectMusicSegment::SetParam, IDirectMusicTrack::SetParam, IDirectMusicPerformance::GetTime, Music Parameters


IDirectMusicPerformance::SetPrepareTime

The IDirectMusicPerformance::SetPrepareTime method sets the interval between the time the IDirectMusicTrack::Play method is called and when the messages should actually be heard through the speaker.

HRESULT SetPrepareTime(
  DWORD dwMilliSeconds
);

Parameters

dwMilliSeconds
Amount of prepare time, in milliseconds. The default value is 1000.

Return Values

The method returns S_OK.

Remarks

For an overview, see Timing.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicPerformance::GetPrepareTime, IDirectMusicPerformance::SetBumperLength


IDirectMusicPerformance::Stop

The IDirectMusicPerformance::Stop method stops playback of one or more segments.

HRESULT Stop(
  IDirectMusicSegment* pSegment,
  IDirectMusicSegmentState* pSegmentState,
  MUSIC_TIME mtTime,
  DWORD dwFlags
);

Parameters

pSegment
Segment to stop playing. All segment states based on this segment are stopped at mtTime. See Remarks.
pSegmentState
Segment state to stop playing. See Remarks.
mtTime
Time at which to stop the segment, segment state, or both. If the time is in the past, or 0 is passed in this parameter, the requested segments and segment states stop playing immediately.
dwFlags
Flag that indicates whether the stop should occur immediately at time mtTime, or on the grid, measure, or beat following mtTime. This is only valid in relation to the currently playing primary segment. (For flag descriptions, see DMUS_SEGF_FLAGS.)

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return E_POINTER.

Remarks

If pSegment and pSegmentState are both NULL, all music stops and all currently cued segments are released. If either pSegment or pSegmentState is not NULL, only the requested segment states are removed from the performance. If both are not NULL, and DMUS_SEGF_DEFAULT is used, the default resolution from the pSegment is used.

If you set all parameters to NULL or 0, everything stops immediately and controller reset messages and note-off messages are sent to all mapped PChannels.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.


IDirectMusicPerformance::TimeToRhythm

The IDirectMusicPerformance::TimeToRhythm method converts music time to rhythm time.

HRESULT TimeToRhythm(
  MUSIC_TIME mtTime,
  DMUS_TIMESIGNATURE *pTimeSig,
  WORD *pwMeasure,
  BYTE *pbBeat,
  BYTE *pbGrid,
  short *pnOffset
);

Parameters

mtTime
Time to convert.
pTimeSig
DMUS_TIMESIGNATURE structure containing information about the time signature.
pwMeasure
Address of a variable to receive the measure where the time falls.
pbBeat
Address of a variable to receive the beat where the time falls.
pbGrid
Address of a variable to receive the grid where the time falls.
pnOffset
Address of a variable to receive the offset from the grid (in music time ticks) where the time falls.

Return Values

If the method succeeds, the return value is S_OK.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicPerformance::RhythmToTime


IDirectMusicPort

The IDirectMusicPort interface provides access to a DirectMusicPort object, which represents a device that sends or receives music data. The input port of an MPU-401, the output port of an MPU-401, the Microsoft Software Synthesizer, and an IHV-provided filter are all ports. Note that a physical device such as an MPU-401 may provide multiple ports. A single port, however, cannot both capture and render data.

For an overview, see Using Ports.

The methods of the IDirectMusicPort interface can be organized into the following groups:

Buffers | PlayBuffer
 | Read
 | SetReadNotificationHandle
Channels | GetChannelPriority
 | GetNumChannelGroups
 | SetChannelPriority
 | SetNumChannelGroups
Device management | Activate
 | DeviceIoControl
 | SetDirectSound
Information | GetCaps
 | GetFormat
 | GetLatencyClock
 | GetRunningStats
Downloadable sounds | Compact
 | DownloadInstrument
 | UnloadInstrument

All COM interfaces inherit the IUnknown interface methods. This interface supports the following three methods:

IUnknown | AddRef
 | QueryInterface
 | Release

The LPDIRECTMUSICPORT type is defined as a pointer to the IDirectMusicPort interface:

typedef IDirectMusicPort *LPDIRECTMUSICPORT;

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicc.h.


IDirectMusicPort::Activate

The IDirectMusicPort::Activate method activates or deactivates the port.

HRESULT Activate(
  BOOL fActive
);

Parameters

fActive
Switch to activate (TRUE) or deactivate (FALSE) the port.

Return Values

If the method succeeds, the return value is S_OK.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicc.h.

See Also

IDirectMusic::Activate, Using Ports


IDirectMusicPort::Compact

The IDirectMusicPort::Compact method is used to instruct the port to compact DLS/wavetable memory, thus making the largest possible contiguous chunk of memory available for new instruments to be downloaded. This method is valid only for an output port that supports DLS wavetable synthesis.

HRESULT Compact();

Parameters

None.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return one of the following error values:

E_FAIL
E_INVALIDARG
E_NOTIMPL
E_OUTOFMEMORY

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicc.h.


IDirectMusicPort::DeviceIoControl

The IDirectMusicPort::DeviceIoControl method calls the Win32 DeviceIoControl function on the underlying file handle implementing the port.

HRESULT DeviceIoControl(
  DWORD dwIoControlCode,
  LPVOID lpInBuffer,
  DWORD nInBufferSize,
  LPVOID lpOutBuffer,
  DWORD nOutBufferSize,
  LPDWORD lpBytesReturned,
  LPOVERLAPPED lpOverlapped
);

Parameters

dwIoControlCode
Control code of operation to perform.
lpInBuffer
Buffer containing input data.
nInBufferSize
Size of input buffer.
lpOutBuffer
Buffer to receive output data.
nOutBufferSize
Size of output buffer
lpBytesReturned
Address of a variable to receive output byte count.
lpOverlapped
Overlapped structure for asynchronous operation.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return one of the following error values:

E_POINTER
E_NOTIMPL

Remarks

This method is supported only on ports implemented by a Windows Driver Model (WDM) filter graph. In the case of a WDM filter graph, the file handle used will be the topmost pin in the graph.

DirectMusic reserves the right to refuse to perform defined kernel streaming operations on a pin which might collide with operations it is performing on the filter graph. User-defined operations, however, will never be blocked.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicc.h.


IDirectMusicPort::DownloadInstrument

The IDirectMusicPort::DownloadInstrument method is used to download an instrument to the DLS device. Downloading an instrument is the process of handing to the DLS device the data that makes up the instrument. This includes articulation data and all waves needed by the instrument. To economize on wave space, only waves and articulation required for a range are downloaded. The method returns an IDirectMusicDownloadedInstrument interface pointer, which is later used to unload the instrument.

HRESULT DownloadInstrument(
  IDirectMusicInstrument *pInstrument,
  IDirectMusicDownloadedInstrument **ppDownloadedInstrument,
  DMUS_NOTERANGE *pNoteRanges,
  DWORD dwNumNoteRanges;
  );

Parameters

pInstrument
Pointer to the instrument from which the method extracts the data to be downloaded.
ppDownloadedInstrument
Address of a variable to receive a pointer to the IDirectMusicDownloadedInstrument interface.
pNoteRanges
Array of DMUS_NOTERANGE structures. Each entry in the array specifies a contiguous range of MIDI note messages to which the instrument must respond. An instrument region will be downloaded only if at least one note in that region is specified in the DMUS_NOTERANGE structures.
dwNumNoteRanges
Number of DMUS_NOTERANGE structures in the array pointed to by pNoteRanges. If this value is set to 0, the pNoteRanges parameter is ignored and all regions and wave data for the instrument are downloaded.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return one of the following error values:

E_POINTER
E_OUTOFMEMORY
E_NOTIMPL

Remarks

To prevent memory loss, the instrument must be unloaded by calling both IDirectMusicPort::UnloadInstrument and IDirectMusicDownloadedInstrument::Release when it is no longer needed.

See Also

IDirectMusicPort::Compact, Working with Instruments

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicc.h.


IDirectMusicPort::GetCaps

The IDirectMusicPort::GetCaps method retrieves the port's capabilities.

HRESULT GetCaps(
  LPDMUS_PORTCAPS pPortCaps
);

Parameters

pPortCaps
Address of a DMUS_PORTCAPS structure to receive the capabilities of the port. The dwSize member of this structure must be properly initialized before the method is called.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return one of the following error values:

E_POINTER
E_INVALIDARG

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicc.h.


IDirectMusicPort::GetChannelPriority

The IDirectMusicPort::GetChannelPriority method is used to retrieve the priority of a MIDI channel. For an overview, see Channels.

HRESULT GetChannelPriority(
  DWORD   dwChannelGroup,
  DWORD   dwChannel,
  LPDWORD pdwPriority
);

Parameters

dwChannelGroup
Group the channel is in.
dwChannel
Index of the channel on the group.
pdwPriority
Address of a variable to receive the priority ranking. See Remarks.

Return Values

If the method succeeds, the return value is S_OK.

Remarks

The following values, defined in Dmusicc.h, each represent a range of priorities. They are listed here in descending order of priority.

DAUD_CRITICAL_VOICE_PRIORITY
DAUD_HIGH_VOICE_PRIORITY
DAUD_STANDARD_VOICE_PRIORITY
DAUD_LOW_VOICE_PRIORITY

The following values express the default ranking of the channels within a range, according to the DLS Level 1 standard. They are listed here in descending order. Note that channel 10, the percussion channel, has the highest priority.

DAUD_CHAN10_DEF_VOICE_PRIORITY_OFFSET
DAUD_CHAN1_DEF_VOICE_PRIORITY_OFFSET
DAUD_CHAN2_DEF_VOICE_PRIORITY_OFFSET
DAUD_CHAN3_DEF_VOICE_PRIORITY_OFFSET
DAUD_CHAN4_DEF_VOICE_PRIORITY_OFFSET
DAUD_CHAN5_DEF_VOICE_PRIORITY_OFFSET
DAUD_CHAN6_DEF_VOICE_PRIORITY_OFFSET
DAUD_CHAN7_DEF_VOICE_PRIORITY_OFFSET
DAUD_CHAN8_DEF_VOICE_PRIORITY_OFFSET
DAUD_CHAN9_DEF_VOICE_PRIORITY_OFFSET
DAUD_CHAN11_DEF_VOICE_PRIORITY_OFFSET
DAUD_CHAN12_DEF_VOICE_PRIORITY_OFFSET
DAUD_CHAN13_DEF_VOICE_PRIORITY_OFFSET
DAUD_CHAN14_DEF_VOICE_PRIORITY_OFFSET
DAUD_CHAN15_DEF_VOICE_PRIORITY_OFFSET
DAUD_CHAN16_DEF_VOICE_PRIORITY_OFFSET

The priority of a channel is represented by a range plus an offset. For example, DAUD_STANDARD_VOICE_PRIORITY + DAUD_CHAN10_DEF_VOICE_PRIORITY represents the highest priority within the standard range.

Channels that have the same priority value have equal priority regardless of which channel group they belong to.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicc.h.

See Also

IDirectMusicPort::SetChannelPriority


IDirectMusicPort::GetFormat

The IDirectMusicPort::GetFormat method retrieves information about the wave format specified in the DMUS_PORTPARAMS structure passed to IDirectMusic::CreatePort, and the recommended size of the buffer to use for wave output. The information can be used to create a compatible IDirectSoundBuffer for the port.

HRESULT GetFormat(
  LPWAVEFORMATEX pWaveFormatEx,
  LPDWORD pdwWaveFormatExSize
  LPDWORD pdwBufferSize
);

Parameters

pWaveFormatEx
WAVEFORMATEX structure to receive information about the format. This value can be NULL. See Remarks.
pdwWaveFormatExSize
Address of a variable that contains, or is to receive, the size of the structure. See Remarks.
pdwBufferSize
Address of a variable to receive the recommended size of the DirectSound buffer.

Return Values

Return values are determined by the implementation. If successful, the method should return S_OK. If it fails, the method may return E_POINTER.

Remarks

The WAVEFORMATEX structure can have a variable length that depends on the details of the format. Before retrieving the format description, the application should query the synthesizer object for the size of the format by calling this method and specifying NULL for the pWaveFormatEx parameter. The size of the structure will be returned in the variable pointed to by pdwWaveFormatExSize. The application can then allocate sufficient memory and call GetFormat again to retrieve the format description.

If pWaveFormatEx is not NULL, DirectMusic writes, at most, pdwWaveFormatExSize bytes to the structure.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicc.h.

See Also

IDirectMusicPort::SetDirectSound


IDirectMusicPort::GetLatencyClock

The IDirectMusicPort::GetLatencyClock method is used to get an IReferenceClock interface pointer to the port's latency clock. The latency clock specifies the nearest time in the future at which a message can be played on time. The latency clock is based on the DirectMusic master clock, which is set by using the IDirectMusic::SetMasterClock method.

HRESULT GetLatencyClock(
  IReferenceClock** ppClock
);

Parameters

ppClock
Address of a variable to receive the latency clock's IReferenceClock interface pointer.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return E_POINTER.

Remarks

In accordance with COM rules, GetLatencyClock increments the reference count of the returned interface. Therefore the application must call Release on the IReferenceClock interface at some point.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicc.h.

See Also

Latency and Bumper Time


IDirectMusicPort::GetNumChannelGroups

The IDirectMusicPort::GetNumChannelGroups method retrieves the number of channel groups on the port.

HRESULT GetNumChannelGroups
  LPDWORD pdwChannelGroups
);

Parameters

pdwChannelGroups
Address of a variable to receive the number of channel groups.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return one of the following error values:

E_FAIL
E_INVALIDARG
E_NOTIMPL
E_OUTOFMEMORY

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicc.h.

See Also

IDirectMusicPort::SetNumChannelGroups, Channels


IDirectMusicPort::GetRunningStats

The IDirectMusicPort::GetRunningStats method retrieves information about the state of the port's synthesizer.

HRESULT GetRunningStats(
  LPDMUS_SYNTHSTATS pStats
);

Parameters

pStats
Address of a DMUS_SYNTHSTATS structure to receive running statistics of the synthesizer. The dwSize member of this structure must be properly initialized before the method is called.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return one of the following error values:

E_POINTER
E_INVALIDARG
E_NOTIMPL

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicc.h.


IDirectMusicPort::PlayBuffer

The IDirectMusicPort::PlayBuffer method is used to cue a buffer for playback by the port.

HRESULT PlayBuffer(
  IDIRECTMUSICBUFFER* pBuffer
);

Parameters

pBuffer
DirectMusicBuffer object to be added to the port's playback queue.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return one of the following error values:

E_FAIL
E_INVALIDARG
E_NOTIMPL
E_OUTOFMEMORY

Remarks

The buffer is in use by the system only for the duration of this method and is free to be reused after the method returns.

If no start time has been set by using the IDirectMusicBuffer::SetStartTime method, the start time is the time of the earliest event in the buffer, as set by the IDirectMusicBuffer::PackStructured or IDirectMusicBuffer::PackUnstructured method.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicc.h.

See Also

IDirectMusicBuffer, IDirectMusic::CreateMusicBuffer


IDirectMusicPort::Read

The IDirectMusicPort::Read method fills a buffer with incoming MIDI data. The method should be called with new buffer objects until no more data is available to be read.

HRESULT Read(
  IDirectMusicBuffer *pBuffer
);

Parameters

pBuffer
Pointer to a DirectMusicBuffer object to be filled with the incoming MIDI data.

Return Values

If the method succeeds, the return value is S_OK or S_FALSE.

If it fails, the method may return one of the following error values:

E_POINTER
E_NOTIMPL

Remarks

When there is no more data to read, the method returns S_FALSE.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicc.h.

See Also

Capturing Music


IDirectMusicPort::SetChannelPriority

The IDirectMusicPort::SetChannelPriority method is used to set the priority of a MIDI channel. For an overview, see Channels.

HRESULT SetChannelPriority(
  DWORD  dwChannelGroup,
  DWORD  dwChannel,
  DWORD  dwPriority
);

Parameters

dwChannelGroup
Group the channel is in. This value must be 1 or greater.
dwChannel
Index of the channel on the group.
dwPriority
The priority ranking. See Remarks for IDirectMusicPort::GetChannelPriority.

Return Values

If the method succeeds, the return value is S_OK.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicc.h.

See Also

IDirectMusicPort::GetChannelPriority, DMUS_CHANNEL_PRIORITY_PMSG.


IDirectMusicPort::SetDirectSound

The IDirectMusicPort::SetDirectSound method is used to override the default DirectSound object or buffer, or both, to which a port's wave data is streamed. It is also used to disconnect the port from DirectSound.

HRESULT SetDirectSound(
  LPDIRECTSOUND pDirectSound,
  LPDIRECTSOUNDBUFFER pDirectSoundBuffer
);

Parameters

pDirectSound
IDirectSound interface of the DirectSound object to which the port is to be connected, or NULL to disconnect and release the existing DirectSound object.
pDirectSoundBuffer
IDirectSoundBuffer interface to connect the port to. This value can be NULL.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return one of the following error values:

DMUS_E_ALREADY_ACTIVATED
E_INVALIDARG

Remarks

When the port is activated, the primary DirectSound buffer will be upgraded, if necessary, to support the sample rate and channel information for this port (specified in the DMUS_PORTPARAMS structure passed to IDirectMusic::CreatePort).

The buffer pointed to by pDirectSoundBuffer must be a secondary streaming buffer with a format that matches the sample rate and channel information for this port. If this parameter is NULL, then an appropriate IDirectSoundBuffer instance will be created internally.

Neither the IDirectSound nor the IDirectSoundBuffer may be changed once the port has been activated.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicc.h.

See Also

IDirectMusicPort::Activate, IDirectMusicPort::GetFormat, Integrating DirectMusic and DirectSound


IDirectMusicPort::SetNumChannelGroups

The IDirectMusicPort::SetNumChannelGroups method changes the number of channel groups that the application needs on the port.

HRESULT SetNumChannelGroups(
  DWORD dwChannelGroups
);

Parameters

dwChannelGroups
Number of channel groups on this port that the application wants to allocate.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return one of the following error values:

E_FAIL
E_INVALIDARG
E_NOTIMPL
E_OUTOFMEMORY

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicc.h.

See Also

IDirectMusicPort::GetNumChannelGroups, Channels


IDirectMusicPort::SetReadNotificationHandle

The IDirectMusicPort::SetReadNotificationHandle method specifies an event that is to be set when MIDI messages are available to be read with the IDirectMusicPort::Read method. The event will be signaled whenever new data is available. To turn off event notification, call SetReadNotificationHandle with a NULL value for the hEvent parameter.

HRESULT SetReadNotificationHandle(
  HANDLE hEvent
);

Parameters

hEvent
An event handle obtained from a call to the Win32 CreateEvent function. It is the application's responsibility to close this handle once the port has been released.

Return Values

The method returns S_OK.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicc.h.

See Also

Capturing Music


IDirectMusicPort::UnloadInstrument

The IDirectMusicPort::UnloadInstrument method is used to unload a previously downloaded DLS instrument.

HRESULT UnloadInstrument(
  IDirectMusicDownloadedInstrument *pDownloadedInstrument
);

Parameters

pDownloadedInstrument
Pointer to an IDirectMusicDownloadedInstrument interface, obtained when the instrument was downloaded by calling the IDirectMusicPort::DownloadInstrument method.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return one of the following error values:

DMUS_E_NOT_DOWNLOADED_TO_PORT
E_POINTER
E_NOTIMPL

Remarks

This method must be called in order to free memory allocated by IDirectMusicPort::DownloadInstrument.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicc.h.

See Also

Working with Instruments


IDirectMusicPortDownload

The IDirectMusicPortDownload interface allows an application to talk directly to a port that supports DLS downloading, and to download memory chunks directly to the port. The interface is used primarily by authoring applications that directly edit DLS instruments. For an overview, see Low-Level DLS.

To obtain the IDirectMusicPortDownload interface, call the IDirectMusicPort::QueryInterface method, passing in IID_IDirectMusicPortDownload as the interface GUID. If the port does not support DLS downloading, this call might fail.

The methods of the IDirectMusicPortDownload interface can be grouped as follows:

Buffer management | AllocateBuffer
 | GetAppend
 | GetBuffer
 | GetDLId
Loading | Download
 | Unload

All COM interfaces inherit the IUnknown interface methods. This interface supports the following three methods:

IUnknown | AddRef
 | QueryInterface
 | Release

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicc.h.


IDirectMusicPortDownload::AllocateBuffer

The IDirectMusicPortDownload::AllocateBuffer method allocates a chunk of memory for downloading DLS data to the port, and returns an IDirectMusicDownload interface pointer that allows access to this buffer.

HRESULT AllocateBuffer(
  DWORD dwSize,
  IDirectMusicDownload** ppIDMDownload
);

Parameters

dwSize
Requested size of buffer.
ppIDMDownload
Address of a variable to receive the IDirectMusicDownload interface pointer.

Return Values

If the method succeeds, it returns S_OK.

If it fails, the method may return one of the following error values:

E_POINTER
E_INVALIDARG
E_OUTOFMEMORY

Remarks

Once a buffer has been allocated, the size cannot change.

The buffer is freed when the IDirectMusicDownload interface is released.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicc.h.

See Also

IDirectMusicPortDownload::GetBuffer, Low-Level DLS


IDirectMusicPortDownload::Download

The IDirectMusicPortDownload::Download method downloads a wave or instrument definition to the port. The memory must first be allocated by using the IDirectMusicPortDownload::AllocateBuffer method.

HRESULT Download(
  IDirectMusicDownload* pIDMDownload
);

Parameters

pIDMDownload
IDirectMusicDownload interface pointer for the buffer.

Return Values

Return values are determined by the implementation of the port.

If the method succeeds, it returns S_OK.

If the method fails, it may return one of the following values:

E_POINTER
E_FAIL
DMUS_E_ALREADY_DOWNLOADED
DMUS_E_BADARTICULATION
DMUS_E_BADINSTRUMENT
DMUS_E_BADOFFSETTABLE
DMUS_E_BADWAVE
DMUS_E_BADWAVELINK
DMUS_E_BUFFERNOTSET
DMUS_E_NOARTICULATION
DMUS_E_NOTMONO
DMUS_E_NOTPCM
DMUS_E_UNKNOWNDOWNLOAD

Remarks

For more information on how to prepare the data to be downloaded, see Low-Level DLS.

Once the memory has been downloaded, you cannot do anything more with it. To update the download, you must create a new buffer and assign it a new download ID obtained by using the IDirectMusicPortDownload::GetDLId method, then send it down.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicc.h.

See Also

IDirectMusicPortDownload::Unload, DMUS_DOWNLOADINFO, DMUS_OFFSETTABLE


IDirectMusicPortDownload::GetAppend

The IDirectMusicPortDownload::GetAppend method retrieves the amount of memory the port needs to be appended to the end of a download buffer. This extra memory can be used by the port to interpolate across a loop boundary.

HRESULT GetAppend(
  DWORD* pdwAppend
);

Parameters

pdwAppend
Address of a variable to receive the number of appended samples for which memory is required. The actual amount of memory can be calculated from the wave format.

Return Values

Return values are determined by the port implementation.

If the method succeeds, the return value is S_OK.

If it fails, the method may return one of the following error values:

E_POINTER
E_NOTIMPL

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicc.h.


IDirectMusicPortDownload::GetBuffer

The IDirectMusicPortDownload::GetBuffer method retrieves the IDirectMusicDownload interface pointer of a buffer whose unique identifier is known.

HRESULT GetBuffer(
  DWORD dwDLId,
  IDirectMusicDownload** ppIDMDownload
);

Parameters

dwDLId
Download identifier of the buffer. See DMUS_DOWNLOADINFO.
ppIDMDownload
Address of a variable to receive the IDirectMusicDownload interface pointer for the buffer.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return one of the following error values:

E_POINTER
DMUS_E_INVALID_DOWNLOADID
DMUS_E_NOT_DOWNLOADED_TO_PORT

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicc.h.

See Also

IDirectMusicPortDownload::GetDLId, IDirectMusicDownload::GetBuffer, Low-Level DLS.


IDirectMusicPortDownload::GetDLId

The IDirectMusicPortDownload::GetDLId method obtains sequential identifiers for one or more download buffers.

Every memory chunk downloaded to the synthesizer must have a unique identifier placed in its DMUS_DOWNLOADINFO structure. The GetDLId method guarantees that no two downloads have the same identifier.

HRESULT GetDLId(
  DWORD* pdwStartDLId,
  DWORD dwCount
);

Parameters

pdwStartDLId
Address of a variable to receive the first identifier.
dwCount
Number of identifiers to reserve. You might plan to download a whole series of chunks at once. Instead of calling GetDLId for each chunk, set dwCount to the number of chunks. GetDLId returns the first ID of the set, and the additional identifiers are automatically reserved up through *pdwStartDLId + dwCount. A subsequent call to GetDLId will skip past the reserved values.

Return Values

If the method succeeds, it returns S_OK.

If it fails, the method may return one of the following error values:

E_POINTER
E_INVALIDARG

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicc.h.

See Also

IDirectMusicPortDownload::GetBuffer, Low-Level DLS


IDirectMusicPortDownload::Unload

The IDirectMusicPortDownload::Unload method unloads a buffer that was previously downloaded by using IDirectMusicPortDownload::Download.

HRESULT Unload(
  IDirectMusicDownload* pIDMDownload
);

Parameters

pIDMDownload
IDirectMusicDownload interface pointer for the buffer.

Return Values

Return values are determined by the port implementation.

If the method succeeds, the return value is S_OK.

If it fails, the method may return one of the following values:

E_NOINTERFACE
DMUS_E_SYNTHNOTCONFIGURED

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicc.h.


IDirectMusicSegment

The IDirectMusicSegment interface represents a segment, a chunk of music made up of multiple tracks. Because almost all of the information that defines a segment is stored in the tracks, and because tracks can be just about anything, the segment itself is a relatively simple object. There are methods to access data in tracks, even though the segment object has no knowledge of the nature of the data.

Segments are usually loaded by calling IDirectMusicLoader::GetObject. They can also be assembled by using the CoCreateInstance function and the IDirectMusicSegment::InsertTrack method.

The DirectMusicSegment object also supports the IDirectMusicObject and IPersistStream interfaces for loading its data.

The methods of the IDirectMusicSegment interface can be grouped as follows:

Timing and looping | GetDefaultResolution
 | GetLength
 | GetLoopPoints
 | GetRepeats
 | GetStartPoint
 | SetDefaultResolution
 | SetLength
 | SetLoopPoints
 | SetRepeats
 | SetStartPoint
Tracks | GetTrack
 | GetTrackGroup
 | InsertTrack
 | RemoveTrack
Notification | AddNotificationType
 | RemoveNotificationType
Parameters | GetParam
 | SetParam
Tools | GetGraph
 | SetGraph
Miscellaneous | Clone
 | InitPlay
 | SetPChannelsUsed

All COM interfaces inherit the IUnknown interface methods. This interface supports the following three methods:

IUnknown | AddRef
 | QueryInterface
 | Release

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

Segments


IDirectMusicSegment::AddNotificationType

The IDirectMusicSegment::AddNotificationType method is similar to and called from the IDirectMusicPerformance::AddNotificationType method, giving the segment a chance to respond to notifications. The segment calls each track's IDirectMusicTrack::AddNotificationType method.

HRESULT AddNotificationType(
  REFGUID rguidNotificationType
);

Parameters

rguidNotificationType
Reference to (C++) or address of (C) the identifier of the notification type to add. For the defined types, see DMUS_NOTIFICATION_PMSG. Applications can also define their own types for custom tracks.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return one of the following error values:

E_POINTER
E_OUTOFMEMORY

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

Notification and Event Handling


IDirectMusicSegment::Clone

The IDirectMusicSegment::Clone method creates a copy of the segment and all the tracks it contains.

HRESULT Clone(
  MUSIC_TIME mtStart,
  MUSIC_TIME mtEnd,
  IDirectMusicSegment** ppSegment
);

Parameters

mtStart
The start of the part to clone. If less than 0, or greater than the length of the segment, 0 will be used.
mtEnd
The end of the part to clone. If this value is past the end of the segment, the segment will be cloned to the end. A value of 0 or anything less than mtStart will also clone to the end.
ppSegment
Address of a variable to receive a pointer to the created segment, if successful. It is caller's responsibility to call Release when finished with the segment.

Return Values

If the method succeeds, the return value is S_OK, or S_FALSE if some tracks failed to clone.

If it fails, the method may return one of the following error values:

E_OUTOFMEMORY
E_POINTER

Remarks

If an IDirectMusicGraph exists in the segment, a copy of the pointer is included in the clone and the reference count is incremented. The start point and loop points set by the IDirectMusicSegment::SetStartPoint and IDirectMusicSegment::SetLoopPoints methods are set to their default values (0, and 0 to the end of the segment respectively) inside the clone. The number of repeats is reset to 0. The resolution set by the IDirectMusicSegment::SetDefaultResolution method is copied into the clone.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.


IDirectMusicSegment::GetDefaultResolution

The IDirectMusicSegment::GetDefaultResolution method retrieves the default resolution for synchronization.

HRESULT GetDefaultResolution(
  DWORD* pdwResolution
);

Parameters

pdwResolution
Address of a variable to receive the default resolution. See DMUS_SEGF_FLAGS.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return E_POINTER.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicSegment::SetDefaultResolution, Segment Timing


IDirectMusicSegment::GetGraph

The IDirectMusicSegment::GetGraph method retrieves the segment's tool graph.

HRESULT GetGraph(
  IDirectMusicGraph** ppGraph
);

Parameters

ppGraph
Address of a variable to receive a pointer to the tool graph.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return one of the following error values:

E_FAIL
E_POINTER

Remarks

If there is no graph in the segment, the method returns E_FAIL.

The reference count of the tool graph is incremented.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicSegment::SetGraph


IDirectMusicSegment::GetLength

The IDirectMusicSegment::GetLength method retrieves the length of the segment.

HRESULT GetLength(
  MUSIC_TIME* pmtLength
);

Parameters

pmtLength
Address of a variable to receive the segment's length in music time.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return E_POINTER.

Remarks

If for some reason the segment's length was never set, *pmtLength is set to 0.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicSegment::SetLength


IDirectMusicSegment::GetLoopPoints

The IDirectMusicSegment::GetLoopPoints method retrieves the start and end loop points inside the segment that will repeat the number of times set by the IDirectMusicSegment::SetRepeats method.

HRESULT GetLoopPoints(
  MUSIC_TIME* pmtStart,
  MUSIC_TIME* pmtEnd
);

Parameters

pmtStart
Address of a variable to receive the start point of the loop.
pmtEnd
Address of a variable to receive the end point of the loop. A value of 0 indicates that the entire segment will loop.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return E_POINTER.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicSegment::SetLoopPoints, Segment Timing


IDirectMusicSegment::GetParam

The IDirectMusicSegment::GetParam method retrieves data from a track inside this segment.

HRESULT GetParam(
  REFGUID rguidType,
  DWORD dwGroupBits,
  DWORD dwIndex,
  MUSIC_TIME mtTime,
  MUSIC_TIME* pmtNext,
  void* pParam
);

Parameters

rguidType
Reference to (C++) or address of (C) the identifier of the type of data to obtain. See Track Parameter Types.
dwGroupBits
Group the desired track is in. Use 0xFFFFFFFF for all groups. For more information, see Identifying the Track.
dwIndex
Index of the track in the group identified by dwGroupBits from which to obtain the data.
mtTime
Time from which to obtain the data.
pmtNext
Address of a variable to receive the segment time (relative to mtTime) until which the data is valid. If this returns a value of 0, it means either that the data will always be valid, or that it is unknown when it will become invalid. If this information is not needed, pmtNext can be set to NULL. See Remarks.
pParam
Address of an allocated structure in which the data is to be returned. The structure must be of the appropriate kind and size for the data type identified by rguidType.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return one of the following error values:

DMUS_E_GET_UNSUPPORTED
DMUS_E_TRACK_NOT_FOUND
E_POINTER

Remarks

The data can become invalid before the time returned in *pmtNext if another control segment is cued. For more information on control segments, see Segments.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicPerformance::GetParam, IDirectMusicSegment::SetParam, IDirectMusicTrack::GetParam, Music Parameters


IDirectMusicSegment::GetRepeats

The IDirectMusicSegment::GetRepeats method retrieves the number of times the segment is set to repeat.

HRESULT GetRepeats(
  DWORD* pdwRepeats
);

Parameters

pdwRepeats
Address of a variable to receive the number of times the segment is set to repeat.

Return Values

If the method succeeds, the return value is S_OK.

If the method fails, the return value may be E_POINTER.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicSegment::SetRepeats


IDirectMusicSegment::GetStartPoint

The IDirectMusicSegment::GetStartPoint method retrieves the point where the segment will start playing in response to the IDirectMusicPerformance::PlaySegment method.

HRESULT GetStartPoint(
  MUSIC_TIME* pmtStart
);

Parameters

pmtStart
Address of a variable to receive the time within the segment when it will start playing.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return E_POINTER.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicSegment::SetStartPoint


IDirectMusicSegment::GetTrack

The IDirectMusicSegment::GetTrack method searches the list of tracks for the one with the supplied type, group, and index, and retrieves a pointer to the DirectMusicTrack object.

HRESULT GetTrack(
  REFGUID rguidType,
  DWORD dwGroupBits,
  DWORD dwIndex,
  IDirectMusicTrack** ppTrack
);

Parameters

rguidType
Address of (C) or reference to (C++) the identifier of the track to find (for example, CLSID_DirectMusicChordTrack). A value of GUID_NULL will retrieve any track. For the track identifiers, see IDirectMusicTrack.
dwGroupBits
Track groups in which to scan for the track. A value of 0 is invalid. Each bit in dwGroupBits corresponds to a track group. To scan all tracks regardless of groups, set this parameter to 0xFFFFFFFF.
dwIndex
Zero-based index into the list of tracks of type rguidType and in group dwGroupBits to return. If multiple groups are selected in dwGroupBits, this index will indicate the nth track of type rguidType encountered in the union of the groups selected.
ppTrack
Address of a variable to receive a pointer to the track. The variable set to NULL if the track is not found.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return E_FAIL.

Remarks

To enumerate all tracks, use GUID_NULL for the rguidType and 0xFFFFFFFF for dwGroupBits. Call GetTrack starting with 0 for dwIndex, incrementing dwIndex until the method no longer returns a success code.

For more information on track groups, see Identifying the Track.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicSegment::InsertTrack


IDirectMusicSegment::GetTrackGroup

The IDirectMusicSegment::GetTrackGroup method retrieves the group bits set on a track inside the segment.

HRESULT GetTrackGroup(
  IDirectMusicTrack* pTrack,
  DWORD* pdwGroupBits
);

Parameters

pTrack
Track for which to find the group bits.
pdwGroupBits
Address of a variable to receive the groups. Each bit in *pdwGroupBits corresponds to a track group.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return one of the following error values:

E_FAIL
E_INVALIDARG

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicSegment::InsertTrack, Identifying the Track


IDirectMusicSegment::InitPlay

The IDirectMusicSegment::InitPlay method is called by the performance when the segment is about to be played.

HRESULT InitPlay(
  IDirectMusicSegmentState** ppSegState,
  IDirectMusicPerformance* pPerformance,
  DWORD dwFlags
);

Parameters

ppSegState
Address of a variable to receive a pointer to the IDirectMusicSegmentState interface, which is created in response to this method call and is used to hold state data. It is returned with a reference count of 1, so a call to its Release method will fully release it.
pPerformance
Address of the IDirectMusicPerformance interface. This is needed by the segment and segment state in order to call methods on the performance object.
dwFlags
DMUS_SEGF_FLAGS that modify the track's behavior. See Remarks.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return one of the following error values:

E_POINTER
E_OUTOFMEMORY

Remarks

When a segment is cued to play, it must create a state structure to store all variables that track the state of one individual performance of the segment. The InitPlay method is called by the performance engine when the segment is about to be played. The segment, in turn, collects state objects for each of the tracks, by calling their IDirectMusicTrack::InitPlay methods, and stores it all in a segment state object, accessed by using the IDirectMusicSegmentState interface. Later, when the segment is finished playing, the performance engine frees it by calling the Release method.

When the segment creates the IDirectMusicSegmentState, it should give the segment state a copy of pPerformance.

Note that a newly created segment state starts with its seek point set to 0.

The dwFlags parameter passes the flags that were handed to the performance in the call to IDirectMusicPerformance::PlaySegment. The track makes decisions on how it should perform based on the DMUS_SEGF_CONTROL and DMUS_SEGF_SECONDARY flags. For example, the tempo track automatically plays the tempo changes only if it is part of a primary segment or a secondary control segment (DMUS_SEGF_SECONDARY is not set, or DMUS_SEGF_CONTROL is set).

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.


IDirectMusicSegment::InsertTrack

The IDirectMusicSegment::InsertTrack method inserts the supplied track into the segment's list of tracks.

HRESULT InsertTrack(
  IDirectMusicTrack* pTrack,
  DWORD dwGroupBits
);

Parameters

pTrack
The track to add to the segment.
dwGroupBits
Group or groups into which to insert the track. This value cannot be 0.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return one of the following error values:

E_FAIL
E_INVALIDARG
E_OUTOFMEMORY
E_POINTER

Remarks

Tracks are put in groups in order to link them correctly. For example, a segment might contain two style tracks and two mute tracks. Each style track would be put in a different group along with its associated mute track. For more information on track groups, see Identifying the Track.

If the segment is currently playing, the new track is not included in playback, because the segment state was not initialized with the new track.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicSegment::RemoveTrack, IDirectMusicSegment::GetTrackGroup


IDirectMusicSegment::RemoveNotificationType

The IDirectMusicSegment::RemoveNotificationType method is similar to and called from the IDirectMusicPerformance::RemoveNotificationType method, allowing the segment to remove notifications. The segment calls each track's IDirectMusicTrack::RemoveNotificationType method.

HRESULT RemoveNotificationType(
  REFGUID rguidNotificationType
);

Parameters

rguidNotificationType
Reference to (C++) or address of (C) the identifier of the notification type to remove. (For the defined types, see DMUS_NOTIFICATION_PMSG.) Setting this value to GUID_NULL causes all notifications to be removed.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return E_POINTER.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

Notification and Event Handling


IDirectMusicSegment::RemoveTrack

The IDirectMusicSegment::RemoveTrack method removes a track from the segment's track list.

HRESULT RemoveTrack(
  IDirectMusicTrack* pTrack
);

Parameters

pTrack
The track to remove from the segment's track list.

Return Values

If the method succeeds, the return value is S_OK, or S_FALSE if the specified track is not in the track list.

If the method fails, the return value may be E_POINTER.

Remarks

The track is released when removed.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicSegment::InsertTrack


IDirectMusicSegment::SetDefaultResolution

The IDirectMusicSegment::SetDefaultResolution method sets the default resolution for synchronization.

HRESULT SetDefaultResolution(
  DWORD dwResolution
);

Parameters

dwResolution
The desired default resolution. This value can be 0 or one of the following members of the DMUS_SEGF_FLAGS enumeration:

DMUS_SEGF_MEASURE
DMUS_SEGF_BEAT
DMUS_SEGF_GRID

Return Values

The method returns S_OK.

Remarks

This method is used primarily by secondary segments (motifs) to define whether they are synchronized to the measure, beat, or grid resolutions.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicSegment::GetDefaultResolution, Segment Timing


IDirectMusicSegment::SetGraph

The IDirectMusicSegment::SetGraph method assigns a tool graph to the segment.

HRESULT SetGraph(
  IDirectMusicGraph* pGraph
);

Parameters

pGraph
Tool graph pointer. Can be set to NULL to clear the segment graph.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return E_POINTER.

Remarks

Any messages flowing through tools in the current tool graph are deleted.

The graph's reference count is incremented, so it is safe to release the original reference.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicPerformance::SetGraph, DirectMusic Tools


IDirectMusicSegment::SetLength

The IDirectMusicSegment::SetLength method sets the length, in music time, of the segment. This method is usually called by the loader, which retrieves the segment length from the file and passes it to the segment object.

HRESULT SetLength(
  MUSIC_TIME mtLength
);

Parameters

mtLength
The desired length. Must be greater than 0.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return one of the following error values:

E_INVALIDARG
DMUS_E_OUT_OF_RANGE

Remarks

Neglecting to set a primary segment length can cause problems when cueing other primary segments with the DMUS_SEGF_QUEUE flag.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicSegment::GetLength


IDirectMusicSegment::SetLoopPoints

The IDirectMusicSegment::SetLoopPoints method sets the start and end points inside the segment that will repeat the number of times set by the IDirectMusicSegment::SetRepeats method.

HRESULT SetLoopPoints(
  MUSIC_TIME mtStart,
  MUSIC_TIME mtEnd
);

Parameters

mtStart
The point at which to begin the loop.
mtEnd
The point at which to end the loop. A value of 0 loops the entire segment.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return DMUS_E_OUT_OF_RANGE.

Remarks

The default values are set to loop the entire segment from beginning to end.

The method fails if mtStart is greater than or equal to the length of the segment, or if mtEnd is greater than the length of the segment. If mtEnd is 0, mtStart must be 0 as well.

This method does not affect any currently playing segment states created from this segment.

The loop points of a cached segment persist even if the segment is released and then reloaded. To ensure that a segment is not subsequently reloaded from the cache, call IDirectMusicLoader::ReleaseObject on it before releasing it.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicSegment::GetLoopPoints, Segment Timing


IDirectMusicSegment::SetParam

The IDirectMusicSegment::SetParam method sets data on a track inside this segment.

HRESULT SetParam(
  REFGUID rguidType,
  DWORD dwGroupBits,
  DWORD dwIndex,
  MUSIC_TIME mtTime,
  void* pParam
);

Parameters

rguidType
Reference to (C++) or address of (C) the type of data to set. See Track Parameter Types.
dwGroupBits
Group the desired track is in. Use 0xFFFFFFFF for all groups. For more information, see the Remarks for IDirectMusicPerformance::SetParam.
dwIndex
Index of the track in the group identified by dwGroupBits in which to set the data.
mtTime
Time at which to set the data.
pParam
Address of structure containing the data, or NULL if no data is required. The structure must be of the appropriate kind and size for the data type identified by rguidType.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return one of the following error values:

DMUS_E_SET_UNSUPPORTED
DMUS_E_TRACK_NOT_FOUND
E_POINTER

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicPerformance::SetParam, IDirectMusicSegment::GetParam, IDirectMusicTrack::SetParam, Music Parameters


IDirectMusicSegment::SetPChannelsUsed

The IDirectMusicSegment::SetPChannelsUsed method sets the performance channels (PChannels) this segment uses. This method is usually called by a track in the IDirectMusicTrack::Init method, in order to inform the segment which PChannels the track uses.

HRESULT SetPChannelsUsed(
  DWORD dwNumPChannels,
  DWORD* paPChannels
);

Parameters

dwNumPChannels
The number of PChannels to set. This must be equal to the number of members in the array pointed to by paPChannels.
paPChannels
Points to an array of PChannels.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return one of the following error values:

E_INVALIDARG
E_OUTOFMEMORY
E_POINTER

Remarks

The purpose of this method is to allow the performance to know which ports are being used by the segment, so that it can determine the actual latency rather than providing for the worst case.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

Latency and Bumper Time, Channels


IDirectMusicSegment::SetRepeats

The IDirectMusicSegment::SetRepeats method sets the number of times the segment is to repeat.

HRESULT SetRepeats(
  DWORD dwRepeats
);

Parameters

dwRepeats
The number of times the segment is to repeat.

Return Values

The method returns S_OK.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicSegment::GetRepeats, Segment Timing


IDirectMusicSegment::SetStartPoint

The IDirectMusicSegment::SetStartPoint method sets the point where the segment will start playing in response to a call to the IDirectMusicPerformance::PlaySegment method.

HRESULT SetStartPoint(
  MUSIC_TIME mtStart
);

Parameters

mtStart
Point within the segment at which it is to start playing. If it is less than 0 or greater than the length of the segment, the start point will be set to 0.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return DMUS_E_OUT_OF_RANGE.

Remarks

By default the start point is 0, meaning the segment starts from the beginning.

The method fails if mtStart is greater than or equal to the length of the segment. If the segment does not already have a length, IDirectMusicSegment::SetLength must be called before this method.

The method does not affect any currently playing segment states created from this segment.

The start point of a cached segment persists even if the segment is released and then reloaded. To ensure that a segment is not subsequently reloaded from the cache, call IDirectMusicLoader::ReleaseObject on it before releasing it.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicSegment::GetStartPoint, IDirectMusicSegmentState::GetStartPoint, IDirectMusicSegment::SetLength, IDirectMusicSegment::SetLoopPoints, Segment Timing


IDirectMusicSegmentState

When the IDirectMusicPerformance::PlaySegment method is called, the performance engine generates a segment state object which tracks the state of the playing segment. It also provides the application with a handle to the segment, in the form of the IDirectMusicSegmentState interface, which can be used to track the playback status of the segment, as well as to directly stop it or remove it from the performance using methods of IDirectMusicPerformance.

Segment state objects can also be created by using CoCreateInstance, or by calling IDirectMusicSegment::InitPlay directly, but segment states generated in this manner aren't very useful.

The interface has the following methods:

IDirectMusicSegmentState | GetRepeats
 | GetSeek
 | GetSegment
 | GetStartPoint
 | GetStartTime

All COM interfaces inherit the IUnknown interface methods. This interface supports the following three methods:

IUnknown | AddRef
 | QueryInterface
 | Release

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.


IDirectMusicSegmentState::GetRepeats

The IDirectMusicSegmentState::GetRepeats method returns the number of times the segment was set to repeat.

HRESULT GetRepeats(
  DWORD* pdwRepeats
);

Parameters

pdwRepeats
Address of a variable to receive the repeat count. A value of 0 indicates that the segment is to play through only once (no repeats).

Return Values

If the method succeeds, the return value is S_OK.

If the method fails, the return value may be E_POINTER.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicSegment::SetRepeats


IDirectMusicSegmentState::GetSeek

The IDirectMusicSegmentState::GetSeek method retrieves the current seek pointer in the segment state. This is the value that will be passed in the mtStart parameter of IDirectMusicTrack::Play the next time that method is called. It does not take into account looping and repeating, so that if the entire segment state repeats to the beginning, the seek pointer is reset to 0.

HRESULT GetSeek(
  MUSIC_TIME* pmtSeek
);

Parameters

pmtSeek
Address of variable to receive the current seek pointer.

Return Values

If the method succeeds, the return value is S_OK.

If the method fails, the return value may be E_POINTER.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.


IDirectMusicSegmentState::GetSegment

The IDirectMusicSegmentState::GetSegment method returns a pointer to the segment that owns this segment state.

HRESULT GetSegment(
  IDirectMusicSegment** ppSegment
);

Parameters

ppSegment
Address of a variable to receive a pointer to the IDirectMusicSegment interface.

Return Values

If the method succeeds, the return value is S_OK.

If the method fails, the return value may be E_POINTER.

Remarks

The pointer returned in ppSegment must be released by the application.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.


IDirectMusicSegmentState::GetStartPoint

The IDirectMusicSegmentState::GetStartPoint method returns the offset into the segment state at which play begins or began.

HRESULT GetStartPoint(
  MUSIC_TIME * pmtStart
);

Parameters

pmtStart
Address of a variable to receive the music time offset from the start of the segment at which the segment state initially plays.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return E_POINTER.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicSegment::SetStartPoint, IDirectMusicSegmentState::GetStartTime


IDirectMusicSegmentState::GetStartTime

The IDirectMusicSegmentState::GetStartTime method gets the music time offset maintained by this segment state. This is the time, measured from the start of the performance, at which the segment started or will start playing.

HRESULT GetStartTime(
  MUSIC_TIME* pmtStart
);

Parameters

pmtStart
Address of a variable to receive the music time offset stored in this segment state.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return one of the following error values:

DMUS_E_BUFFER_EMPTY
E_POINTER

Remarks

If the segment was started from some point other than the beginning, this method returns the time at which play started minus the offset into the segment where play started. For example, if you played a segment at tick 5000 of the performance, and started from tick 1000 within the segment, the start time of the segment state would be 4000.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicSegment::SetStartPoint, IDirectMusicSegment::GetStartPoint, IDirectMusicSegmentState::GetStartPoint


IDirectMusicStyle

The IDirectMusicStyle interface provides access to a style object. The style object provides the performance with the information it needs to play musical patterns. For an overview, see Using Styles.

Since styles usually include bands and motifs, the IDirectMusicStyle interface provides methods for accessing these objects.

The DirectMusicStyle object also supports the IDirectMusicObject and IPersistStream interfaces for loading its data.

The methods of the IDirectMusicStyle interface can be organized in the following groups:

Enumeration | EnumBand
 | EnumChordMap
 | EnumMotif
Information | GetBand
 | GetChordMap
 | GetDefaultBand
 | GetDefaultChordMap
 | GetEmbellishmentLength
 | GetMotif
 | GetTempo
 | GetTimeSignature

All COM interfaces inherit the IUnknown interface methods. This interface supports the following three methods:

IUnknown | AddRef
 | QueryInterface
 | Release

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.


IDirectMusicStyle::EnumBand

The IDirectMusicStyle::EnumBand method retrieves the name of the band with a given index value.

HRESULT EnumBand(
  DWORD dwIndex,
  WCHAR * pwszName
);

Parameters

dwIndex
Zero-based index into the style's band list.
pwszName
Address of a variable to receive the band name. This should be of size MAX_PATH.

Return Values

If the method succeeds, it returns S_OK, or S_FALSE if there is no band with the given index value, or DMUS_S_STRING_TRUNCATED if the length of the name is greater than MAX_PATH.

If it fails, the method may return one of the following error values:

DMUS_E_TYPE_UNSUPPORTED
E_POINTER

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.


IDirectMusicStyle::EnumChordMap

The IDirectMusicStyle::EnumChordMap method retrieves the name of the chordmap with the given index value.

HRESULT EnumChordMap(
  DWORD dwIndex,
  WCHAR * pwszName
);

Parameters

dwIndex
Zero-based index of the chordmap in the style's chordmap list.
pwszName
Address of a variable to receive the chordmap name. This should of size MAX_PATH.

Return Values

If the method succeeds, the return value is S_OK, S_FALSE if there is no chordmap with the given index value, or DMUS_S_STRING_TRUNCATED if the length of the name is greater than MAX_PATH.

If it fails, the method may return one of the following error values:

DMUS_E_TYPE_UNSUPPORTED
E_POINTER

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.


IDirectMusicStyle::EnumMotif

The IDirectMusicStyle::EnumMotif method retrieves the name of a motif with a given index value.

HRESULT EnumMotif(
  DWORD dwIndex,
  WCHAR * pwszName
);

Parameters

dwIndex
Zero-based index into the style's motif list.
pwszName
Address of a variable to receive the motif name. This should be of size MAX_PATH.

Return Values

If the method succeeds, the return value is S_OK, S_FALSE if there is no motif with the given index value, or DMUS_S_STRING_TRUNCATED if the length of the motif name is greater than MAX_PATH.

If it fails, the method may return E_POINTER.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicStyle::GetMotif, Using Motifs


IDirectMusicStyle::GetBand

The IDirectMusicStyle::GetBand method retrieves the named band.

HRESULT GetBand(
  WCHAR* pwszName,
  IDirectMusicBand** ppBand
);

Parameters

pwszName
The name of the band to be retrieved. This name is assigned by the author of the style.
ppBand
Address of a variable to receive a pointer to the band.

Return Values

If the method succeeds, the return value is S_OK if a band is returned, or S_FALSE if there is no band with that name.

If the method fails, the return value may be E_POINTER.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicStyle::GetDefaultBand, Using Bands


IDirectMusicStyle::GetChordMap

The IDirectMusicStyle::GetChordMap method retrieves a named chordmap.

HRESULT GetChordMap(
  WCHAR* pwszName,
  IDirectMusicChordMap** ppChordMap
);

Parameters

pwszName
Name of the chordmap to be retrieved.
ppChordMap
Address of a variable to receive a pointer to the IDirectMusicChordMap interface.

Return Values

If the method succeeds, the return value is S_OK if a chordmap is returned, or S_FALSE if there is no chordmap by that name.

If ppChordMap is not a valid pointer, the method returns E_POINTER.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicStyle::GetDefaultChordMap, Using Chordmaps


IDirectMusicStyle::GetDefaultBand

The IDirectMusicStyle::GetDefaultBand method retrieves the style's default band.

HRESULT GetDefaultBand(
  IDirectMusicBand ** ppBand
);

Parameters

ppBand
Address of a variable to receive a pointer to the default band.

Return Values

If the method succeeds, the return value is S_OK if a band is returned, or S_FALSE if the style does not have a default band.

If the method fails, the return value may be E_POINTER.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicStyle::GetBand, Using Bands


IDirectMusicStyle::GetDefaultChordMap

The IDirectMusicStyle::GetDefaultChordMap method retrieves the style's default chordmap.

HRESULT GetDefaultChordMap(
  IDirectMusicChordMap** ppChordMap
);

Parameters

ppChordMap
Address of a variable to receive a pointer to the IDirectMusicChordMap interface.

Return Values

If the method succeeds, the return value is S_OK if a chordmap is returned, or S_FALSE if the style does not have a default chordmap.

If the method fails, the return value may be E_POINTER.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicStyle::GetChordMap, Using Chordmaps


IDirectMusicStyle::GetEmbellishmentLength

The IDirectMusicStyle::GetEmbellishmentLength method finds the shortest and longest lengths for patterns of the specified embellishment type and groove level.

HRESULT GetEmbellishmentLength(
  DWORD dwType,
  DWORD dwLevel,
  DWORD* pdwMin,
  DWORD* pdwMax
);

Parameters

dwType
Embellishment type. See DMUS_COMMANDT_TYPES.
dwLevel
A groove level in the range 1 to 100. Ignored for non-groove embellishments.
pdwMin
Length of the shortest pattern of the specified type and groove level.
pdwMax
Length of the longest pattern of the specified type and groove level.

Return Values

If the method succeeds, the return value is S_OK or S_FALSE.

If the method fails, the return value may be E_POINTER.

Remarks

If there are no patterns of the specified type and groove level, the method returns S_FALSE.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.


IDirectMusicStyle::GetMotif

The IDirectMusicStyle::GetMotif method creates a segment containing the named motif.

HRESULT GetMotif(
  WCHAR* pwszName,
  IDirectMusicSegment** ppSegment
);

Parameters

pwszName
Name of the motif to be retrieved.
ppSegment
Address of a variable to receive a pointer to a segment containing the named motif.

Return Values

If the method succeeds, the return value is S_OK or S_FALSE.

If it fails, the method may return E_POINTER.

Remarks

The method searches the style's list of motifs for one whose name matches pwszName. If one is found, a segment is created containing a motif track. The track references the style as its associated style and the motif as its pattern.

If there is no motif with the given name, the method returns S_FALSE.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

Using Motifs


IDirectMusicStyle::GetTempo

The IDirectMusicStyle::GetTempo method retrieves the recommended tempo of the style.

HRESULT GetTempo(
  double* pTempo
);

Parameters

pTempo
Recommended tempo of the style.

Return Values

If the method succeeds, the return value is S_OK.

If pTempo is not a valid pointer, the method returns E_POINTER.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.


IDirectMusicStyle::GetTimeSignature

The IDirectMusicStyle::GetTimeSignature method retrieves the style's time signature.

HRESULT GetTimeSignature(
  DMUS_TIMESIGNATURE* pTimeSig
);

Parameters

pTimeSig
Address of a DMUS_TIMESIGNATURE structure to receive data.

Return Values

If the method succeeds, the return value is S_OK.

If the method fails, the return value may be E_POINTER.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.


IDirectMusicThru

The IDirectMusicThru interface supports thruing of music messages from a capture port to another port. It is obtained by calling QueryInterface on the IDirectMusicPort interface for the capture port. For an example, see the Remarks for IDirectMusicThru::ThruChannel.

The interface has the following method:

IDirectMusicThru ThruChannel

All COM interfaces inherit the IUnknown interface methods. This interface supports the following three methods:

IUnknown | AddRef
 | QueryInterface
 | Release

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicc.h.

See Also

Capturing Music


IDirectMusicThru::ThruChannel

The IDirectMusicThru::ThruChannel method establishes or breaks a thruing connection between a channel on a capture port and a channel on another port.

HRESULT ThruChannel(
  DWORD dwSourceChannelGroup,
  DWORD dwSourceChannel,
  DWORD dwDestinationChannelGroup,
  DWORD dwDestinationChannel,
  LPDIRECTMUSICPORT pDestinationPort
);

Parameters

dwSourceChannelGroup
Channel group on the capture port. In the current version of DirectMusic, this value will always be 1.
dwSourceChannel
Source channel.
dwDestinationChannelGroup
Channel group on the destination port.
dwDestinationChannel
Destination channel.
pDestinationPort
IDirectMusicPort for the destination channel. Set this value to NULL in order to break an existing thruing connection.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return one of the following error values:

E_NOTIMPL
E_INVALIDARG
DMUS_E_PORT_NOT_RENDER

Remarks

Thruing to the Microsoft Software Synthesizer is not recommended. Thruing is done as soon as possible upon reception of the incoming MIDI events. Because of the comparatively high latency of the software synthesizer (compared with a hardware port), and the fact that it renders blocks of audio data at a time, each event is delayed by a small, essentially random amount of time before it actually plays. This random offset shows up as jitter in the playback of the data. Latency of other devices (such as an MPU-401 port) is small enough that the jitter does not occur.

If an application needs to thru to the software synthesizer, it should add a small offset to the incoming note event time stamps to compensate for the rendering latency of the synthesizer.

The following example function obtains the IDirectMusicThru interface and establishes a thru connection between all channels on group 1 of the capture port and the equivalent channels on a destination port.

HRESULT SetupOneToOneThru(
    IDirectMusicPort *pCapturePort,
    IDirectMusicPort *pRenderPort)
{
    HRESULT hr;
    IDirectMusicThru *pThru;

    hr = pCapturePort->QueryInterface(IID_IDirectMusicThru,
            (void**)&pThru);
    if (FAILED(hr))
        return hr;

    for (DWORD dwChannel = 0; dwChannel < 16; dwChannel++)
    {
        hr = pThru->ThruChannel(1, dwChannel,
            1, dwChannel, pRenderPort);
        if (FAILED(hr))
            break;
    }

    pThru->Release();
    return hr;
}

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicc.h.


IDirectMusicTool

Tools are objects that implement the IDirectMusicTool interface. They are used inside graphs (see IDirectMusicGraph). When a message is sent using IDirectMusicPerformance::SendPMsg, the message flows through tools inside graphs. The tools can modify the message, make additional messages, remove messages, and so on.

This interface is of most interest to developers who want to create their own tools.

The methods of the IDirectMusicTool interface can be organized in the following groups:

Initialization | Init
Message management | Flush
 | GetMediaTypeArraySize
 | GetMediaTypes
 | GetMsgDeliveryType
 | ProcessPMsg

All COM interfaces inherit the IUnknown interface methods. This interface supports the following three methods:

IUnknown | AddRef
 | QueryInterface
 | Release

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

Overview of DirectMusic Data Flow, Message Creation and Delivery, DirectMusic Tools


IDirectMusicTool::Flush

The IDirectMusicTool::Flush method is called for each message in the queue when the performance stops. The tool can use the method to do whatever is necessary to flush the message. For instance, the output tool uses this method to ensure that any pending note-off messages are immediately processed.

HRESULT Flush(
  IDirectMusicPerformance* pPerf,
  DMUS_PMSG* pPMSG,
  REFERENCE_TIME rtTime
);

Parameters

pPerf
Pointer to the IDirectMusicPerformance interface.
pPMSG
Pointer to the message to flush.
rtTime
Time at which to flush.

Return Values

Return values are determined by the implementation. If the method succeeds, the return value should be one of the following:

DMUS_S_REQUEUE
DMUS_S_FREE
S_OK

If it fails, the method may return E_POINTER.

Remarks

The message will have DMUS_PMSGF_TOOL_FLUSH set in its dwFlags member. See DMUS_PMSG.

If the method returns DMUS_S_REQUEUE, the tool wants the message to be requeued. This allows the tool to put a new timestamp and parameters on the message and requeue it, or to requeue the message with a different delivery type.

If the return value is DMUS_S_FREE, the tool wants the message freed automatically, and does not wish to requeue the message.

If S_OK is returned, the tool does not wish the message to be freed automatically. Perhaps the tool is holding onto the message for some reason, or has freed it itself.

Care must be taken not to create a circular reference to the performance represented by pPerf. For more information, see DirectMusic Tools.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.


IDirectMusicTool::GetMediaTypeArraySize

The IDirectMusicTool::GetMediaTypeArraySize method retrieves the size of the array that must be passed into the IDirectMusicTool::GetMediaTypes method. A return value of 0 indicates that the tool handles all types, and it is unnecessary to call GetMediaTypes.

HRESULT GetMediaTypeArraySize(
  DWORD* pdwNumElements
);

Parameters

pdwNumElements
Address of a variable to receive the number of media types. If 0 is returned in this field, all types are supported.

Return Values

Return values are determined by the implementation. If successful, the method should return S_OK. If it fails, the method may return E_POINTER.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.


IDirectMusicTool::GetMediaTypes

The IDirectMusicTool::GetMediaTypes method retrieves a list of the type of messages this tool supports.

HRESULT GetMediaTypes(
  DWORD** padwMediaTypes,
  DWORD dwNumElements
);

Parameters

padwMediaTypes
Address of a pointer to an array of DWORDs. The method fills this array with the media types supported by this tool. For media types, see DMUS_PMSGT_TYPES.
dwNumElements
Number of elements in the array padwMediaTypes. This value should be equal to the number returned by the IDirectMusicTool::GetMediaTypeArraySize method. If dwNumElements is less than this number, the method can't return all of the message types that are supported. If it is greater than this number, the extra elements in the array should be set to 0.

Return Values

Return values are determined by the implementation. If successful, the method should return S_OK, or S_FALSE if the method couldn't fill in all values because dwNumElements was too small. If it fails, the method may return one of the following error values:

E_POINTER
E_INVALIDARG
E_NOTIMPL

Remarks

If the method returns E_NOTIMPL, the tool processes all media types.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.


IDirectMusicTool::GetMsgDeliveryType

The IDirectMusicTool::GetMsgDeliveryType method retrieves the tool's delivery type, which determines when messages are to be delivered to the tool.

HRESULT GetMsgDeliveryType(
  DWORD* pdwDeliveryType
);

Parameters

pdwDeliveryType
Address of a variable to receive the delivery type. The returned value must be DMUS_PMSGF_TOOL_IMMEDIATE, DMUS_PMSGF_TOOL_QUEUE, or DMUS_PMSGF_TOOL_ATTIME. An unrecognized value in *pdwDeliveryType will be treated as DMUS_PMSGF_TOOL_IMMEDIATE by the graph.

Return Values

Return values are determined by the implementation. If successful, the method should return S_OK. If it fails, the method may return E_POINTER.

Remarks

For an overview of the delivery mechanism, see Message Creation and Delivery.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.


IDirectMusicTool::Init

The IDirectMusicTool::Init method is called when the tool is inserted into the graph, giving the tool an opportunity to perform any necessary initialization.

HRESULT Init(
  IDirectMusicGraph* pGraph
);

Parameters

pGraph
Pointer to the calling graph.

Return Values

Return values are determined by the implementation. If successful, the method should return S_OK. If it fails, the method may return one of the following error values:

E_FAIL
E_NOTIMPL

Remarks

Because a tool can be inserted into more than one graph, this method must be able to deal gracefully with multiple calls.

Care must be taken not to create a circular reference to the graph represented by pGraph. For more information, see DirectMusic Tools.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicGraph::InsertTool


IDirectMusicTool::ProcessPMsg

The IDirectMusicTool::ProcessPMsg method performs the main task of the tool. It is called from inside the performance's real-time thread for all messages that match the types specified by IDirectMusicTool::GetMediaTypes.

HRESULT ProcessPMsg(
  IDirectMusicPerformance* pPerf,
  DMUS_PMSG* pPMSG
);

Parameters

pPerf
Pointer to the performance.
pPMSG
Pointer to the message to process.

Return Values

Return values are determined by the implementation. If the method succeeds, the return value should be one of the following:

DMUS_S_REQUEUE
DMUS_S_FREE
S_OK

If it fails, the method may return E_POINTER.

Remarks

If the method returns DMUS_S_REQUEUE, the tool wants the message to be requeued. This allows the tool to put a new timestamp and parameters on the message and requeue it, or to requeue the message with a different delivery type.

If the return value is DMUS_S_FREE, the tool wants the message freed automatically, and does not wish to requeue the message.

If S_OK is returned, the tool does not want the message to be freed automatically. Perhaps the tool is holding onto the message for some reason, or has freed it itself.

Tools should not perform time-consuming activities, because doing so can severely affect overall performance. Also, care must be taken not to create a circular reference to the performance represented by pPerf. For more information, see DirectMusic Tools.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicPerformance::SendPMsg, Messages, Message Creation and Delivery


IDirectMusicTrack

The IDirectMusicTrack interface represents a track object. Almost everything that has to do with the definition of a segment is stored in its tracks. The track mechanism allows segments to be infinitely extensible, and the segment doesn't have to have any knowledge about any of the music and audio technologies that it employs.

If you plan to install your own music playback mechanism into DirectMusic, you will need to create a DirectMusicTrack object to represent it. Otherwise, the methods of this interface will typically not be called directly from the application.

Note When implementing methods of the IDirectMusicTrack interface, you must take care not to hold onto references to objects passed in. For example, if IDirectMusicTrack::Init adds a reference to the IDirectMusicSegment it receives as a parameter, you must ensure that this reference is released.

The IDirectMusicTrack interface has the following methods:

Initialization | Init
Playback | EndPlay
 | InitPlay
 | Play
Notification | AddNotificationType
 | RemoveNotificationType
Parameters | GetParam
 | IsParamSupported
 | SetParam
Miscellaneous | Clone

All COM interfaces inherit the IUnknown interface methods. This interface supports the following three methods:

IUnknown | AddRef
 | QueryInterface
 | Release

The DirectMusicTrack object also supports the IDirectMusicObject and IPersistStream interfaces for loading its data.

The following table shows which methods are supported by the standard track types. For a general description of the standard types, see Tracks.

Track | IDirectMusicTrack methods |  | IPersistStream methods
Band (CLSID_DirectMusicBandTrack)
 | AddNotificationType | No | IsDirty | Yes
 | Clone | Yes | GetSizeMax | No
 | EndPlay | Yes | Load | Yes
 | GetParam | No | Save | Yes
 | Init | Yes |  |
 | InitPlay | Yes
 | IsParamSupported | Yes
 | Play | Yes
 | SetParam | Yes
 | RemoveNotificationType | No
Chord (CLSID_DirectMusicChordTrack)
 | AddNotificationType | Yes | IsDirty | Yes
 | Clone | Yes | GetSizeMax | No
 | EndPlay | Yes | Load | Yes
 | GetParam | Yes | Save | Yes
 | Init | Yes |  |
 | InitPlay | Yes
 | IsParamSupported | Yes
 | Play | Yes
 | SetParam | Yes
 | RemoveNotificationType | Yes
Chordmap (CLSID_DirectMusicChordMapTrack)
 | AddNotificationType | No | IsDirty | No
 | Clone | Yes | GetSizeMax | No
 | EndPlay | Yes* | Load | Yes
 | GetParam | Yes | Save | No
 | Init | Yes* |  |
 | InitPlay | Yes*
 | IsParamSupported | Yes
 | Play | Yes*
 | SetParam | Yes
 | RemoveNotificationType | No
Command (CLSID_DirectMusicCommandTrack)
 | AddNotificationType | Yes | IsDirty | Yes
 | Clone | Yes | GetSizeMax | No
 | EndPlay | Yes | Load | Yes
 | GetParam | Yes | Save | Yes
 | Init | Yes |  |
 | InitPlay | Yes
 | IsParamSupported | Yes
 | Play | Yes
 | SetParam | Yes
 | RemoveNotificationType | Yes
Motif (CLSID_DirectMusicMotifTrack)
 | AddNotificationType | Yes | IsDirty | No
 | Clone | Yes | GetSizeMax | No
 | EndPlay | Yes | Load | No
 | GetParam | No | Save | No
 | Init | Yes |  |
 | InitPlay | Yes
 | IsParamSupported | Yes
 | Play | Yes
 | SetParam | Yes
 | RemoveNotificationType | Yes
Mute (CLSID_DirectMusicMuteTrack)
 | AddNotificationType | No | IsDirty | Yes
 | Clone | Yes | GetSizeMax | No
 | EndPlay | Yes* | Load | Yes
 | GetParam | Yes | Save | Yes
 | Init | Yes* |  |
 | InitPlay | Yes*
 | IsParamSupported | Yes
 | Play | Yes*
 | SetParam | Yes
 | RemoveNotificationType | No
Sequence (CLSID_DirectMusicSeqTrack)
 | AddNotificationType | No | IsDirty | No
 | Clone | Yes | GetSizeMax | No
 | EndPlay | Yes | Load | Yes
 | GetParam | No | Save | No
 | Init | Yes |  |
 | InitPlay | Yes
 | IsParamSupported | No
 | Play | Yes
 | SetParam | No
 | RemoveNotificationType | No
Signpost (CLSID_DirectMusicSignPostTrack)
 | AddNotificationType | No | IsDirty | Yes
 | Clone | Yes | GetSizeMax | No
 | EndPlay | Yes* | Load | Yes
 | GetParam | No | Save | Yes
 | Init | Yes* |  |
 | InitPlay | Yes*
 | IsParamSupported | No
 | Play | Yes*
 | SetParam | No
 | RemoveNotificationType | No
Style (CLSID_DirectMusicStyleTrack)
 | AddNotificationType | Yes | IsDirty | No
 | Clone | Yes | GetSizeMax | No
 | EndPlay | Yes | Load | Yes
 | GetParam | Yes | Save | No
 | Init | Yes |  |
 | InitPlay | Yes
 | IsParamSupported | Yes
 | Play | Yes
 | SetParam | Yes
 | RemoveNotificationType | Yes
SysEx (CLSID_DirectMusicSysExTrack)
 | AddNotificationType | No | IsDirty | No
 | Clone | Yes | GetSizeMax | No
 | EndPlay | Yes | Load | Yes
 | GetParam | No | Save | No
 | Init | Yes |  |
 | InitPlay | Yes
 | IsParamSupported | No
 | Play | Yes
 | SetParam | No
 | RemoveNotificationType | No
Tempo (CLSID_DirectMusicTempoTrack)
 | AddNotificationType | No | IsDirty | No
 | Clone | Yes | GetSizeMax | No
 | EndPlay | Yes | Load | Yes
 | GetParam | Yes | Save | No
 | Init | Yes |  |
 | InitPlay | Yes
 | IsParamSupported | Yes
 | Play | Yes
 | SetParam | Yes
 | RemoveNotificationType | No
Time Signature** (CLSID_DirectMusicTimeSigTrack)
 | AddNotificationType | Yes | IsDirty | No
 | Clone | Yes | GetSizeMax | No
 | EndPlay | Yes | Load | Yes
 | GetParam | Yes | Save | No
 | Init | Yes |  |
 | InitPlay | Yes
 | IsParamSupported | Yes
 | Play | Yes
 | SetParam | Yes
 | RemoveNotificationType | Yes

Notes * The method returns a value other than E_NOTIMPL but does not do anything else.

** The time signature track exists in imported MIDI files and DirectMusic Producer segments specifically created with one. In most cases the style track implements the time signature track's functionality, so it is not necessary for a segment that contains a style track to contain a time signature track as well.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

Tracks, Setting and Retrieving Track Parameters


IDirectMusicTrack::AddNotificationType

The IDirectMusicTrack::AddNotificationType method enables event notification for a track. It is similar to and called from the IDirectMusicSegment::AddNotificationType method.

HRESULT AddNotificationType(
  REFGUID rguidNotificationType
);

Parameters

rguidNotificationType
Address of (C) or reference to (C++) the identifier of the notification type to add. For the defined types, see DMUS_NOTIFICATION_PMSG. Applications can also define their own types for custom tracks.

Return Values

If the method succeeds, the return value is S_OK, or S_FALSE if the track does not support the notification type.

If the track does not support notifications, the method returns E_NOTIMPL.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicTrack::RemoveNotificationType, Notification and Event Handling


IDirectMusicTrack::Clone

The IDirectMusicTrack::Clone method makes a copy of a track.

HRESULT Clone(
  MUSIC_TIME mtStart,
  MUSIC_TIME mtEnd,
  IDirectMusicTrack** ppTrack
 );

Parameters

mtStart
The start of the part to clone. It should be 0 or greater, and less than the length of the track.
mtEnd
The end of the part to clone. It should be greater than mtStart and less than the length of the track.
ppTrack
Address of a variable to receive a pointer to the created track, if successful.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return one of the following error values:

E_FAIL
E_INVALIDARG
E_OUTOFMEMORY
E_POINTER

Remarks

It is the caller's responsibility to call Release when finished with the track.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.


IDirectMusicTrack::EndPlay

The IDirectMusicTrack::EndPlay method is called when the object that originally called IDirectMusicTrack::InitPlay is destroyed.

HRESULT EndPlay(
  void * pStateData
);

Parameters

pStateData
Pointer to the state data returned from IDirectMusicTrack::InitPlay. This data should be freed in the EndPlay method.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return E_POINTER.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.


IDirectMusicTrack::GetParam

The IDirectMusicTrack::GetParam method retrieves data from a track.

HRESULT GetParam(
  REFGUID rguidType,
  MUSIC_TIME mtTime,
  MUSIC_TIME* pmtNext,
  void* pParam
);

Parameters

rguidType
Reference to (C++) or address of (C) the identifier of the type of data to obtain. See Track Parameter Types.
mtTime
Time, in track time, from which to obtain the data.
pmtNext
Address of a variable to receive the track time (relative to the current time) until which the data is valid. If this returns a value of 0, it means either that the data will always be valid, or that it is unknown when it will become invalid. If this information is not needed, pmtNext can be set to NULL.
pParam
Address of an allocated structure in which the data is to be returned. The structure must be of the appropriate kind and size for the data type identified by rguidType.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return one of the following error values:

DMUS_E_NOT_FOUND
DMUS_E_NOT_INIT
DMUS_E_TYPE_DISABLED
DMUS_E_GET_UNSUPPORTED
E_POINTER

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicTrack::SetParam, IDirectMusicTrack::IsParamSupported, IDirectMusicPerformance::GetParam, IDirectMusicSegment::GetParam, Music Parameters


IDirectMusicTrack::Init

The IDirectMusicTrack::Init method is called by a segment when a track is added and performs any necessary initialization.

HRESULT Init(
  IDirectMusicSegment* pSegment
);

Parameters

pSegment
Pointer to the segment to which this track belongs.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return one of the following error values:

DMUS_E_NOT_INIT
E_OUTOFMEMORY
E_POINTER

Remarks

If the track plays messages, it should call IDirectMusicSegment::SetPChannelsUsed in the Init method.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.


IDirectMusicTrack::InitPlay

The IDirectMusicTrack::InitPlay method is called when a track is ready to start playing. It returns a pointer to state data, which is sent into IDirectMusicTrack::Play and IDirectMusicTrack::EndPlay.

HRESULT InitPlay(
  IDirectMusicSegmentState* pSegmentState,
  IDirectMusicPerformance* pPerformance,
  void** ppStateData,
  DWORD dwVirtualTrackID,
  DWORD dwFlags
);

Parameters

pSegmentState
Pointer to the calling IDirectMusicSegmentState.
pPerformance
Pointer to the calling IDirectMusicPerformance.
ppStateData
Address of a variable to receive a pointer to state information. The format and use of the data is specific to the track. The data should be created in the InitPlay method and freed in the IDirectMusicTrack::EndPlay method. The pointer is passed to the IDirectMusicTrack::Play method.
dwVirtualTrackID
Virtual track ID assigned to this track instance.
dwFlags
DMUS_SEGF_FLAGS that control the track's behavior. See Remarks.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return one of the following error values:

DMUS_E_NOT_INIT
E_OUTOFMEMORY
E_POINTER

Remarks

It is unnecessary for the track to store the pSegmentState, pPerformance, or dwTrackID parameters, because they are also sent into IDirectMusicTrack::Play.

The dwFlags parameter passes the flags that were handed to the performance in the call to IDirectMusicPerformance::PlaySegment. The track makes decisions on how it should perform based on the DMUS_SEGF_CONTROL and DMUS_SEGF_SECONDARY flags. For example, the tempo track automatically plays the tempo changes only if it is part of a primary segment or a secondary control segment (DMUS_SEGF_SECONDARY is not set, or DMUS_SEGF_CONTROL is set).

A track can return NULL in ppStateData.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.


IDirectMusicTrack::IsParamSupported

The IDirectMusicTrack::IsParamSupported method determines whether the track supports a given data type in the IDirectMusicTrack::GetParam and IDirectMusicTrack::SetParam methods.

HRESULT IsParamSupported(
  REFGUID rguidType
);

Parameters

rguidType
Reference to (C++) or address of (C) the identifier of the type of data. See Track Parameter Types.

Return Values

If the method succeeds and the type is supported, the return value is S_OK.

If it fails, the method may return one of the following error values:

DMUS_E_TYPE_DISABLED
DMUS_E_TYPE_UNSUPPORTED
E_POINTER
E_NOTIMPL

Remarks

If a message type has been disabled by using one of the SetParam methods (see Disabling and Enabling Messages on a Track), the IDirectMusicTrack::IsParamSupported method returns DMUS_E_TYPE_DISABLED when passed the corresponding parameter type (either GUID_TempoParam or GUID_TimeSignature).

The method also returns DMUS_E_TYPE_DISABLED if passed GUID_DisableTempo when that message type has already been disabled, or if passed GUID_EnableTempo when that message type is currently enabled. The same is true for GUID_DisableTimeSig and GUID_EnableTimeSig.

The method returns DMUS_E_TYPE_UNSUPPORTED when the track does not support the message type referred to by a GUID_EnableTempo, GUID_EnableTimeSig, GUID_DisableTempo, or GUID_DisableTimeSig parameter type.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicTrack::GetParam, IDirectMusicTrack::SetParam, Music Parameters


IDirectMusicTrack::Play

The IDirectMusicTrack::Play method causes the track to play. It performs any work the track must do when the segment is played, such as creating and sending messages.

HRESULT Play(
  void* pStateData,
  MUSIC_TIME mtStart,
  MUSIC_TIME mtEnd,
  MUSIC_TIME mtOffset
  DWORD dwFlags,
  IDirectMusicPerformance* pPerf,
  IDirectMusicSegmentState* pSegSt,
  DWORD dwVirtualID
);

Parameters

pStateData
State data pointer, from the IDirectMusicTrack::InitPlay method. The format and use of the data is specific to the track.
mtStart
Start time.
mtEnd
End time.
mtOffset
Offset to add to all messages sent to IDirectMusicPerformance::SendPMsg.
dwFlags
Flags that indicate the state of this call. See DMUS_TRACKF_FLAGS. A value of 0 indicates that this call to Play continues playback from the previous call.
pPerf
The performance used to allocate and send the message.
pSegSt
The segment state this track belongs to. The IDirectMusicSegmentState::QueryInterface method can be called to obtain an IDirectMusicGraph interface—in order to call IDirectMusicGraph::StampPMsg, for instance.
dwVirtualID
Virtual Identifier of the track. This value must be put in the dwVirtualTrackID member of any message (see DMUS_PMSG) that will be sent by IDirectMusicPerformance::SendPMsg.

Return Values

If the method succeeds, the return value may be S_OK or DMUS_S_END.

If it fails, the method may return one of the following error values:

DMUS_E_NOT_INIT
E_POINTER

Remarks

If the track is empty, the method returns DMUS_S_END.

Tracks generate messages in a medium-priority thread. You can call time-consuming functions, such as code to stream data from a file, from within a track's Play method. However, be sure to follow the guidelines for safe multithreading.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.


IDirectMusicTrack::RemoveNotificationType

The IDirectMusicTrack::RemoveNotificationType method removes an event notification from a track. It is similar to and called from the IDirectMusicSegment::RemoveNotificationType method.

HRESULT RemoveNotificationType(
  REFGUID rguidNotificationType
);

Parameters

rguidNotificationType
Address of (C) or reference to (C++) the identifier of the notification type to remove. For the defined types, see DMUS_NOTIFICATION_PMSG.

Return Values

If the method succeeds, the return value is S_OK, or S_FALSE if the track does not support the notification type.

If the track does not support notifications, the method returns E_NOTIMPL.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicTrack::AddNotificationType, Notification and Event Handling


IDirectMusicTrack::SetParam

The IDirectMusicTrack::SetParam method sets data on a track.

HRESULT SetParam(
  REFGUID rguidType,
  MUSIC_TIME mtTime,
  void* pParam
);

Parameters

rguidType
Reference to (C++) or address of (C) the identifier of the type of data to set. See Track Parameter Types.
mtTime
Time, in track time, at which to set the data.
pParam
Address of structure containing the data, or NULL if no data is required. The structure must be of the appropriate kind and size for the data type identified by rguidType.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method may return one of the following error values:

DMUS_E_SET_UNSUPPORTED
DMUS_E_TYPE_DISABLED
E_OUTOFMEMORY
E_POINTER

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicTrack::GetParam, IDirectMusicTrack::IsParamSupported, IDirectMusicPerformance::SetParam, IDirectMusicSegment::SetParam, Setting and Retrieving Track Parameters


IKsControl

The IKsControl interface is used to get, set, or query the support of properties, events, and methods. This interface is part of the Windows Driver Model kernel streaming architecture, but is also used by DirectMusic to expose properties of DirectMusic ports. To retrieve this interface, call the IDirectMusicPort::QueryInterface method with IID_IKsControl in the riid parameter.

Routing of the property item request to the port varies depending on the port implementation. No properties are supported by ports which represent DirectMusic emulation on top of the Win32 handle-based multimedia calls (midiOut and midiIn functions).

Property item requests to a port which represents a pluggable software synthesizer are answered totally in user mode. The topology of this type of port is a synthesizer (represented by an IDirectMusicSynth interface) connected to a sink node (an IDirectMusicSynthSink interface). The property request will be given first to the synthesizer node, and then to the sink node if it is not recognized by the synthesizer.

The interface has the following methods. At present, only KsProperty is supported by DirectMusic.

IKsControl | KsProperty
 | KsEvent
 | KsMethod

All COM interfaces inherit the IUnknown interface methods. This interface supports the following three methods:

IUnknown | AddRef
 | QueryInterface
 | Release

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmksctrl.h.

See Also

Port Property Sets


IKsControl::KsProperty

The IKsControl::KsProperty method gets or sets the value of a property. For an overview, see Port Property Sets.

HRESULT KsProperty(
  PKSPROPERTY pProperty,
  ULONG ulPropertyLength,
  LPVOID pvPropertyData,
  ULONG ulDataLength,
  PULONG pulBytesReturned
);

Parameters

pProperty
Pointer to a KSPROPERTY structure that gives the property set, item, and operation to perform. If this property contains instance data, then that data should reside in memory immediately following the structure.
ulPropertyLength
The length of the memory pointed to by pProperty, including any instance data.
pvPropertyData
For a set operation, a memory buffer containing data representing the new value of the property. For a get operation, a memory buffer big enough to hold the value of the property. For a basic support query, a pointer to a buffer at least the size of a DWORD.
ulDataLength
The length of the buffer pointed to by pvPropertyData.
pulBytesReturned
On a KSPROPERTY_TYPE_GET or KSPROPERTY_TYPE_BASICSUPPORT call, the number of bytes returned in pvPropertyData by the port.

Return Values

If the method succeeds, it returns S_OK.

If the it fails, the method may return one of the following error values:

E_FAIL
E_INVALIDARG
E_NOTIMPL
E_OUTOFMEMORY
E_POINTER
DMUS_E_UNKNOWN_PROPERTY

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmksctrl.h.

See Also

Port Property Sets


IReferenceClock

The IReferenceClock interface represents a system reference clock. The DirectMusic master clock and a port's latency clock implement this interface.

The interface has the following methods:

IReferenceClock | GetTime
 | AdviseTime
 | AdvisePeriodic
 | Unadvise

All COM interfaces inherit the IUnknown interface methods. This interface supports the following three methods:

IUnknown | AddRef
 | QueryInterface
 | Release

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicc.h.

See Also

IDirectMusic::GetMasterClock, IDirectMusicPort::GetLatencyClock, Timing


IReferenceClock::AdvisePeriodic

The IReferenceClock::AdvisePeriodic method requests an asynchronous, periodic notification that a duration has elapsed.

HRESULT AdvisePeriodic(
  REFERENCE_TIME rtStartTime,
  REFERENCE_TIME rtPeriodTime,
  HSEMAPHORE hSemaphore,
  DWORD * pdwAdviseCookie
);

Parameters

rtStartTime
Time the notification should begin.
rtPeriodTime
Duration between notifications.
hSemaphore
Handle of a semaphore through which to advise.
pdwAdviseCookie
Address of a variable to receive the identifier of the request. This is used to identify this call to AdvisePeriodic in the future—for example, to cancel it.

Return Values

Return values are determined by the implementation. If the method succeeds, it returns S_OK. If it fails, it may return one of the following error values:

E_FAIL
E_POINTER
E_INVALIDARG
E_NOTIMPL

Remarks

When the time indicated by rtStartTime is reached, the semaphore whose handle is set as hSemaphore is released. Thereafter, the semaphore will be released repetitively with a period of rtPeriodTime.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicc.h.

See Also

IReferenceClock::Unadvise


IReferenceClock::AdviseTime

The IReferenceClock::AdviseTime method requests an asynchronous notification that a duration has elapsed.

HRESULT AdviseTime(
  REFERENCE_TIME rtBaseTime,
  REFERENCE_TIME rtStreamTime,
  HEVENT hEvent,
  DWORD * pdwAdviseCookie
);

Parameters

rtBaseTime
Base reference time.
rtStreamTime
Stream offset time.
hEvent
Handle of an event through which to advise.
pdwAdviseCookie
Address of a variable to receive the identifier of the request. This is used to identify this call to AdviseTime in the future—for example, to cancel it.

Return Values

Return values are determined by the implementation. If the method succeeds, it returns S_OK. If it fails, it may return one of the following error values:

E_FAIL
E_POINTER
E_INVALIDARG
E_NOTIMPL

Remarks

When the time rtBaseTime + rtStreamTime is reached, the event whose handle is hEvent will be set. If the time has already passed, the event will be set immediately.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicc.h.

See Also

IReferenceClock::Unadvise


IReferenceClock::GetTime

The IReferenceClock::GetTime method retrieves the current time.

HRESULT GetTime(
  REFERENCE_TIME * pTime
);

Parameters

pTime
Address of a variable to receive the current time.

Return Values

Return values are determined by the implementation. If the method succeeds, it returns S_OK. If it fails, it may return one of the following error values:

E_FAIL
E_POINTER
E_INVALIDARG
E_NOTIMPL

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicc.h.


IReferenceClock::Unadvise

The IReferenceClock::Unadvise method cancels a request for notification.

HRESULT Unadvise(
  DWORD dwAdviseCookie
);

Parameters

dwAdviseCookie
Identifier of the request that is to be canceled, as set in the IReferenceClock::AdviseTime or IReferenceClock::AdvisePeriodic method.

Return Values

Return values are determined by the implementation. If the method succeeds, it returns S_OK. If it fails, it may return one of the following error values:

E_FAIL
E_POINTER
E_INVALIDARG
E_NOTIMPL

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicc.h.


Messages

DirectMusic message structures are all based on DMUS_PMSG. Because C does not support inheritance, the members of this structure are included in each derived structure as the DMUS_PMSG_PART macro.

For an overview of messages, see DirectMusic Messages.

This section contains information about the following structures used to contain message information:

  • DMUS_PMSG
  • DMUS_CHANNEL_PRIORITY_PMSG
  • DMUS_CURVE_PMSG
  • DMUS_MIDI_PMSG
  • DMUS_NOTE_PMSG
  • DMUS_NOTIFICATION_PMSG
  • DMUS_PATCH_PMSG
  • DMUS_SYSEX_PMSG
  • DMUS_TEMPO_PMSG
  • DMUS_TIMESIG_PMSG
  • DMUS_TRANSPOSE_PMSG

See Also

IDirectMusicPerformance::AllocPMsg, IDirectMusicPerformance::SendPMsg, IDirectMusicPerformance::FreePMsg, IDirectMusicTool::ProcessPMsg


DMUS_PMSG

The DMUS_PMSG structure contains information common to all DirectMusic messages. Because C does not support inheritance, the members of this structure are included in all message types (including DMUS_PMSG itself) by the inclusion of the DMUS_PMSG_PART macro, which expands to the syntax shown here.

typedef struct DMUS_PMSG {
    DWORD              dwSize;
    REFERENCE_TIME     rtTime;
    MUSIC_TIME         mtTime;
    DWORD              dwFlags;
    DWORD              dwPChannel;
    DWORD              dwVirtualTrackID;
    IDirectMusicTool*  pTool;
    IDirectMusicGraph* pGraph;
    DWORD              dwType;
    DWORD              dwVoiceID;
    DWORD              dwGroupID;
    IUnknown*          punkUser;
} DMUS_PMSG;

Members

dwSize
Size of the structure, in bytes.
rtTime
Real time (in 100 nanosecond increments) at which the message is to be played, modified by dwFlags.
mtTime
Music time at which the message is to be played, modified by dwFlags.
dwFlags
Various bits (see DMUS_PMSGF_FLAGS and DMUS_TIME_RESOLVE_FLAGS).
dwPChannel
Performance channel (PChannel). The port, channel group, and MIDI channel can be derived from this value by using the IDirectMusicPerformance::PChannelInfo method.
dwVirtualTrackID
Identifier of the track.
pTool
Tool interface pointer.
pGraph
Tool graph interface pointer.
dwType
Message type (see DMUS_PMSGT_TYPES).
dwVoiceID
Reserved for future use. This value is always 0.
dwGroupID
Identifier of the track group or groups the message belongs to. (Tracks are assigned to groups in the IDirectMusicSegment::InsertTrack method.)
punkUser
User COM pointer. This pointer is always released when the message is freed. If the application wishes to retain the object, it should call AddRef before the message is freed.

Remarks

The DMUS_PMSG structure is used by itself for messages containing the following values in the dwType member:

DMUS_PMSGT_STOP
Sending a message of this type stops the performance at the indicated time.
DMUS_PMSGT_DIRTY
When a control segment starts or ends, all tools in the segment and performance graphs receive a message of this type, indicating that if they cache data from GetParam calls, they must call GetParam again to refresh their data. Tools that want to receive this message type must indicate their desire through a call to IDirectMusicTool::GetMediaTypes. Also, note that tools in the performance graph will receive one copy of the message for each segment in the performance. Such tools can safely ignore the extra messages with the same time stamp.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicPerformance::SendPMsg


DMUS_CHANNEL_PRIORITY_PMSG

The DMUS_CHANNEL_PRIORITY_PMSG message structure contains data about a channel priority change.

typedef struct _DMUS_CHANNEL_PRIORITY_PMSG {
    DMUS_PMSG_PART
    DWORD dwChannelPriority;
} DMUS_CHANNEL_PRIORITY_PMSG;

Members

DMUS_PMSG_PART
Macro for common message members. See DMUS_PMSG.
dwChannelPriority
The priority of the channel. For a list of defined values, see the remarks for IDirectMusicPort::GetChannelPriority.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicPort::SetChannelPriority, IDirectMusicPerformance::SendPMsg


DMUS_CURVE_PMSG

DMUS_CURVE_PMSG is a message structure that represents a curve (for example, a sequence of continuous controller events).

typedef struct DMUS_CURVE_PMSG {
    DMUS_PMSG_PART
    MUSIC_TIME mtDuration;
    MUSIC_TIME mtOriginalStart;
    MUSIC_TIME mtResetDuration;
    short      nStartValue;
    short      nEndValue;
    short      nResetValue;
    WORD       wMeasure;
    short      nOffset;
    BYTE       bBeat;
    BYTE       bGrid;
    BYTE       bType;
    BYTE       bCurveShape;
    BYTE       bCCData;
    BYTE       bFlags;
} DMUS_CURVE_PMSG;

Members

DMUS_PMSG_PART
Macro for common message members. See DMUS_PMSG.
mtDuration
How long the curve lasts.
mtOriginalStart
Must be set to either zero when this message is created or to the original time of the curve.
mtResetDuration
How long after the curve is finished until the reset value is set.
nStartValue
The curve's start value.
nEndValue
The curve's end value.
nResetValue
Curve's reset value, set after mtResetDuration or upon a flush or invalidation.
wMeasure
Measure in which this curve occurs.
nOffset
Offset from grid at which this curve occurs, in music time.
bBeat
Beat (in measure) at which this curve occurs.
bGrid
Grid offset from beat at which this curve occurs.
bType
Type of curve. This can be one of the following values:

DMUS_CURVET_PBCURVE
DMUS_CURVET_CCCURVE
DMUS_CURVET_MATCURVE
DMUS_CURVET_PATCURVE

bCurveShape
Shape of curve. This can be one of the following values:

DMUS_CURVES_LINEAR
DMUS_CURVES_INSTANT
DMUS_CURVES_EXP
DMUS_CURVES_LOG
DMUS_CURVES_SINE

bCCData
CC number if this is a control change type.
bFlags
Set to DMUS_CURVE_RESET if the nResetValue must be set when the time is reached or an invalidation occurs because of a transition. If 0, the curve stays permanently at the new value. All other bits are reserved.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicPerformance::SendPMsg


DMUS_MIDI_PMSG

The DMUS_MIDI_PMSG structure contains data for a standard MIDI message not represented by another message type, such as a control change or pitch bend.

typedef struct DMUS_MIDI_PMSGG {
    DMUS_PMSG_PART
    BYTE  bStatus;
    BYTE  bByte1;
    BYTE  bByte2;
    BYTE  bPad[1];
} DMUS_MIDI_PMSG;

Members

DMUS_PMSG_PART
Macro for common message members. See DMUS_PMSG.
bStatus
Standard MIDI status byte.
bByte1
First byte of the MIDI message. Ignored for MIDI messages that don't require it.
bByte2
Second byte of the MIDI message. Ignored for MIDI messages that don't require it.
bPad
Padding to word boundary.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

MIDI Messages, IDirectMusicPerformance::SendPMsg


DMUS_NOTE_PMSG

The DMUS_NOTE_PMSG structure contains data for a music note event.

typedef struct DMUS_NOTE_PMSG {
    DMUS_PMSG_PART
    MUSIC_TIME mtDuration;
    WORD       wMusicValue;
    WORD       wMeasure;
    short      nOffset;
    BYTE       bBeat;
    BYTE       bGrid;
    BYTE       bVelocity;
    BYTE       bFlags;
    BYTE       bTimeRange;
    BYTE       bDurRange;
    BYTE       bVelRange;
    BYTE       bPlayModeFlags;
    BYTE       bSubChordLevel;
    BYTE       bMidiValue;
} DMUS_NOTE_PMSG;

Members

DMUS_PMSG_PART
Macro for common message members. See DMUS_PMSG.
mtDuration
Duration of the note.
wMusicValue
Description of note. In most play modes, this is a packed array of four-bit values (nibbles), as follows:

Octave, in the range -2 to 14. The note is transposed up or down by the octave times 12.

Chord position, in the range 0 to 15, though it should never be above 3. The first position in the chord is 0.

Scale position, in the range 0 to 15. Typically it is just 0 through 2, but it is possible to have a one-note chord and have everything above the chord be interpreted as a scale position.

Accidental, in the range -8 to 7, but typically in the range -2 to 2. This represents an offset that takes the note out of the scale.

In the fixed play modes, the music value is simply a MIDI note value in the range 0 to 127.

wMeasure
Measure in which this note occurs.
nOffset
Offset from grid at which this note occurs, in music time.
bBeat
Beat (in measure) at which this note occurs.
bGrid
Grid offset from beat at which this note occurs.
bVelocity
Note velocity.
bFlags
See DMUS_NOTEF_FLAGS.
bTimeRange
Range to randomize time.
bDurRange
Range to randomize duration.
bVelRange
Range to randomize velocity.
bPlayModeFlags
Play mode determining how the music value is related to the chord and subchord. For a list of values, see DMUS_PLAYMODE_FLAGS.
bSubChordLevel
Subchord level the note uses. See DMUS_SUBCHORD.
bMidiValue
MIDI note value, converted from wMusicValue.

Remarks

When a note is to be played, the DMUS_NOTE_PMSG flows through the graph and any tools in the graph until it reaches the final MIDI output tool. When the tool sees that DMUS_NOTEF_NOTEON is set in the bFlags member, it sends a MIDI note-on message to the correct port (according to the dwPChannel member of the DMUS_PMSG part). It then clears the flag, adds m_mtDuration to the m_mtTime, and requeues the message so that the note is turned off at the appropriate time.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicPerformance::SendPMsg, Music Values and MIDI Notes


DMUS_NOTIFICATION_PMSG

The DMUS_NOTIFICATION_PMSG structure is a DMUS_PMSG that represents a notification.

typedef struct DMUS_NOTIFICATION_PMSG {
    DMUS_PMSG_PART
    GUID   guidNotificationType;
    DWORD  dwNotificationOption;
    DWORD  dwField1;
    DWORD  dwField2;
} DMUS_NOTIFICATION_PMSG;

Members

DMUS_PMSG_PART
Macro for common message members. See DMUS_PMSG.
guidNotificationType
Identifier of the notification type. The following types are defined:
GUID_NOTIFICATION_CHORD
Chord change.
GUID_NOTIFICATION_COMMAND
Command event.
GUID_NOTIFICATION_MEASUREANDBEAT
Measure and beat event.
GUID_NOTIFICATION_PERFORMANCE
Performance event, further defined in dwNotificationOption.
GUID_NOTIFICATION_SEGMENT
Segment event, further defined in dwNotificationOption.
dwNotificationOption
Identifier of the notification subtype.

If the notification type is GUID_NOTIFICATION_SEGMENT, this member can contain one of the following values:

DMUS_NOTIFICATION_SEGABORT
The segment was stopped by IDirectMusicPerformance::Stop.
DMUS_NOTIFICATION_SEGALMOSTEND
The segment has reached the end minus the prepare time.
DMUS_NOTIFICATION_SEGEND
The segment has ended.
DMUS_NOTIFICATION_SEGLOOP
The segment has looped.
DMUS_NOTIFICATION_SEGSTART
The segment has started.

If the notification type is GUID_NOTIFICATION_COMMAND, this member can contain one of the following values:

DMUS_NOTIFICATION_GROOVE
Groove change.
DMUS_NOTIFICATION_EMBELLISHMENT
Embellishment command (intro, fill, break, or end).

If the notification type is GUID_NOTIFICATION_PERFORMANCE, this member can contain one of the following values:

DMUS_NOTIFICATION_MUSICSTARTED
Playback has started.
DMUS_NOTIFICATION_MUSICSTOPPED
Playback has stopped.

If the notification type is GUID_NOTIFICATION_MEASUREANDBEAT, this member contains DMUS_NOTIFICATION_MEASUREBEAT. No other subtypes are defined.

If the notification type is GUID_NOTIFICATION_CHORD, this member contains DMUS_NOTIFICATION_CHORD. No other subtypes are defined.

dwField1
Extra data specific to the type of notification. For GUID_NOTIFICATION_MEASUREANDBEAT notifications, this member returns the beat number within the measure.
dwField2
Extra data specific to the type of notification. Reserved for future or application-defined use.

Remarks

The punkUser member (see DMUS_PMSG) contains the IUnknown pointer of the segment state. This is especially useful in the chord and command cases, where you can query for the IDirectMusicSegmentState interface, call IDirectMusicSegmentState::GetSegment to get the IDirectMusicSegment pointer, and then call the IDirectMusicSegment::GetParam method to get the chord or command at the time given in the notification message's mtTime member.

Applications can define their own notification message types and subtypes and use dwField1 and dwField2 for extra data. Such custom notification messages can be allocated and sent just like any message. Application-defined tracks can send messages of a particular type after the GUID (guidNotificationType) has been handed to IDirectMusicTrack::AddNotificationType.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

Notification and Event Handling, IDirectMusicPerformance::SendPMsg


DMUS_PATCH_PMSG

The DMUS_PATCH_PMSG structure contains data for a program change message.

typedef struct DMUS_PATCH_PMSG {
    DMUS_PMSG_PART
    BYTE  byInstrument;
    BYTE  byMSB;
    BYTE  byLSB;
    BYTE  byPad[1];
} DMUS_PATCH_PMSG;

Members

DMUS_PMSG_PART
Macro for common message members. See DMUS_PMSG.
byInstrument
Patch number of instrument.
byMSB
Most significant byte of bank select.
byLSB
Least significant byte of bank select.
byPad
Padding to word boundary.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

DMUS_MIDI_PMSG, IDirectMusicPerformance::SendPMsg, MIDI Messages


DMUS_SYSEX_PMSG

The DMUS_SYSEX_PMSG structure is a DMUS_PMSG that represents a MIDI system exclusive message.

typedef struct DMUS_SYSEX_PMSG {
    DMUS_PMSG_PART
    DWORD dwLen;
    BYTE  abData[1];
} DMUS_SYSEX_PMSG;

Members

DMUS_PMSG_PART
Macro for common message members. See DMUS_PMSG.
dwLen
Length of the data, in bytes.
abData
Array of data.

Remarks

The data part of a system exclusive message must begin with the System Exclusive identifier (0xF0) and end with EOX (0xF7).

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

DMUS_MIDI_PMSG, DMUS_PATCH_PMSG, MIDI Messages, IDirectMusicPerformance::SendPMsg


DMUS_TEMPO_PMSG

The DMUS_TEMPO_PMSG structure contains data for a message that controls the performance's tempo.

typedef struct DMUS_TEMPO_PMSG {
    DMUS_PMSG_PART
    double dblTempo;
} DMUS_TEMPO_PMSG;

Members

DMUS_PMSG_PART
Macro for common message members. See DMUS_PMSG.
dblTempo
The tempo, in the range DMUS_TEMPO_MIN to DMUS_TEMPO_MAX.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicPerformance::SendPMsg


DMUS_TIMESIG_PMSG

The DMUS_TIMESIG_PMSG structure contains data for a message that controls the performance's time signature.

typedef struct _DMUS_TIMESIG_PMSG {
    DMUS_PMSG_PART
    BYTE bBeatsPerMeasure;
    BYTE bBeat;
    WORD wGridsPerBeat;
} DMUS_TIMESIG_PMSG;

Members

DMUS_PMSG_PART
Macro for common message members. See DMUS_PMSG.
bBeatsPerMeasure
Beats per measure (top of the time signature).
bBeat
What note receives the beat (bottom of the time signature), where 1 is a whole note, 2 is a half note, 4 is a quarter note, and so on. Zero is a 256th note.
wGridsPerBeat
Grids (subdivisions) per beat. This value determines the timing resolution for certain music events—for example, segments cued with the DMUS_SEGF_GRID flag (see DMUS_SEGF_FLAGS).

Remarks

Time signature messages are generated by the time signature track and the style track. In general, a segment will contain one or the other, but not both. A segment representing a MIDI file has a time signature track, but most segments authored with a tool such as DirectMusic Producer contain time signature information in the style track.

By default, only the primary segment sends time signature messages. For information on how to change this behavior, see Disabling and Enabling Messages on a Track.

The time signature is used by the performance to resolve time to measure, beat, and grid boundaries in all methods where the time can be adjusted by DMUS_SEGF_FLAGS or DMUS_TIME_RESOLVE_FLAGS. The time signature and style tracks also use the time signature to generate notifications on measure and beat boundaries. See DMUS_NOTIFICATION_PMSG.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicPerformance::SendPMsg, DMUS_TIMESIGNATURE


DMUS_TRANSPOSE_PMSG

The DMUS_TRANSPOSE_PMSG structure contains data for a message that controls a transposition.

typedef struct _DMUS_TRANSPOSE_PMSG {
    DMUS_PMSG_PART
    short nTranspose;
} DMUS_TRANSPOSE_PMSG;

Members

DMUS_PMSG_PART
Macro for common message members. See DMUS_PMSG.
nTranspose
Number of semitones by which to transpose. This can be a negative value.

Remarks

If the transposition of a note puts it outside the standard MIDI range of 0-127, it will not play.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicPerformance::SendPMsg


Structures

This section contains reference information for the following run-time structures used in DirectMusic:

  • DMUS_BUFFERDESC
  • DMUS_CHORD_KEY
  • DMUS_CHORD_PARAM
  • DMUS_CLOCKINFO
  • DMUS_COMMAND_PARAM
  • DMUS_EVENTHEADER
  • DMUS_MUTE_PARAM
  • DMUS_NOTERANGE
  • DMUS_OBJECTDESC
  • DMUS_PORTCAPS
  • DMUS_PORTPARAMS
  • DMUS_RHYTHM_PARAM
  • DMUS_SUBCHORD
  • DMUS_SYNTHSTATS
  • DMUS_TEMPO_PARAM
  • DMUS_TIMESIGNATURE
  • DMUS_VERSION
  • DMUS_WAVES_REVERB_PARAMS
  • KSPROPERTY

Special categories of structures are contained in the following sections:

  • Messages
  • File Structures
  • DLS Structures

Note The memory for all DirectX structures must be initialized to zero before use. In addition, all structures that contain a dwSize member must set the member to the size of the structure, in bytes, before use. The following DirectDraw example performs these tasks on a common structure, DDCAPS:

DDCAPS ddcaps; // Can't use this yet.

ZeroMemory(&ddcaps, sizeof(ddcaps));
ddcaps.dwSize = sizeof(ddcaps);

// Now the structure can be used.
.
.


DMUS_BUFFERDESC

The DMUS_BUFFERDESC structure is used to describe a buffer for the IDirectMusic::CreateMusicBuffer method.

typedef struct _DMUS_BUFFERDESC {
    DWORD dwSize;
    DWORD dwFlags;
    GUID  guidBufferFormat;
    DWORD cbBuffer;
} DMUS_BUFFERDESC, *LPDMUS_BUFFERDESC;

Members

dwSize
The size of this structure, in bytes. This member must be initialized before the structure is used.
dwFlags
No flags are defined.
guidBufferFormat
Identifier of the KS format of the buffer. The value GUID_NULL represents KSDATAFORMAT_SUBTYPE_DIRECTMUSIC.

If guidBufferFormat represents a KS format other than KSDATAFORMAT_SUBTYPE_DIRECTMUSIC, the application must verify that the port playing back the data understands the specified format; if not, the buffer will be ignored. To find out if the port supports a specific KS format, use the IKsControl::KsProperty method.

cbBuffer
Minimum size of the buffer, in bytes. The amount of memory actually allocated may be slightly higher, as the system will pad the buffer to a multiple of four bytes. The buffer must be at least 32 bytes in order to accommodate a single MIDI channel message, and at least 28 bytes plus the size of the data in order to accommodate a sysex message or other unstructured data.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

DMUS_EVENTHEADER, IDirectMusicBuffer::PackStructured, IDirectMusicBuffer::PackUnstructured


DMUS_CHORD_KEY

The DMUS_CHORD_KEY structure is used to describe a chord in the IDirectMusicPerformance::MIDIToMusic and IDirectMusicPerformance::MusicToMIDI methods.

typedef struct _DMUS_CHORDKEY {
    WCHAR         wszName[16];
    WORD          wMeasure;
    BYTE          bBeat;
    BYTE          bSubChordCount;
    DMUS_SUBCHORD SubChordList[DMUS_MAXSUBCHORD];
    DWORD         dwScale;
    BYTE          bKey;
} DMUS_CHORDKEY;

Members

wszName
Name of the chord.
wMeasure
Measure the chord falls on.
bBeat
Beat the chord falls on.
bSubChordCount
Number of chords in the chord's list of subchords.
SubChordList
Array of DMUS_SUBCHORD structures, describing the components that make up the chord.
dwScale
Scale underlying the entire chord.
bKey
Key underlying the entire chord.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicPerformance::GetParam, IDirectMusicPerformance::SetParam, IDirectMusicSegment::GetParam, IDirectMusicSegment::SetParam, IDirectMusicTrack::GetParam, IDirectMusicTrack::SetParam, Music Parameters


DMUS_CHORD_PARAM

The DMUS_CHORD_PARAM structure is used as the pParam parameter in calls to the various GetParam and SetParam methods when the track is a chord track and rguidType is GUID_ChordParam.

typedef DMUS_CHORD_KEY DMUS_CHORD_PARAM;

Members

See DMUS_CHORD_KEY.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicf.h.

See Also

IDirectMusicPerformance::GetParam, IDirectMusicPerformance::SetParam, IDirectMusicSegment::GetParam, IDirectMusicSegment::SetParam, IDirectMusicTrack::GetParam, IDirectMusicTrack::SetParam, Music Parameters


DMUS_CLOCKINFO

The DMUS_CLOCKINFO structure reports information about a clock enumerated by using the IDirectMusic::EnumMasterClock method.

typedef struct _DMUS_CLOCKINFO{
    DWORD           dwSize;
    DMUS_CLOCKTYPE  ctType;
    GUID            guidClock;
    WCHAR           wszDescription[DMUS_MAX_DESCRIPTION];
} DMUS_CLOCKINFO, *LPDMUS_CLOCKINFO;

Members

dwSize
Size of the structure, in bytes This member must be initialized to sizeof(DMUS_CLOCKINFO) before the structure is passed to a method.
ctType
Member of the DMUS_CLOCKTYPE enumeration specifying the type of clock.
guidClock
Identifier of the clock. This value may be passed to the IDirectMusic::SetMasterClock method in order to set the master clock for DirectMusic.
wszDescription
Description of the clock.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.


DMUS_COMMAND_PARAM

The DMUS_COMMAND_PARAM structure is used as the pParam parameter in calls to various GetParam and SetParam methods when the track is a command track and the rguidType parameter is GUID_CommandParam.

typedef struct {
    BYTE bCommand;
    BYTE bGrooveLevel;
    BYTE bGrooveRange;
} DMUS_COMMAND_PARAM;

Members

bCommand
Command type. See DMUS_COMMANDT_TYPES.
bGrooveLevel
Command's groove level. The groove level is a value between 1 and 100.
bGrooveRange
Amount by which the groove level can be randomized. For instance, if the groove level is 35 and the range is 4, the actual groove level could be anywhere from 33 to 37. Not currently implemented.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicf.h.

See Also

IDirectMusicPerformance::GetParam, IDirectMusicPerformance::SetParam, IDirectMusicSegment::GetParam, IDirectMusicSegment::SetParam, IDirectMusicTrack::GetParam, IDirectMusicTrack::SetParam


DMUS_EVENTHEADER

The DMUS_EVENTHEADER structure precedes and describes an event in a port buffer.

typedef struct _DMUS_EVENTHEADER {
    DWORD           cbEvent;
    DWORD           dwChannelGroup;
    REFERENCE_TIME  rtDelta;
    DWORD           dwFlags;
} DMUS_EVENTHEADER, *LPDMUS_EVENTHEADER;

Members

cbEvent
Number of bytes in event.
dwChannelGroup
Group to which the event belongs.
rtDelta
Offset from start time of buffer.
dwFlags
Set to DMUS_EVENT_STRUCTURED if the event is parseable MIDI data.

Remarks

Pshpack4.h is included before the declaration of this structure to turn off automatic alignment of structures, so that the data immediately follows the header. (For more information, see the comments in Pshpack4.h.) Poppack.h is then included to turn alignment back on, and the entire structure (header plus event) is padded to an eight-byte boundary.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicc.h.

See Also

IDirectMusicBuffer::GetNextEvent, IDirectMusicBuffer::PackStructured, IDirectMusicBuffer::PackUnstructured


DMUS_NOTERANGE

The DMUS_NOTERANGE structure specifies a range of notes that an instrument must respond to. An array of these structures is passed to the IDirectMusicPerformance::DownloadInstrument and IDirectMusicPort::DownloadInstrument methods to specify what notes the instrument should respond to and therefore what instrument regions need to be downloaded.

typedef struct _DMUS_NOTERANGE {
    DWORD dwLowNote;
    DWORD dwHighNote;
} DMUS_NOTERANGE, *LPDMUS_NOTERANGE;

Members

dwLowNote
The low note for this range of MIDI notes to which the instrument must respond.
dwHighNote
The high note for this range of MIDI notes to which the instrument must respond.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmdls.h.


DMUS_MUTE_PARAM

The DMUS_MUTE_PARAM structure is used as the pParam parameter in calls to the various GetParam and SetParam methods when the track is a mute track and rguidType is GUID_MuteParam.

typedef struct _DMUS_MUTE_PARAM {
    DWORD  dwPChannel;
    DWORD  dwPChannelMap;
    BOOL   fMute;
} DMUS_MUTE_PARAM;

Members

dwPChannel
The performance channel to mute or remap. If the structure is being passed to GetParam, this member must be initialized.
dwPChannelMap
Channel to which dwPChannel is being mapped. This member is ignored if fMute is TRUE.
fMute
TRUE if dwPChannel is being muted.

Remarks

If you wanted all the notes on PChannel 3 to play on PChannel 9 instead, you would set dwPChannel to 3 and dwPChannelMap to 9 before passing the structure to one of the SetParam methods. If you wanted to mute the notes on PChannel 8, you would set dwPChannel to 8 and dwPChannelMap to 0xFFFFFFFF.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicf.h.

See Also

IDirectMusicPerformance::GetParam, IDirectMusicPerformance::SetParam, IDirectMusicSegment::GetParam, IDirectMusicSegment::SetParam, IDirectMusicTrack::GetParam, IDirectMusicTrack::SetParam


DMUS_OBJECTDESC

The DMUS_OBJECTDESC structure is used to describe a DirectMusic object. It is passed to the IDirectMusicLoader::GetObject method to identify the object that the loader should retrieve from storage. Information about an object is retrieved in this structure by the IDirectMusicLoader::EnumObject and IDirectMusicObject::GetDescriptor methods.

typedef struct _DMUS_OBJECTDESC {
    DWORD         dwSize;
    DWORD         dwValidData;
    GUID          guidObject;
    GUID          guidClass;
    FILETIME      ftDate;
    DMUS_VERSION  vVersion;
    WCHAR         wszName[DMUS_MAX_NAME];
    WCHAR         wszCategory[DMUS_MAX_CATEGORY];
    WCHAR         wszFileName[DMUS_MAX_FILENAME];
    LONGLONG      llMemLength;
    PBYTE         pbMemData;
} DMUS_OBJECTDESC, *LPDMUS_OBJECTDESC;

Members

dwSize
Size of the structure, in bytes. This member must be initialized to sizeof(DMUS_OBJECTDESC) before the structure is passed to any method.
dwValidData
Flags describing which members are valid, and giving further information about some members. The following values are defined:
DMUS_OBJ_OBJECT
The guidObject member is valid.
DMUS_OBJ_CLASS
The guidClass member is valid.
DMUS_OBJ_NAME
The wszName member is valid.
DMUS_OBJ_CATEGORY
The wszCategory member is valid.
DMUS_OBJ_FILENAME
The wszFileName member is valid.
DMUS_OBJ_FULLPATH
The wszFileName member contains the full path. If this flag is set, the loader assumes that wszFileName is valid even if DMUS_OBJ_FILENAME has not been set.
DMUS_OBJ_MEMORY
The object is in memory, and llMemLength and pbMemData are valid.
DMUS_OBJ_URL
The wszFileName member contains an URL. (URLs are not currently supported by the DirectMusic loader.)
DMUS_OBJ_VERSION
The vVersion member is valid.
DMUS_OBJ_DATE
The ftDate member is valid.
DMUS_OBJ_LOADED
Object is currently loaded in memory.
guidObject
Unique identifier for this object.
guidClass
Unique identifier for the class of object. All the standard objects have defined identifiers consisting of "CLSID_" plus the name of the object. For example, a segment object is identified as CLSID_DirectMusicSegment. See the defines in Dmusici.h.
ftDate
Last edited date of object.
vVersion
DMUS_VERSION structure containing version information.
wszName
Name of object.
wszCategory
Category for object.
wszFileName
File path. If DMUS_OBJ_FULLPATH is set, this is the full path; otherwise it is just the file name.
llMemLength
Size of data in memory.
pbMemData
Data in memory.

Remarks

At least one of wszName, guidObject, and wszFileName must be filled with valid data in order to retrieve the object by using the IDirectMusicLoader::GetObject method.

The name and category strings use 16-bit characters in the WCHAR format, not 8-bit ANSI chars. Be sure to convert as appropriate. You can use the C library routine mbstowcs to convert from multibyte to Unicode and wcstombs to convert from Unicode back to multibyte.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

Enumerating Objects, Loading Objects, Getting Object Descriptors


DMUS_PORTCAPS

The DMUS_PORTCAPS structure receives information about a port enumerated by a call to the IDirectMusic::EnumPort method. The structure is also used to return information through the IDirectMusicPort::GetCaps method.

typedef struct _DMUS_PORTCAPS {
    DWORD dwSize;
    DWORD dwFlags;
    GUID  guidPort;
    DWORD dwClass;
    DWORD dwType;
    DWORD dwMemorySize;
    DWORD dwMaxChannelGroups;
    DWORD dwMaxVoices;
    DWORD dwMaxAudioChannels;
    DWORD dwEffectFlags;
    WCHAR wszDescription[DMUS_MAX_DESCRIPTION];
} DMUS_PORTCAPS, *LPDMUS_PORTCAPS;

Members

dwSize
Size of the structure, in bytes. This member must be initialized to sizeof(DMUS_PORTCAPS) before the structure is passed to any method.
dwFlags
Flags describing various capabilities of the port. This field may contain one or more of the following values:
DMUS_PC_DIRECTSOUND
The port supports streaming wave data to DirectSound.
DMUS_PC_DLS
The port supports DLS Level 1 sample collections.
DMUS_PC_EXTERNAL
This port connects to devices outside of the host—for example, devices connected over an external MIDI port like the MPU-401.
DMUS_PC_GMINHARDWARE
The synthesizer has its own GM instrument set, so GM instruments do not need to be downloaded.
DMUS_PC_GSINHARDWARE
This port contains the Roland GS sound set in hardware.
DMUS_PC_MEMORYSIZEFIXED
Memory available for DLS instruments cannot be adjusted.
DMUS_PC_SHAREABLE
More than one port can be created that uses the same range of channel groups on the device. Unless this bit is set, the port can only be opened in exclusive mode. In exclusive mode, an attempt to create a port will fail unless free channel groups are available to assign to the create request.
DMUS_PC_SOFTWARESYNTH
The port is a software synthesizer.
DMUS_PC_XGINHARDWARE
The port contains the Yamaha XG extensions in hardware.
guidPort
Identifier of the port. This value may be passed to the IDirectMusic::CreatePort method in order to get an IDirectMusicPort interface for the port.
dwClass
Class of this port. The following classes are defined:
DMUS_PC_INPUTCLASS
Input port.
DMUS_PC_OUTPUTCLASS
Output port.
dwType
Type of this port. The following types are defined:
DMUS_PORT_WINMM_DRIVER
Windows Multimedia driver.
DMUS_PORT_USER_MODE_SYNTH
User mode synthesizer.
DMUS_PORT_KERNEL_MODE
WDM driver.
dwMemorySize
Amount of memory available to store DLS instruments. If the port is using system memory and the amount is therefore limited only by the available system memory, this field will contain DMUS_PC_SYSTEMMEMORY.
dwMaxChannelGroups
Maximum number of channel groups supported by this port. A channel group is a set of 16 MIDI channels.
dwMaxVoices
Maximum number of voices that can be allocated when this port is opened.
dwMaxAudioChannels
Maximum number of audio channels that can be rendered by the port.
dwEffectFlags
Flags indicating what audio effects are available on the port. The following flags are defined:
DMUS_EFFECT_NONE
No effects are supported.
DMUS_EFFECT_REVERB
The port supports reverb.
DMUS_EFFECT_CHORUS
The port supports chorus.
wszDescription
Description of the port. This may be a system-generated name, such as L"MPU-401 Output Port [330]", or a user-specified friendly name, such as L"Port w/ External SC-55".

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicc.h.


DMUS_PORTPARAMS

The DMUS_PORTPARAMS structure contains parameters for the opening of a DirectMusic port. These parameters are passed in when the IDirectMusic::CreatePort method is called.

typedef struct _DMUS_PORTPARAMS {
    DWORD dwSize;
    DWORD dwValidParams;
    DWORD dwVoices;
    DWORD dwChannelGroups;
    DWORD dwAudioChannels;
    DWORD dwSampleRate;
    DWORD dwEffectFlags;
    DWORD fShare;
} DMUS_PORTPARAMS, *LPDMUS_PORTPARAMS;

Members

dwSize
Size of the structure, in bytes. This member must be initialized to sizeof(DMUS_PORTPARAMS) before the structure is passed to a method.
dwValidParams
Specifies which port parameters in this structure have been filled in. Setting the flag for a particular parameter means that you wish to have this parameter set on the method call, or wish to override the default value when the port is created. The following flags have been defined:

DMUS_PORTPARAMS_VOICES
DMUS_PORTPARAMS_CHANNELGROUPS
DMUS_PORTPARAMS_AUDIOCHANNELS
DMUS_PORTPARAMS_SAMPLERATE
DMUS_PORTPARAMS_EFFECTS
DMUS_PORTPARAMS_SHARE

dwVoices
Number of voices required on this port.
dwChannelGroups
Number of channel groups to be allocated on this port. Must be less than or equal to the number of channel groups specified in the DMUS_PORTCAPS structure returned by the IDirectMusic::EnumPort and IDirectMusicPort::GetCaps methods.
dwAudioChannels
Desired number of output channels.
dwSampleRate
Desired sample rate in hertz.
dwEffectFlags
Flags indicating which special effects are desired. The following flags are defined:

DMUS_EFFECT_NONE
DMUS_EFFECT_REVERB
DMUS_EFFECT_CHORUS

fShare
If TRUE, all ports use the channel groups assigned to this port. If FALSE, the port is opened in exclusive mode and the use of the same channel groups by other ports is forbidden.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicc.h.

See Also

DMUS_PORTCAPS


DMUS_RHYTHM_PARAM

The DMUS_RHYTHM_PARAM structure is used as the pParam parameter in calls to the various GetParam methods when the track is a chord track and rguidType is GUID_RhythmParam.

typedef struct {
    DMUS_TIMESIGNATURE  TimeSig;
    DWORD               dwRhythmPattern;
} DMUS_RHYTHM_PARAM;

Members

TimeSig
A DMUS_TIMESIGNATURE structure containing the rhythm parameter's time signature. This structure must be initialized before DMUS_RHYTHM_PARAM structure is passed to GetParam.
dwRhythmPattern
A rhythm pattern for a sequence of chords. Each bit represents a beat in one or more measures, with a 1 signifying a chord on the beat and a 0 signifying no chord.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicf.h.

See Also

IDirectMusicPerformance::GetParam, IDirectMusicPerformance::SetParam, IDirectMusicSegment::GetParam, IDirectMusicSegment::SetParam, IDirectMusicTrack::GetParam, IDirectMusicTrack::SetParam


DMUS_SUBCHORD

The DMUS_SUBCHORD structure is used in the SubChordList member of a DMUS_CHORD_PARAM structure.

typedef struct {
    DWORD dwChordPattern;
    DWORD dwScalePattern;
    DWORD dwInversionPoints;
    DWORD dwLevels;
    BYTE  bChordRoot;
    BYTE  bScaleRoot;
} DMUS_SUBCHORD;

Members

dwChordPattern
Notes in the subchord. Each of the lower 24 bits represents a semitone, starting with the root at the least significant bit, and the bit is set if the note is in the chord.
dwScalePattern
Notes in the scale. Each of the lower 24 bits represents a semitone, starting with the root at the least significant bit, and the bit is set if the note is in the scale.
dwInversionPoints
Points in the scale where inversions can occur. Bits that are off signify that the notes in the interval cannot be inverted. Thus the pattern 100001111111 indicates that inversions are allowed anywhere except between the fifth and seventh degrees of a major scale.
dwLevels
Bitfield showing which levels are supported by this subchord. Each part in a style is assigned a level, and this chord will be used only for parts whose levels are contained in this member.
bChordRoot
Root of the subchord, where 0 is the bottom C in the range and 23 is the top B.
bScaleRoot
Root of the scale, where 0 is the bottom C in the range and 23 is the top B.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.


DMUS_SYNTHSTATS

The DMUS_SYNTHSTATS structure is used by the IDirectMusicPort::GetRunningStats method to return the current running status of a synthesizer.

typedef struct DMUS_SYNTHSTATS {
    DWORD dwSize;
    DWORD dwValidStats;
    DWORD dwVoices;
    DWORD dwTotalCPU;
    DWORD dwCPUPerVoice;
    DWORD dwLostNotes;
    DWORD dwFreeMemory;
    long  lPeakVolume;
} DMUS_SYNTHSTATS, *LPDMUS_SYNTHSTATS;

Members

dwSize
Size of the structure, in bytes. This member must be initialized to sizeof(DMUS_SYNTHSTATS) before the structure is passed to a method.
dwValidStats
Specifies which fields in this structure have been filled in by the synthesizer. The following flags have been defined:

DMUS_SYNTHSTATS_VOICES
DMUS_SYNTHSTATS_TOTAL_CPU
DMUS_SYNTHSTATS_CPU_PER_VOICE
DMUS_SYNTHSTATS_FREE_MEMORY
DMUS_SYNTHSTATS_LOST_NOTES
DMUS_SYNTHSTATS_PEAK_VOLUME

dwVoices
Average number of voices playing.
dwTotalCPU
Total percentage of the CPU being consumed, multiplied by 100.
dwCPUPerVoice
Percentage of the CPU being consumed per voice, multiplied by 100.
dwLostNotes
Number of notes lost. Notes can be dropped because of voice-stealing or because too much of the CPU is being consumed.
dwFreeMemory
Amount of memory currently available to store DLS instruments. If the synthesizer is using system memory and the amount is therefore limited only by the available system memory, this value is set to DMUS_SYNTHSTATS_SYSTEMMEMORY.
lPeakVolume
Peak volume, measured in hundredths of decibels.

Remarks

All the running status parameters, with the exception of dwFreeMemory, are refreshed every second. For example, dwLostNotes provides the total number of notes lost over a one-second period.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.


DMUS_TEMPO_PARAM

The DMUS_TEMPO_PARAM structure is used as the pParam parameter in calls to the various GetParam and SetParam methods when the track is a tempo track and rguidType is GUID_TempoParam.

typedef struct _DMUS_TEMPO_PARAM {
    MUSIC_TIME  mtTime;
    double      dblTempo;
} DMUS_TEMPO_PARAM;

Members

mtTime
Time for which the tempo was retrieved. (This member is not used in SetParam methods, which use their mtTime parameter instead.)
dblTempo
The tempo, in the range DMUS_TEMPO_MIN to DMUS_TEMPO_MAX.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicf.h.

See Also

IDirectMusicPerformance::GetParam, IDirectMusicPerformance::SetParam, IDirectMusicSegment::GetParam, IDirectMusicSegment::SetParam, IDirectMusicTrack::GetParam, IDirectMusicTrack::SetParam


DMUS_TIMESIGNATURE

The DMUS_TIMESIGNATURE structure is passed to the IDirectMusicStyle::GetTimeSignature method to retrieve information about a style's time signature. It is also used in DMUS_RHYTHM_PARAM structure, and in the various GetParam methods when the rguidType parameter is GUID_TimeSignature and the track is a time signature or style track.

typedef struct _DMUS_TIMESIGNATURE {
    MUSIC_TIME mtTime;
    BYTE  bBeatsPerMeasure;
    BYTE  bBeat;
    WORD  wGridsPerBeat;
} DMUS_TIMESIGNATURE;

Members

mtTime
Music time at which this time signature occurs.
bBeatsPerMeasure
Top of time signature.
bBeat
Bottom of time signature.
wGridsPerBeat
Grids (subdivisions) per beat. This value determines the timing resolution for certain music events—for example, segments cued with the DMUS_SEGF_GRID flag (see DMUS_SEGF_FLAGS).

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicPerformance::GetParam, IDirectMusicPerformance::SetParam, IDirectMusicSegment::GetParam, IDirectMusicSegment::SetParam, IDirectMusicTrack::GetParam, IDirectMusicTrack::SetParam, DMUS_TIMESIG_PMSG


DMUS_VERSION

The DMUS_VERSION structure contains version information for an object described in the DMUS_OBJECTDESC structure.

typedef struct _DMUS_VERSION {
    DWORD  dwVersionMS;
    DWORD  dwVersionLS;
} DMUS_VERSION, FAR *LPDMUS_VERSION;

Members

dwVersionMS
Most significant DWORD of version number.
dwVersionLS
Least significant DWORD of version number.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.


DMUS_WAVES_REVERB_PARAMS

The DMUS_WAVES_REVERB_PARAMS structure contains information about reverberation effects.

typedef struct _DMUS_WAVES_REVERB_PARAMS {
    float  fInGain;
    float  fReverbMix;
    float  fReverbTime;
    float  fHighFreqRTRatio;
} DMUS_WAVES_REVERB_PARAMS;

Parameters

fInGain
Input gain in dB (to avoid output overflows). The default value is 0.
fReverbMix
Reverb mix in dB. A value of 0 means 100 percent wet reverb (no direct signal). Negative values gives less wet signal. The coefficients are calculated so that the overall output level stays approximately constant regardless of the amount of reverb mix. The default value is -10.0.
fReverbTime
Reverb decay time, in milliseconds. The default value is 1000.
fHighFreqRTRatio
Ratio of the high frequencies to the global reverb time. Unless very bright reverbs are wanted, this should be set to a value of less than 1. For example, if fReverbTime is 1000 ms and dHighFreqRTRatio is 0.1, then the decay time for high frequencies will be 100ms. The default value is 0.001.

Remarks

The TrueVerb reverberation technology from Waves is licensed to Microsoft as the SimpleVerb implementation for use in the Microsoft Software Synthesizer.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicc.h.


KSPROPERTY

The KSPROPERTY structure is passed to the IKsControl::KsProperty method to identify a property and operation.

KSPROPERTY is defined as a KSIDENTIFIER structure, which is declared as follows:

typedef struct {
    union {
        struct {
            GUID   Set;
            ULONG  Id;
            ULONG  Flags;
        };
        LONGLONG    Alignment;
    };
} KSIDENTIFIER, *PKSIDENTIFIER;

Members

Set
Identifier of the property set. The following property set GUIDs are predefined by DirectMusic:
GUID_DMUS_PROP_DLS1
Item 0 is a Boolean indicating whether or not this port supports the downloading of DLS samples.
GUID_DMUS_PROP_Effects
Item 0 contains DMUS_EFFECT_NONE or one or more effects flags (see the dwEffectFlags member of DMUS_PORTCAPS). This property is used to set or retrieve the current state of the effects.
GUID_DMUS_PROP_GM_Hardware
Item 0 is a Boolean indicating whether or not this port supports GM in hardware.
GUID_DMUS_PROP_GS_Capable
Item 0 is a Boolean indicating whether or not this port supports the minimum requirements for Roland GS extensions.
GUID_DMUS_PROP_GS_Hardware
Item 0 is a Boolean indicating whether or not this port supports Roland GS extensions in hardware.
GUID_DMUS_PROP_LegacyCaps
Item 0 is the MIDIINCAPS or MIDIOUTCAPS structure that describes the underlying Windows Multimedia device implementing this port. A MIDIINCAPS structure will be returned if dwClass is DMUS_PC_INPUTCLASS in this port's capabilities structure. Otherwise a MIDIOUTCAPS structure will be returned.
GUID_DMUS_PROP_MemorySize
Item 0 is a Boolean indicating how many bytes of sample RAM are available on this device.
GUID_DMUS_PROP_SynthSink_DSOUND
Item 0 is a Boolean indicating whether or not this port supports DirectSound.
GUID_DMUS_PROP_SynthSink_WAVE
Item 0 is a Boolean indicating whether or not this port supports wave output using the waveOut functions.
GUID_DMUS_PROP_Volume
Item 1 (DMUS_ITEM_Volume) is a LONG which is the signed value, in hundredths of a dB, which will be added to the gain of all voices after all DLS articulation has been performed. By default, when a port is added to the performance, this property is set to the master volume. For master volume, see Setting and Retrieving Global Parameters.
GUID_DMUS_PROP_WavesReverb
Item 0 is a DMUS_WAVES_REVERB_PARAMS structure containing reverb parameters.
GUID_DMUS_PROP_WriteLatency
Item 0 is the write latency of the user mode synthesizer (the dwType member of the DMUS_PORTCAPS structure is DMUS_PORT_USER_MODE_SYNTH) that streams its output to DirectSound. The write latency is the delay between when the synthesizer creates a buffer of sound and when it is heard. By adjusting this value, an application can fine-tune the synthesizer for minimum latency without sound breakup. On some machines, in particular machines without hardware support for DirectSound, the initial latency will be much larger than on others, so the value should always be read first, and then adjusted with a relative value. The write latency can have different values for each port instance. This property must be set each time the port is activated.
GUID_DMUS_PROP_WritePeriod
Item 0 is the write period, in milliseconds, of the user mode synthesizer (the dwType member of the DMUS_PORTCAPS structure is DMUS_PORT_USER_MODE_SYNTH) that streams its output to DirectSound. The write period controls how frequently the synthesizer sink wakes up to allow the synthesizer to mix. By reducing this value, the application can reduce the overall latency of the synthesizer. However, values under 10 milliseconds start to increase the CPU load. The write period has the same value for all port instances that use the standard DirectSound sink. This property must be set each time the port is activated.
GUID_DMUS_PROP_XG_Capable
Item 0 is a Boolean indicating whether or not this port supports the minimum requirements for Yamaha XG extensions.
GUID_DMUS_PROP_XG_Hardware
Item 0 is a Boolean indicating whether or not this port supports Yamaha XG extensions in hardware.
Id
Item within the property set.
Flags
One of the following flags to specify the operation:
KSPROPERTY_TYPE_GET
To retrieve the given property item's value.
KSPROPERTY_TYPE_SET
To set the given property item's value.
KSPROPERTY_TYPE_BASICSUPPORT
To determine the type of support available for the property set. The data returned by IKsControl::KsProperty in *pvPropertyData will be a DWORD containing one or both of KSPROPERTY_TYPE_GET and KSPROPERTY_TYPE_SET, indicating which operations are possible.
Alignment
Not used in DirectMusic.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmksctrl.h.

See Also

Port Property Sets


File Structures

This section contains references to data structures used in DirectMusic files. Most applications do not need to know about these structures, because each standard DirectMusic object handles the loading of its own data through its IPersistStream interface. The structures are chiefly of interest for music-authoring applications that need to save data in a format compatible with DirectMusic.

The following structures are used in DirectMusic files:

  • DMUS_IO_BAND_ITEM_HEADER
  • DMUS_IO_BAND_TRACK_HEADER
  • DMUS_IO_CHORD
  • DMUS_IO_CHORDENTRY
  • DMUS_IO_CHORDMAP
  • DMUS_IO_CHORDMAP_SIGNPOST
  • DMUS_IO_CHORDMAP_SUBCHORD
  • DMUS_IO_COMMAND
  • DMUS_IO_CURVE_ITEM
  • DMUS_IO_INSTRUMENT
  • DMUS_IO_MOTIFSETTINGS
  • DMUS_IO_MUTE
  • DMUS_IO_NEXTCHORD
  • DMUS_IO_PARTREF
  • DMUS_IO_PATTERN
  • DMUS_IO_REFERENCE
  • DMUS_IO_SEGMENT_HEADER
  • DMUS_IO_SEQ_ITEM
  • DMUS_IO_SIGNPOST
  • DMUS_IO_STYLE
  • DMUS_IO_STYLECURVE
  • DMUS_IO_STYLENOTE
  • DMUS_IO_STYLEPART
  • DMUS_IO_SUBCHORD
  • DMUS_IO_SYSEX_ITEM
  • DMUS_IO_TEMPO_ITEM
  • DMUS_IO_TIMESIG
  • DMUS_IO_TIMESIGNATURE_ITEM
  • DMUS_IO_TOOL_HEADER
  • DMUS_IO_TRACK_HEADER
  • DMUS_IO_VERSION

See Also

DirectMusic File Format


DMUS_IO_BAND_ITEM_HEADER

The DMUS_IO_BAND_ITEM_HEADER structure contains information about a band change. It is used in the Band Track Form.

typedef struct _DMUS_IO_BAND_ITEM_HEADER {
    MUSIC_TIME lBandTime;
} DMUS_IO_BAND_ITEM_HEADER;

Members

lBandTime
Time of the band change.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicf.h.


DMUS_IO_BAND_TRACK_HEADER

The DMUS_IO_BAND_TRACK_HEADER structure contains information about the default behavior of a band track. It is used in the Band Track Form.

typedef struct _DMUS_IO_BAND_TRACK_HEADER {
    BOOL bAutoDownload;
} DMUS_IO_BAND_TRACK_HEADER;

Members

bAutoDownload
Flag for automatic downloading of instruments when segment is played.

Remarks

For more information on automatic downloading, see Using Bands.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicf.h.


DMUS_IO_CHORD

The DMUS_IO_CHORD structure contains information about a chord change. It is used in the Chord Track List.

typedef struct _DMUS_IO_CHORD {
    WCHAR       wszName[16];
    MUSIC_TIME  mtTime;
    WORD        wMeasure;
    BYTE        bBeat;
} DMUS_IO_CHORD;

Members

wszName
Name of the chord.
mtTime
Time of the chord.
wMeasure
Measure the chord falls on.
bBeat
Beat the chord falls on.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicf.h.


DMUS_IO_CHORDENTRY

The DMUS_IO_CHORDENTRY structure contains information about a chord entry. It is used in the Chordmap Form.

typedef struct _DMUS_IO_CHORDENTRY {
    DWORD   dwFlags;
    WORD    wConnectionID;
} DMUS_IO_CHORDENTRY;

Members

dwFlags
Flag indicating whether the chord is a starting chord (bit 2 set) or an ending chord (bit 3 set) in the chord graph.
wConnectionID
Replaces run-time "pointer to this". Each chord entry is tagged with a unique connection identifier.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicf.h.


DMUS_IO_CHORDMAP

The DMUS_IO_CHORDMAP structure contains information about a chordmap. It is used in the Chordmap Form.

typedef struct _DMUS_IO_CHORDMAP {
    WCHAR   wszLoadName[20];
    DWORD   dwScalePattern;
    DWORD   dwFlags;
} DMUS_IO_CHORDMAP;

Members

wszLoadName
Name of the chordmap, used in the object description when the chordmap is being loaded.
dwScalePattern
The scale associated with the chord map. Each of the lower 24 bits represents a semitone, starting with the root at the least significant bit, and the bit is set if the note is in the scale.
dwFlags
Reserved for future use.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicf.h.


DMUS_IO_CHORDMAP_SIGNPOST

The DMUS_IO_CHORDMAP_SIGNPOST structure contains information about a signpost chord in a chordmap. It is used in the Chordmap Form.

typedef struct _DMUS_IO_CHORDMAP_SIGNPOST {
    DWORD   dwChords;
    DWORD   dwFlags;
} DMUS_IO_CHORDMAP_SIGNPOST;

Members

dwChords
Types of signpost supported by this chord.. The values are used to match against the same values as they appear in templates. Composing from template consists of (among other things) looking for these values in the template and finding actual chords in the chordmap that match these values. The following flags are defined:
DMUS_SIGNPOSTF_A
DMUS_SIGNPOSTF_B
DMUS_SIGNPOSTF_C
DMUS_SIGNPOSTF_D
DMUS_SIGNPOSTF_E
DMUS_SIGNPOSTF_F
DMUS_SIGNPOSTF_LETTER
DMUS_SIGNPOSTF_1
DMUS_SIGNPOSTF_2
DMUS_SIGNPOSTF_3
DMUS_SIGNPOSTF_4
DMUS_SIGNPOSTF_5
DMUS_SIGNPOSTF_6
DMUS_SIGNPOSTF_7
DMUS_SIGNPOSTF_ROOT
DMUS_SIGNPOSTF_CADENCE
dwFlags
Flag defining whether this chord is to be preceded by cadence chords. Signpost chords can have up to two cadence chords. This value can be SPOST_CADENCE1 (first cadence), SPOST_CADENCE2 (second cadence), or a combination of these two flags.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicf.h.

See Also

DMUS_IO_SIGNPOST


DMUS_IO_CHORDMAP_SUBCHORD

The DMUS_IO_CHORDMAP_SUBCHORD structure contains information about a subchord. It is used in the Chordmap Form.

typedef struct _DMUS_IO_CHORDMAP_SUBCHORD {
    DWORD   dwChordPattern;
    DWORD   dwScalePattern;
    DWORD   dwInvertPattern;
    BYTE    bChordRoot;
    BYTE    bScaleRoot;
    WORD    wCFlags;
    DWORD   dwLevels;
} DMUS_IO_CHORDMAP_SUBCHORD;

Members

dwChordPattern
Notes in the subchord. Each of the lower 24 bits represents a semitone, starting with the root at the least significant bit, and the bit is set if the note is in the chord.
dwScalePattern
Notes in the scale. Each of the lower 24 bits represents a semitone, starting with the root at the least significant bit, and the bit is set if the note is in the scale.
dwInvertPattern
Points in the scale where inversions can occur. Bits that are off signify that the notes in the interval cannot be inverted. Thus the pattern 100001111111 indicates that inversions are allowed anywhere except between the fifth and seventh degrees of a major scale.
bChordRoot
Root of the subchord, where 0 is the bottom C in the range and 23 is the top B.
bScaleRoot
Root of the scale, where 0 is the bottom C in the range and 23 is the top B.
wCFlags
Reserved for future use.
dwLevels
Bitfield showing which levels are supported by this subchord. Each part in a style is assigned a level, and this chord will be used only for parts whose levels are contained in this member.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicf.h.

See Also

DMUS_SUBCHORD


DMUS_IO_COMMAND

The DMUS_IO_COMMAND structure contains information about a command event. It is used in the Command Track Chunk.

typedef struct _DMUS_IO_COMMAND {
    MUSIC_TIME  mtTime;
    WORD        wMeasure;
    BYTE        bBeat;
    BYTE        bCommand;
    BYTE        bGrooveLevel;
    BYTE        bGrooveRange;
} DMUS_IO_COMMAND;

Members

mtTime
Time of the command.
wMeasure
Measure the command falls on.
bBeat
Beat the command falls on.
bCommand
Command type. See DMUS_COMMANDT_TYPES.
bGrooveLevel
Groove level, or 0 if command is not a groove command.
bGrooveRange
Amount by which the groove level can be randomized. For instance, if the groove level is 35 and the range is 4, the actual groove level could be anywhere from 33 to 37.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicf.h.


DMUS_IO_CURVE_ITEM

The DMUS_IO_CURVE_ITEM structure contains information about a curve event in a track. It is used in the Sequence Track List.

typedef struct _DMUS_IO_CURVE_ITEM {
    MUSIC_TIME  mtStart;
    MUSIC_TIME  mtDuration;
    MUSIC_TIME  mtResetDuration;
    DWORD       dwPChannel;
    short       nStartValue;
    short       nEndValue;
    short       nResetValue;
    BYTE        bType;
    BYTE        bCurveShape;
    BYTE        bCCData;
    BYTE        bFlags;
} DMUS_IO_CURVE_ITEM;

Members

mtStart
Start time of the curve.
mtDuration
How long the curve lasts.
mtResetDuration
How long after the curve is finished until the reset value is set.
dwPChannel
Performance channel for the event.
nOffset
Offset from the grid boundary at which the curve occurs, in music time. MIDI curves are associated with the closest grid when loaded, so this value can be positive or negative.
nStartValue
Start value.
nEndValue
End value.
nResetValue
Reset value, set after mtResetDuration or upon a flush or invalidation.
bType
Type of curve. The following types are defined:

DMUS_CURVET_PBCURVE
DMUS_CURVET_CCCURVE
DMUS_CURVET_MATCURVE
DMUS_CURVET_PATCURVE

bCurveShape
Shape of curve. The following shapes are defined:

DMUS_CURVES_LINEAR
DMUS_CURVES_INSTANT
DMUS_CURVES_EXP
DMUS_CURVES_LOG
DMUS_CURVES_SINE

bCCData
CC number if this is a control change type.
bFlags
Set to DMUS_CURVE_RESET if the nResetValue must be set when the time is reached or an invalidation occurs because of a transition. If 0, the curve stays permanently at the new value. All other bits are reserved.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicf.h.

See Also

DMUS_IO_SEQ_ITEM


DMUS_IO_INSTRUMENT

The DMUS_IO_INSTRUMENT structure contains information about an instrument. It is used in the Band Form.

typedef struct _DMUS_IO_INSTRUMENT {
    DWORD  dwPatch;
    DWORD  dwAssignPatch;
    DWORD  dwNoteRanges[4];
    DWORD  dwPChannel;
    DWORD  dwFlags;
    BYTE   bPan;
    BYTE   bVolume;
    short  nTranspose;
    DWORD  dwChannelPriority;
} DMUS_IO_INSTRUMENT;

Members

dwPatch
MSB, LSB, and program change to define instrument.
dwAssignPatch
MSB, LSB, and program change to assign to instrument when downloading.
dwNoteRanges
128 bits; one for each MIDI note instrument needs to able to play.
dwPChannel
Performance channel instrument plays on.
dwFlags
Control flags. The following values are defined:
DMUS_IO_INST_ASSIGN_PATCH
dwAssignPatch is valid.
DMUS_IO_INST_BANKSELECT
dwPatch contains a valid bank select, both MSB and LSB.
DMUS_IO_INST_CHANNEL_PRIORITY
dwChannelPriority is valid.
DMUS_IO_INST_GM
Instrument is from the General MIDI collection.
DMUS_IO_INST_GS
Instrument is from the Roland GS collection.
DMUS_IO_INST_NOTERANGES
dwNoteRanges is valid.
DMUS_IO_INST_PAN
bPan is valid.
DMUS_IO_INST_PATCH
dwPatch is valid.
DMUS_IO_INST_TRANSPOSE
nTranspose is valid.
DMUS_IO_INST_USE_DEFAULT_GM_SET
The default General MIDI instrument set should be downloaded to the port even if the port has GM in hardware. If a MIDI file with the XG or GS reset sysex message is parsed, the bank select messages will be sent whether or not GUID_StandardMIDIFile was commanded on the band. In other words, GUID_StandardMIDIFile is effective only for pure GM files.
DMUS_IO_INST_VOLUME
bVolume is valid.
DMUS_IO_INST_XG
Instrument is from the Yamaha XG collection.
bPan
Pan for instrument.
bVolume
Volume for instrument.
nTranspose
Number of semitones to transpose notes.
dwChannelPriority
Channel priority. For a list of defined values, see IDirectMusicPort::GetChannelPriority.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicf.h.


DMUS_IO_MOTIFSETTINGS

The DMUS_IO_MOTIFSETTINGS structure contains information about a motif. It is used in the Style Form.

typedef struct _DMUS_IO_MOTIFSETTINGS {
    DWORD       dwRepeats;
    MUSIC_TIME  mtPlayStart;
    MUSIC_TIME  mtLoopStart;
    MUSIC_TIME  mtLoopEnd;
    DWORD       dwResolution;
} DMUS_IO_MOTIFSETTINGS;

Members

dwRepeats
Number of repetitions.
mtPlayStart
Start of playback, normally 0.
mtLoopStart
Start of looping portion, normally 0.
mtLoopEnd
End of looping portion.
dwResolution
Default resolution. See DMUS_TIME_RESOLVE_FLAGS.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicf.h.

See Also

IDirectMusicSegment::SetLoopPoints


DMUS_IO_MUTE

The DMUS_IO_MUTE structure contains information about a mute event on a channel. It is used in the Mute Track Chunk.

typedef struct _DMUS_IO_MUTE {
    MUSIC_TIME  mtTime;
    DWORD       dwPChannel;
    DWORD       dwPChannelMap;
} DMUS_IO_MUTE;

Members

mtTime
Time of the event.
dwPChannel
Performance channel to mute or remap.
dwPChannelMap
Channel to which dwPChannel is being mapped, or 0xFFFFFFFF if dwPChannel is to be muted.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicf.h.

See Also

DMUS_MUTE_PARAM


DMUS_IO_NEXTCHORD

The DMUS_IO_NEXTCHORD stucture contains information about the next chord in a chord graph. It is used in the Chordmap Form.

typedef struct _DMUS_IO_NEXTCHORD {
    DWORD   dwFlags;
    WORD    nWeight;
    WORD    wMinBeats;
    WORD    wMaxBeats;
    WORD    wConnectionID;
} DMUS_IO_NEXTCHORD;

Members

dwFlags
Reserved for future use.
nWeight
Likelihood (in the range 1-100) that this link will be followed when traversing the chord graph.
wMinBeats
Smallest number of beats that this chord is allowed to play in a composed segment.
wMaxBeats
Largest number of beats that this chord is allowed to play in a composed segment.
wConnectionID
Refers to the wConnectionID member of a DMUS_IO_CHORDENTRY structure.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicf.h.


DMUS_IO_PARTREF

The DMUS_IO_PARTREF structure contains information about a part reference. It is used in the Style Form.

typedef struct _DMUS_IO_PARTREF {
    GUID  guidPartID;
    WORD  wLogicalPartID;
    BYTE  bVariationLockID;
    BYTE  bSubChordLevel;
    BYTE  bPriority;
    BYTE  bRandomVariation;
} DMUS_IO_PARTREF;

Members

guidPartID
Identifier of part.
wLogicalPartID
Identifier corresponding to a particular MIDI channel on a port.
bVariationLockID
Parts with the same value in this member always play the same variation.
bSubChordLevel
Subchord level this part wants. See Remarks.
bPriority
Priority of the part. For information on priorities, see Channels.
bRandomVariation
When set, matching variations play in random order. When clear, matching variations play sequentially.

Remarks

The bSubChordLevel member contains a zero-based index value. At run time, 1 is shifted left by this value to yield a single-bit value for comparison with the dwLevels member of a DMUS_SUBCHORD structure. Thus a part with a bSubChordLevel of 0 would be mapped to any subchord that contained 1 in dwLevels.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicf.h.


DMUS_IO_PATTERN

The DMUS_IO_PATTERN structure contains information about a pattern. It is used in the Style Form.

typedef struct _DMUS_IO_PATTERN {
    DMUS_IO_TIMESIG  timeSig;
    BYTE             bGrooveBottom;
    BYTE             bGrooveTop;
    WORD             wEmbellishment;
    WORD             wNbrMeasures;
} DMUS_IO_PATTERN;

Members

timeSig
DMUS_IO_TIMESIG structure containing a time signature to override the style's default time signature.
bGrooveBottom
Bottom of groove range.
bGrooveTop
Top of groove range.
wEmbellishment
Type of embellishment. See DMUS_COMMANDT_TYPES.
wNbrMeasures
Length of the pattern in measures.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicf.h.


DMUS_IO_REFERENCE

The DMUS_IO_REFERENCE structure contains information about a reference to another object that might be stored in another file. It is used in the reference list chunk. See Common Chunks.

typedef struct _DMUS_IO_REFERENCE {
    GUID    guidClassID;
    DWORD   dwValidData;
} DMUS_IO_REFERENCE;

Members

guidClassID
Class identifier.
dwValidData
Flags to indicate which data chunks for the reference are present. For a list of values, see the corresponding member of DMUS_OBJECTDESC.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicf.h.


DMUS_IO_SEGMENT_HEADER

The DMUS_IO_SEGMENT_HEADER structure contains information about a segment. It is used in the Segment Form.

typedef struct _DMUS_IO_SEGMENT_HEADER {
    DWORD       dwRepeats;
    MUSIC_TIME  mtLength;
    MUSIC_TIME  mtPlayStart;
    MUSIC_TIME  mtLoopStart;
    MUSIC_TIME  mtLoopEnd;
    DWORD       dwResolution;
} DMUS_IO_SEGMENT_HEADER;

Members

dwRepeats
Number of repetitions.
mtLength
Length of the segment.
mtPlayStart
Start of playback, normally 0.
mtLoopStart
Start of looping portion, normally 0.
mtLoopEnd
End of looping portion.
dwResolution
Default resolution. See DMUS_TIME_RESOLVE_FLAGS.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicf.h.

See Also

DMUS_IO_MOTIFSETTINGS, IDirectMusicSegment::SetLoopPoints.


DMUS_IO_SEQ_ITEM

The DMUS_IO_SEQ_ITEM structure contains information about an item of data in a sequence track. It is used in the Sequence Track List.

typedef struct _DMUS_IO_SEQ_ITEM {
    MUSIC_TIME  mtTime;
    MUSIC_TIME  mtDuration;
    DWORD       dwPChannel;
    short       nOffset
    BYTE        bStatus;
    BYTE        bByte1;
    BYTE        bByte2;
} DMUS_IO_SEQ_ITEM;

Members

mtTime
Time of the event.
mtDuration
Duration for which the event is valid.
dwPChannel
Performance channel for the event.
nOffset
Offset from the grid boundary at which the note is played, in music time. MIDI notes are associated with the closest grid when loaded, so this value can be positive or negative.
bStatus
MIDI event type. Equivalent to the MIDI status byte, but without channel information.
bByte1
First byte of the MIDI data.
bByte2
Second byte of the MIDI data.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicf.h.

See Also

DMUS_IO_CURVE_ITEM, MIDI Messages


DMUS_IO_SIGNPOST

The DMUS_IO_SIGNPOST structure contains information about a signpost in a signpost track, in order to associate it with signpost chords in a chordmap. It is used in the Signpost Track Chunk.

typedef struct _DMUS_IO_SIGNPOST {
    MUSIC_TIME  mtTime;
    DWORD       dwChords;
    WORD        wMeasure;
} DMUS_IO_SIGNPOST;

Members

mtTime
Time of the signpost.
dwChords
Types of signpost chords allowed to be associated with this signpost. The values are used to match against the same values as they appear in templates. Composing from template consists of (among other things) looking for these values in the template and finding actual chords in the chordmap that match these values. The following flags are defined:
DMUS_SIGNPOSTF_A
DMUS_SIGNPOSTF_B
DMUS_SIGNPOSTF_C
DMUS_SIGNPOSTF_D
DMUS_SIGNPOSTF_E
DMUS_SIGNPOSTF_F
DMUS_SIGNPOSTF_LETTER
DMUS_SIGNPOSTF_1
DMUS_SIGNPOSTF_2
DMUS_SIGNPOSTF_3
DMUS_SIGNPOSTF_4
DMUS_SIGNPOSTF_5
DMUS_SIGNPOSTF_6
DMUS_SIGNPOSTF_7
DMUS_SIGNPOSTF_ROOT
DMUS_SIGNPOSTF_CADENCE
wMeasure
Measure on which the signpost falls.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicf.h.

See Also

DMUS_IO_CHORDMAP_SIGNPOST


DMUS_IO_STYLE

The DMUS_IO_STYLE structure contains information about the time signature and tempo of a style. It is used in the Style Form.

typedef struct _DMUS_IO_STYLE {
    DMUS_IO_TIMESIG  timeSig;
    double           dblTempo;
} DMUS_IO_STYLE;

Members

timeSig
DMUS_IO_TIMESIG structure containing the default time signature for the style.
dblTempo
Tempo of the style.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicf.h.


DMUS_IO_STYLECURVE

The DMUS_IO_STYLECURVE structure contains information about a curve in a style. It is used in the Style Form.

typedef struct _DMUS_IO_STYLECURVE {
    MUSIC_TIME  mtGridStart;
    DWORD       dwVariation;
    MUSIC_TIME  mtDuration;
    MUSIC_TIME  mtResetDuration;
    short       nTimeOffset;
    short       nStartValue;
    short       nEndValue;
    short       nResetValue;
    BYTE        bEventType;
    BYTE        bCurveShape;
    BYTE        bCCData;
    BYTE        bFlags;
} DMUS_IO_STYLECURVE;

Members

mtGridStart
Start time of the grid in which the curve occurs.
dwVariation
Which variations this curve belongs to. Each bit corresponds to one of 32 variations.
mtDuration
How long the curve lasts.
mtResetDuration
How long after the curve is finished until the reset value is set.
nTimeOffset
Offset from mtGridStart at which the curve occurs.
nStartValue
Start value.
nEndValue
End value.
nResetValue
Reset value, set after mtResetDuration or upon a flush or invalidation.
bEventType
Type of curve. The following types are defined:

DMUS_CURVET_PBCURVE
DMUS_CURVET_CCCURVE
DMUS_CURVET_MATCURVE
DMUS_CURVET_PATCURVE

bCurveShape
Shape of curve. The following shapes are defined:

DMUS_CURVES_LINEAR
DMUS_CURVES_INSTANT
DMUS_CURVES_EXP
DMUS_CURVES_LOG
DMUS_CURVES_SINE

bCCData
CC number if this is a control change type.
bFlags
Set to DMUS_CURVE_RESET if the nResetValue must be set when the time is reached or an invalidation occurs because of a transition. If 0, the curve stays permanently at the new value. All other bits are reserved.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicf.h.

See Also

DMUS_CURVE_PMSG, DMUS_IO_CURVE_ITEM


DMUS_IO_STYLENOTE

The DMUS_IO_STYLENOTE structure contains information about a note in a style. It is used in the Style Form.

typedef struct _DMUS_IO_STYLENOTE {
    MUSIC_TIME  mtGridStart;
    DWORD       dwVariation;
    MUSIC_TIME  mtDuration;
    short       nTimeOffset;
    WORD        wMusicValue;
    BYTE        bVelocity;
    BYTE        bTimeRange;
    BYTE        bDurRange;
    BYTE        bVelRange;
    BYTE        bInversionID;
    BYTE        bPlayModeFlags;
} DMUS_IO_STYLENOTE;

Members

mtGridStart
When the note occurs.
dwVariation
Which variations this note belongs to. Each bit corresponds to one of 32 variations.
mtDuration
How long the note lasts.
nTimeOffset
Offset from mtGridStart.
wMusicValue
Position in scale.
bVelocity
Note velocity.
bTimeRange
Range within which to randomize start time.
bDurRange
Range within which to randomize duration.
bVelRange;
Range within which to randomize velocity.
bInversionID
Identifier of inversion group to which this note belongs.
bPlayModeFlags
Flags to override the play mode of the part. For a list of values, see DMUS_PLAYMODE_FLAGS.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicf.h.


DMUS_IO_STYLEPART

The DMUS_IO_STYLEPART structure contains information about a musical part. It is used in the Style Form.

typedef struct _DMUS_IO_STYLEPART {
    DMUS_IO_TIMESIG  timeSig;
    DWORD            dwVariationChoices[32];
    GUID             guidPartID;
    WORD             wNbrMeasures;
    BYTE             bPlayModeFlags;
    BYTE             bInvertUpper;
    BYTE             bInvertLower;
} DMUS_IO_STYLEPART;

Members

timeSig
DMUS_IO_TIMESIG structure containing a time signature to override the style's default time signature.
dwVariationChoices
Each word corresponds to one of 32 possible variations. The flags set in each word indicate which types of chord are supported by that variation (see Remarks). The following flags are defined:
DMUS_VARIATIONF_MAJOR
Seven positions in the scale for major chords.
DMUS_VARIATIONF_MINOR
Seven positions in the scale for minor chords.
DMUS_VARIATIONF_OTHER
Seven positions in the scale for other chords.
DMUS_VARIATIONF_ROOT_SCALE
Handles chord roots in the scale.
DMUS_VARIATIONF_ROOT_FLAT
Handles flat chord roots (based on scale notes).
DMUS_VARIATIONF_ROOT_SHARP
Handles sharp chord roots (based on scale notes).
DMUS_VARIATIONF_TYPE_TRIAD
Handles simple chords for triads.
DMUS_VARIATIONF_TYPE_6AND7
Handles simple chords for 6 and 7.
DMUS_VARIATIONF_TYPE_COMPLEX
Handles complex chords.
DMUS_VARIATIONF_DEST_TO1
Handles transitions to 1 chord.
DMUS_VARIATIONF_DEST_TO5
Handles transitions to 5 chord.
DMUS_VARIATIONF_MODES
DMUS_VARIATIONF_IMA25_MODE
DMUS_VARIATIONF_DMUS_MODE
One of these flags is set to indicate the mode. For DirectMusic, this value should always be DMUS_VARIATIONF_DMUS_MODE.
guidPartID
Unique identifier of the part.
wNbrMeasures
Length of the part, in measures.
bPlayModeFlags
Flags to define the play mode. For a list of values, see DMUS_PLAYMODE_FLAGS.
bInvertUpper
Upper limit of inversion.
bInvertLower
Lower limit of inversion.

Remarks

The flags in dwVariationChoices determine the types of chords supported by a given variation in DirectMusic mode. The first seven flags (bits 1-7) are set if the variation supports major chords rooted in scale positions. For example, if bits 1, 2, and 4 are set, the variation supports major chords rooted in the tonic, second, and fourth scale positions. The next seven flags serve the same purpose, but for minor chords, and the following seven flags serve the same purpose for chords that are not major or minor (for example, SUS 4 chords). Bits 22, 23, and 24 are set if the variation supports chords rooted in the scale, chords rooted sharp of scale tones, and chords rooted flat of scale tones, respectively. For example, to support a C# minor chord in the scale of C major, bits 8 (for tonic minor) and 24 (for sharp) need to be set. Bits 25, 26, an 27 handle chords that are triads, 6th or 7th chords, and chords with extensions, respectively. Bits 28 and 29 handle chords that are followed by tonic and dominant chords, respectively.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicf.h.


DMUS_IO_SUBCHORD

The DMUS_IO_SUBCHORD structure contains information about a subchord. It is used in the Chord Track List.

typedef struct _DMUS_IO_SUBCHORD {
    DWORD   dwChordPattern;
    DWORD   dwScalePattern;
    DWORD   dwInversionPoints;
    DWORD   dwLevels;
    BYTE    bChordRoot;
    BYTE    bScaleRoot;
} DMUS_IO_SUBCHORD;

Members

dwChordPattern
Notes in the subchord. Each of the lower 24 bits represents a semitone, starting with the root at the least significant bit, and the bit is set if the note is in the chord.
dwScalePattern
Notes in the scale. Each of the lower 24 bits represents a semitone, starting with the root at the least significant bit, and the bit is set if the note is in the scale.
dwInversionPoints
Points in the scale where inversions can occur. Bits that are off signify that the notes in the interval cannot be inverted. Thus the pattern 100001111111 indicates that inversions are allowed anywhere except between the fifth and seventh degrees of a major scale.
dwLevels
Which levels are supported by this subchord. Certain instruments may be assigned different levels (such as to play only the lower subchords of a chord), and this value is a way of mapping subchords to those levels.
bChordRoot
Root of the subchord, where 0 is the bottom C in the range and 23 is the top B.
bScaleRoot
Root of the scale, where 0 is the bottom C in the range and 23 is the top B.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicf.h.

See Also

DMUS_SUBCHORD


DMUS_IO_SYSEX_ITEM

The DMUS_IO_SYSEX_ITEM structure contains information about a system-exclusive MIDI message. It is used in the Sysex Track Chunk.

typedef struct _DMUS_IO_SYSEX_ITEM {
    MUSIC_TIME  mtTime;
    DWORD       dwPChannel;
    DWORD       dwSysExLength;
} DMUS_IO_SYSEX_ITEM;

Members

mtTime
Time of the message.
dwPChannel
Performance channel of the event.
dwSysExLength
Length of the data, in bytes.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicf.h.

See Also

MIDI System Messages


DMUS_IO_TEMPO_ITEM

The DMUS_IO_TEMPO_ITEM structure contains information about a tempo change in a track. It is used in the Tempo Track Chunk.

typedef struct _DMUS_IO_TEMPO_ITEM {
    MUSIC_TIME  mtTime;
    double      dblTempo;
} DMUS_IO_TEMPO_ITEM;

Members

mtTime
Time of the tempo change.
dblTempo
Tempo, in beats per minute.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicf.h.


DMUS_IO_TIMESIG

The DMUS_IO_TIMESIG structure contains information about the time signature of a segment. It is used in the DMUS_IO_STYLE, DMUS_IO_VERSION, and DMUS_IO_PATTERN structures.

typedef struct _DMUS_IO_TIMESIG {
    BYTE  bBeatsPerMeasure;
    BYTE  bBeat;
    WORD  wGridsPerBeat;
} DMUS_IO_TIMESIG;

Members

bBeatsPerMeasure
Beats per measure (top of time signature).
bBeat
What note receives the beat (bottom of the time signature), where 1 is a whole note, 2 is a half note, 4 is a quarter note, and so on. Zero is a 256th note.
wGridsPerBeat
Grids (subdivisions) per beat.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicf.h.

See Also

DMUS_IO_TIMESIGNATURE_ITEM


DMUS_IO_TIMESIGNATURE_ITEM

The DMUS_IO_TIMESIGNATURE_ITEM structure contains information about a time signature change. It is used in the Time Signature Track Chunk.

typedef struct _DMUS_IO_TIMESIGNATURE_ITEM {
    MUSIC_TIME  mtTime;
    BYTE        bBeatsPerMeasure;
    BYTE        bBeat;
    WORD        wGridsPerBeat;
} DMUS_IO_TIMESIGNATURE_ITEM;

Members

mtTime
Time of the event.
bBeatsPerMeasure
Beats per measure (top of time signature).
bBeat
What note receives the beat (bottom of the time signature), where 1 is a whole note, 2 is a half note, 4 is a quarter note, and so on. Zero is a 256th note.
wGridsPerBeat
Grids (subdivisions) per beat.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicf.h.

See Also

DMUS_IO_TIMESIG, DMUS_TIMESIG_PMSG


DMUS_IO_TOOL_HEADER

The DMUS_IO_TOOL_HEADER structure contains information about a tool. It is used in the Tool Form.

typedef struct _DMUS_IO_TOOL_HEADER {
    GUID    guidClassID;
    long    lIndex;
    DWORD   cPChannels;
    FOURCC  ckid;
    FOURCC  fccType;
    DWORD   dwPChannels[1];
} DMUS_IO_TOOL_HEADER;

Members

guidClassID
Class identifier of tool.
lIndex
Position in graph.
cPChannels
Number of items in dwPChannels array.
ckid
Identifier of tool's data chunk. If this value is zero, it is assumed that the chunk is of type LIST, so fccType is valid and must be nonzero.
fccType
List type. If this value is zero, ckid is valid and must be nonzero.
dwPChannels
Array of performance channels for which the tool is valid.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicf.h.

See Also

IDirectMusicGraph::InsertTool


DMUS_IO_TRACK_HEADER

The DMUS_IO_TRACK_HEADER structure contains information about a track. It is used in the Track Form.

typedef struct _DMUS_IO_TRACK_HEADER {
    GUID     guidClassID;
    DWORD    dwPosition;
    DWORD    dwGroup;
    FOURCC   ckid;
    FOURCC   fccType;
} DMUS_IO_TRACK_HEADER;

Members

guidClassID
Class identifier of track.
dwPosition
Position in track list.
dwGroup
Group bits for track.
ckid
Identifier of track's data chunk. If this value is zero, it is assumed that the chunk is of type LIST, so fccType is valid and must be nonzero.
fccType
List type. If this value is zero, ckid is valid and must be nonzero.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicf.h.

See Also

IDirectMusicSegment::GetTrackGroup, IDirectMusicSegment::InsertTrack, Track Form


DMUS_IO_VERSION

The DMUS_IO_VERSION structure contains the version number of the data. It is used in the version subchunk of various chunks. See Common Chunks.

typedef struct _DMUS_IO_VERSION {
    DWORD  dwVersionMS;
    DWORD  dwVersionLS;
} DMUS_IO_VERSION;

Members

dwVersionMS
High-order 32 bits of version number.
dwVersionLS
Low-order 32 bits of version number.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicf.h.


DLS Structures

This section contains reference information for structures used with downloadable sounds. Most applications do not need to use these structures, as DirectMusic handles the details of loading DLS collections and downloading instruments to the synthesizer. They are of interest chiefly for DLS-editing applications.

For an overview of using DLS data, see Low-Level DLS.

For more information on DLS data formats, see the specification from the MIDI Manufacturers Association.

The following structures are included in this section:

  • DMUS_ARTICPARAMS
  • DMUS_ARTICULATION
  • DMUS_COPYRIGHT
  • DMUS_DOWNLOADINFO
  • DMUS_EXTENSIONCHUNK
  • DMUS_INSTRUMENT
  • DMUS_LFOPARAMS
  • DMUS_MSCPARAMS
  • DMUS_OFFSETTABLE
  • DMUS_PEGPARAMS
  • DMUS_REGION
  • DMUS_VEGPARAMS
  • DMUS_WAVE
  • DMUS_WAVEDATA


DMUS_ARTICPARAMS

The DMUS_ARTICPARAMS structure describes parameters for a DLS articulation chunk. All parameters for articulation are stored in one chunk, which is composed of a series of structures that define each functional area of the articulation. If an instrument or region uses articulation, it references this chunk by index from the DMUS_ARTICULATION chunk.

typedef struct {
    DMUS_LFOPARAMS LFO;
    DMUS_VEGPARAMS VolEG;
    DMUS_PEGPARAMS PitchEG;
    DMUS_MSCPARAMS Misc;
} DMUS_ARTICPARAMS;

Members

LFO
DMUS_LFOPARAMS structure containing parameters for low-frequency oscillator.
VolEG
DMUS_VEGPARAMS structure containing parameters for volume envelope generator.
PitchEG
DMUS_PEGPARAMS structure containing parameters for pitch envelope generator.
Misc
DMUS_MSCPARAMS structure containing initial pan position.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmdls.h.


DMUS_ARTICULATION

The DMUS_ARTICULATION structure describes a DLS instrument articulation chunk. This chunk connects all available DLS articulation data in one list. For example, it might have a DLS Level 1 chunk and a manufacturer's proprietary articulation chunk. The DLS chunk is referenced by ulArt1Idx, while all additional articulation chunks are referenced by the list that starts with ulFirstExtCkIdx.

typedef struct {
    ULONG ulArt1Idx;
    ULONG ulFirstExtCkIdx;
} DMUS_ARTICULATION;

Members

ulArt1Idx
Index, in the DMUS_OFFSETTABLE, of the DLS articulation chunk. If 0, there is no DLS articulation.
ulFirstExtCkIdx
Index of the first third-party extension chunk. If 0, there are no third-party extension chunks associated with the articulation.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmdls.h.


DMUS_COPYRIGHT

The DMUS_COPYRIGHT structure describes an optional copyright chunk in DLS data.

typedef struct {
    ULONG cbSize;
    BYTE  byCopyright[ ];
} DMUS_COPYRIGHT;

Members

cbSize
Size of data.
byCopyright[ ]
Copyright data.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmdls.h.


DMUS_DOWNLOADINFO

The DMUS_DOWNLOADINFO structure is used as a header for DLS data to be downloaded to a port. It defines the size and functionality of the download and is always followed by a DMUS_OFFSETTABLE chunk.

typedef struct _DMUS_DOWNLOADINFO {
    DWORD dwDLType;
    DWORD dwDLId;
    DWORD dwNumOffsetTableEntries;
    DWORD cbSize;
} DMUS_DOWNLOADINFO;

Members

dwDLType
Type of data being downloaded. The following types are defined:
DMUS_DOWNLOADINFO_INSTRUMENT
Instrument definition, starting with the DMUS_INSTRUMENT structure
DMUS_DOWNLOADINFO_WAVE
PCM wave data, starting with the DMUS_WAVE structure.
dwDLId
Unique 32-bit identifier for the object. See Remarks.
dwNumOffsetTableEntries
Number of entries in the DMUS_OFFSETTABLE structure that follows.
cbSize
Size of this memory chunk, inlcuding the offset table.

Remarks

The identifier in dwDLId is used to connect objects together and is obtained by using the IDirectMusicPortDownload::GetDLId method. Primarily it connects the regions in an instrument to wave chunks. For example, suppose a wave download is given a dwDLId of 3. Then an instrument chunk downloads with the value 3 placed in the WaveLink.ulTableIndex member of one of its DMUS_REGION structures. This indicates that the region is connected to the wave chunk.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmdls.h.

See Also

Low-Level DLS


DMUS_EXTENSIONCHUNK

The DMUS_EXTENSIONCHUNK structure describes a DLS extension chunk. All extensions to the DLS file format that are unknown to DirectMusic are downloaded in this variable-size chunk.

typedef struct {
    ULONG  cbSize;
    ULONG  ulNextExtCkIdx;
    FOURCC ExtCkID;
    BYTE   byExtCk[ ];
} DMUS_EXTENSIONCHUNK;

Members

cbSize
Size of chunk.
ulNextExtCkIdx
Index, in the DMUS_OFFSETTABLE, of the next extension chunk. If 0, there are no more third-party extension chunks
ExtCkID
Chunk identifier.
byExtCk[ ]
Data.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmdls.h.


DMUS_INSTRUMENT

The DMUS_INSTRUMENT structure contains an instrument definition in a DLS download chunk.

typedef struct {
    ULONG ulPatch;
    ULONG ulFirstRegionIdx;
    ULONG ulGlobalArtIdx;
    ULONG ulFirstExtCkIdx;
    ULONG ulCopyrightIdx;
    ULONG ulFlags;
} DMUS_INSTRUMENT;

Members

ulPatch
Patch number of instrument.
ulFirstRegionIdx
Index of first region chunk (see DMUS_REGION) within the instrument. There should always be a region, but for compatibility with future synthesizer architectures it is acceptable to have 0 in this member.
ulGlobalArtIdx
Index, in the DMUS_OFFSETTABLE, of the global articulation chunk (see DMUS_ARTICULATION) for the instrument. If 0, the instrument does not have global articulation.
ulFirstExtCkIdx
Index, in the DMUS_OFFSETTABLE, of the first extension chunk (see DMUS_EXTENSIONCHUNK) within the instrument. This is used to add new chunks that DirectMusic is unaware of. If 0, no third-party extension chunks associated with the instrument.
ulCopyrightIdx
Index, in the DMUS_OFFSETTABLE, of an optional copyright chunk (see DMUS_COPYRIGHT). If 0, no copyright information is associated with the instrument.
ulFlags
Additional flags for the instrument. The following flag is defined:
DMUS_INSTRUMENT_GM_INSTRUMENT
The instrument is a standard General MIDI instrument. In the case of patch overlap, GM instruments always have lower priority than other DLS instruments. For example, if a GM instrument is downloaded with patch 0 and a non-GM instrument is also downloaded at patch 0, the non-GM instrument is always selected for playback.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmdls.h.


DMUS_LFOPARAMS

The DMUS_LFOPARAMS structure defines the low-frequency oscillator for a DLS articulation chunk. It is used in the DMUS_ARTICPARAMS structure.

typedef struct {
    PCENT pcFrequency;
    TCENT tcDelay;
    GCENT gcVolumeScale;
    PCENT pcPitchScale;
    GCENT gcMWToVolume;
    PCENT pcMWToPitch;
} DMUS_LFOPARAMS;

Members

pcFrequency
Frequency, in pitch units. See Remarks.
tcDelay
Initial delay, in time cents. See Remarks.
gcVolumeScale
Scaling of output to control tremolo, in attenuation units. See Remarks.
pcPitchScale
Scaling of LFO output to control vibrato, in pitch units. See Remarks.
gcMWToVolume
Mod wheel range for controlling tremolo, in attenuation units. See Remarks.
pcMWToPitch
Mod wheel range for controlling tremolo, in attenuation units. See Remarks.

Remarks

The DLS Level 1 specification defines time cents, pitch cents, and attenuation as 32-bit logarithmic values. See the specification from the MIDI Manufacturers Association for details.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmdls.h.

See Also

DMUS_ARTICPARAMS


DMUS_MSCPARAMS

The DMUS_MSCPARAMS structure defines the pan for a DLS articulation chunk. It is used in the DMUS_ARTICPARAMS structure.

typedef struct {
    PERCENT ptDefaultPan;
} DMUS_MSCPARAMS;

Members

ptDefaultPan
Default pan, ranging from -50 to 50 percent in units of 0.1 percent shifted left by 16.

Remarks

PERCENT is defined as long. For more information about pan values, see the DLS specification from the MIDI Manufacturers Association.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmdls.h.

See Also

DMUS_ARTICPARAMS


DMUS_OFFSETTABLE

The DMUS_OFFSETTABLE structure is used in the header of DLS instrument data being downloaded to a port.

typedef struct _DMUS_OFFSETTABLE {
    ULONG ulOffsetTable[DMUS_DEFAULT_SIZE_OFFSETTABLE];
} DMUS_OFFSETTABLE;

Members

ulOffsetTable
Array of indices into the data.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmdls.h.

See Also

Low-Level DLS


DMUS_PEGPARAMS

The DMUS_PEGPARAMS structure defines the pitch envelope for a DLS articulation chunk. It is used in the DMUS_ARTICPARAMS structure.

typedef struct {
    TCENT   tcAttack;
    TCENT   tcDecay;
    PERCENT ptSustain;
    TCENT   tcRelease;
    TCENT   tcVel2Attack;
    TCENT   tcKey2Decay;
    PCENT   pcRange;
} DMUS_PEGPARAMS;

Members

tcAttack
Attack time, in time cents. See Remarks.
tcDecay
Decay time, in time cents. See Remarks.
ptSustain
Sustain, in hundredths of a percent shifted left by 16.
tcRelease
Release time, in time cents. See Remarks.
tcVel2Attack
Velocity to attack, in time cents. See Remarks.
tcKey2Decay
Key to decay, in time cents. See Remarks.
pcRange
Envelope range, in pitch units. See Remarks.

Remarks

The DLS Level 1 specification defines time cents and pitch cents as 32-bit logarithmic values. See the specification from the MIDI Manufacturers Association for details about the values in this structure.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmdls.h.

See Also

DMUS_ARTICPARAMS


DMUS_REGION

The DMUS_REGION structure defines a region for a DLS download. One or more regions can be embedded in an instrument buffer and referenced by the the instrument header chunk, DMUS_INSTRUMENT.

typedef struct {
    RGNRANGE RangeKey;
    RGNRANGE RangeVelocity;
    USHORT   fusOptions;
    USHORT   usKeyGroup;
    ULONG    ulRegionArtIdx;
    ULONG    ulNextRegionIdx;
    ULONG    ulFirstExtCkIdx;
    WAVELINK WaveLink;
    WSMPL    WSMP;
    WLOOP    WLOOP[1];
} DMUS_REGION;

Members

RangeKey
Key range for this region.
RangeVelocity
Velocity range for this region.
fusOptions
Options for the synthesis of this region. The following flag is defined:
F_RGN_OPTION_SELFNONEXCLUSIVE
If a second note-on of the same note is received by the synthesis engine, the second note will be played as well as the first. This option is off by default, so that the synthesis engine will force a note-off of the first note.
usKeyGroup
Key group for a drum instrument. Key group values allow multiple regions within a drum instrument to belong to the same group. If a synthesis engine is instructed to play a note with a key group setting and any other notes are currently playing with this same key group, the synthesis engine should turn off all notes with the same key group value as soon as possible. Currently key groups 1 through 15 are legal, and 0 indicates no key group.
ulRegionArtIdx
Index, in the DMUS_OFFSETTABLE, of the global articulation chunk for the region. If 0, the region does not have an articulation and relies on the instrument's global articulation.
ulNextRegionIdx
Index, in the DMUS_OFFSETTABLE, of the next region in the region list. If 0, there no more regions.
ulFirstExtCkIdx
Index, in the DMUS_OFFSETTABLE, of the third-party extension chunk list. If 0, no extension chunks are associated with the region.
WaveLink
Standard DLS structure (declared in Dls1.h) for managing a link from the region to a wave. The ulTableIndex member of the WAVELINK structure contains the download identifier of the associated wave buffer. (For more information, see DMUS_DOWNLOADINFO and Low-Level DLS.)
WSMP
Standard DLS structure (declared in Dls1.h) for managing the playback of the wave. If the cSampleLoops member is 1, the following WLOOP structure carries the loop start and end points.
WLOOP
Standard DLS structure (declared in Dls1.h) for describing a loop.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmdls.h.


DMUS_VEGPARAMS

The DMUS_VEGPARAMS structure defines a volume envelope for a DLS articulation chunk.

typedef struct {
    TCENT   tcAttack;
    TCENT   tcDecay;
    PERCENT ptSustain;
    TCENT   tcRelease;
    TCENT   tcVel2Attack;
    TCENT   tcKey2Decay;
} DMUS_VEGPARAMS;

Members

tcAttack
Attack time, in time cents. See Remarks.
tcDecay
Decay time, in time cents. See Remarks.
ptSustain
Sustain, measured in hundredths of a percent and shifted left by 16.
tcRelease
Release time, in time cents. See Remarks.
tcVel2Attack
Velocity to attack, in time cents. See Remarks.
tcKey2Decay
Key to decay, in time cents. See Remarks.

Remarks

The DLS Level 1 specification defines time cents as a 32-bit logarithmic value. See the specification from the MIDI Manufacturers Association for details about the values in this structure.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmdls.h.

See Also

DMUS_ARTICPARAMS


DMUS_WAVE

The DMUS_WAVE structure defines a wave chunk for a DLS download.

typedef struct {
    ULONG  ulFirstExtCkIdx;
    ULONG  ulCopyrightIdx;
    ULONG  ulWaveDataIdx;
    WAVEFORMATEX   WaveformatEx;
} DMUS_WAVE;

Members

ulFirstExtCkIdx
Index, in the DMUS_OFFSETTABLE, of third-party extension chunks. If 0, no extension chunks are associated with the wave.
ulCopyrightIdx
Index, in the DMUS_OFFSETTABLE, of copyright chunks. If 0, no copyright information is associated with the wave.
ulWaveDataIdx
Index, in the DMUS_OFFSETTABLE, of wave data. See DMUS_WAVEDATA.
WaveformatEx
Wave format of the chunk.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmdls.h.


DMUS_WAVEDATA

The DMUS_WAVEDATA structure comprises a data chunk for a DLS wave download. The nature of the wave data is defined by the WAVEFORMATEX chunk, embedded in DMUS_WAVE.

typedef struct {
    ULONG cbSize;
    BYTE byData[ ];
} DMUS_WAVEDATA;

Members

cbSize
Size of data.
byData[ ]
PCM wave data.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmdls.h.


Enumerated Types

This section contains references for the following enumerated types:

  • DMUS_CLOCKTYPE
  • DMUS_COMMANDT_TYPES
  • DMUS_COMPOSEF_FLAGS
  • DMUS_NOTEF_FLAGS
  • DMUS_PLAYMODE_FLAGS
  • DMUS_PMSGF_FLAGS
  • DMUS_PMSGT_TYPES
  • DMUS_SEGF_FLAGS
  • DMUS_SHAPET_TYPES
  • DMUS_TIME_RESOLVE_FLAGS
  • DMUS_TRACKF_FLAGS


DMUS_CLOCKTYPE

The members of the DMUS_CLOCKTYPE enumeration are used in the ctType member of the DMUS_CLOCKINFO structure.

typedef enum {
    DMUS_CLOCK_SYSTEM = 0,
    DMUS_CLOCK_WAVE   = 1
} DMUS_CLOCKTYPE;

Members

DMUS_CLOCK_SYSTEM
The clock is the system clock.
DMUS_CLOCK_WAVE
The clock is on a wave playback device.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusicc.h.


DMUS_COMMANDT_TYPES

The members of the DMUS_COMMANDT_TYPES enumeration are used in the wCommand parameter of the IDirectMusicComposer::AutoTransition and IDirectMusicComposer::ComposeTransition methods and in the bCommand member of the DMUS_COMMAND_PARAM structure.

enum enumDMUS_COMMANDT_TYPES {
    DMUS_COMMANDT_GROOVE      = 0,
    DMUS_COMMANDT_FILL        = 1,
    DMUS_COMMANDT_INTRO       = 2,
    DMUS_COMMANDT_BREAK       = 3,
    DMUS_COMMANDT_END         = 4,
    DMUS_COMMANDT_ENDANDINTRO = 5
} DMUS_COMMANDT_TYPES;

Members

DMUS_COMMANDT_GROOVE
The command is a groove command.
DMUS_COMMANDT_FILL
The command is a fill.
DMUS_COMMANDT_INTRO
The command is an intro.
DMUS_COMMANDT_BREAK
The command is a break.
DMUS_COMMANDT_END
The command is an ending.
DMUS_COMMANDT_ENDANDINTRO
The command is an ending and an intro.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.


DMUS_COMPOSEF_FLAGS

The DMUS_COMPOSEF_FLAGS are used in the dwFlags parameter of the IDirectMusicComposer::ComposeTransition and IDirectMusicComposer::AutoTransition methods.

typedef enum enumDMUS_COMPOSEF_FLAGS {
    DMUS_COMPOSEF_NONE                = 0,
    DMUS_COMPOSEF_ALIGN             = 0x1,
    DMUS_COMPOSEF_OVERLAP           = 0x2,
    DMUS_COMPOSEF_IMMEDIATE         = 0x4,
    DMUS_COMPOSEF_GRID              = 0x8,
    DMUS_COMPOSEF_BEAT             = 0x10,
    DMUS_COMPOSEF_MEASURE          = 0x20,
    DMUS_COMPOSEF_AFTERPREPARETIME = 0x40,
    DMUS_COMPOSEF_MODULATE       = 0x1000,
    DMUS_COMPOSEF_LONG           = 0x2000
}  DMUS_COMPOSEF_FLAGS;

Members

DMUS_COMPOSEF_NONE
No flags. By default, the transition starts on a measure boundary.
DMUS_COMPOSEF_ALIGN
Align transition to the time signature of the currently playing segment.
DMUS_COMPOSEF_OVERLAP
Overlap the transition into pToSeg. This flag is not implemented.
DMUS_COMPOSEF_IMMEDIATE
AutoTransition only. Start transition on music or reference time boundary.
DMUS_COMPOSEF_GRID
AutoTransition only. Start transition on grid boundary.
DMUS_COMPOSEF_BEAT
AutoTransition only. Start transition on beat boundary.
DMUS_COMPOSEF_MEASURE
AutoTransition only. Start transition on measure boundary.
DMUS_COMPOSEF_AFTERPREPARETIME
AutoTransition only. Use the DMUS_SEGF_AFTERPREPARETIME flag when cueing the transition.
DMUS_COMPOSEF_MODULATE
Compose a transition that modulates smoothly from pFromSeg to pToSeg, using the chord of pToSeg.
DMUS_COMPOSEF_LONG
Composes a long transition. If this flag is not set, the length of the transition is at most one measure, unless the wCommand parameter of ComposeTransition or AutoTransition specifies an ending and the style contains an ending of greater than one measure. If this flag is set, the length of the transition increases by one measure.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

DMUS_SEGF_FLAGS


DMUS_NOTEF_FLAGS

The DMUS_NOTEF_FLAGS are used in the bFlags member of the DMUS_NOTE_PMSG structure.

typedef enum enumDMUS_NOTEF_FLAGS {
    DMUS_NOTEF_NOTEON = 1,
} DMUS_NOTEF_FLAGS;

Members

DMUS_NOTEF_NOTEON
Set if this is a MIDI note-on, clear if it is a MIDI note-off. When a DMUS_NOTE_PMSG is first sent by the IDirectMusicPerformance::SendPMsg method, this flag should be set.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.


DMUS_PLAYMODE_FLAGS

The DMUS_PLAYMODE_FLAGS are used in various structures for the basic play modes. The play mode determines how a music value is transposed to a MIDI note.

typedef enum enumDMUS_PLAYMODE_FLAGS {
    DMUS_PLAYMODE_KEY_ROOT          = 1,
    DMUS_PLAYMODE_CHORD_ROOT        = 2,
    DMUS_PLAYMODE_SCALE_INTERVALS   = 4,
    DMUS_PLAYMODE_CHORD_INTERVALS   = 8,
    DMUS_PLAYMODE_NONE              = 16,
} DMUS_PLAYMODE_FLAGS;

Members

DMUS_PLAYMODE_KEY_ROOT
Transpose on top of the key root.
DMUS_PLAYMODE_CHORD_ROOT
Transpose on top of the chord root.
DMUS_PLAYMODE_SCALE_INTERVALS
Use scale intervals from scale pattern.
DMUS_PLAYMODE_CHORD_INTERVALS
Use chord intervals from chord pattern.
DMUS_PLAYMODE_NONE
No mode. Indicates the parent part's mode should be used.

Remarks

The following defined values represent combinations of play mode flags:

DMUS_PLAYMODE_ALWAYSPLAY
Combination of DMUS_PLAYMODE_SCALE_INTERVALS, DMUS_PLAYMODE_CHORD_INTERVALS, and DMUS_PLAYMODE_CHORD_ROOT. If it is desirable to play a note that is above the top of the chord, this mode finds a position for the note by using intervals from the scale. Essentially, this mode is a combination of the normal and melodic playback modes, where a failure in normal causes a second try in melodic mode.
DMUS_PLAYMODE_FIXED
Interpret the music value as a MIDI value. This is defined as 0 and signifies the absence of other flags. This flag is used for drums, sound effects, and sequenced notes that should not be transposed by the chord or scale.
DMUS_PLAYMODE_FIXEDTOCHORD
Same as DMUS_PLAYMODE_CHORD_ROOT. The music value is a fixed MIDI value, but it is transposed on top of the chord root.
DMUS_PLAYMODE_FIXEDTOKEY
Same as DMUS_PLAYMODE_KEY_ROOT. The music value is a fixed MIDI value, but it is transposed on top of the key root.
DMUS_PLAYMODE_MELODIC
Combination of DMUS_PLAYMODE_CHORD_ROOT and DMUS_PLAYMODE_SCALE_INTERVALS. The chord root is used but the notes only track the intervals in the scale. The key root and chord intervals are completely ignored. This is useful for melodic lines that play relative to the chord root.
DMUS_PLAYMODE_NORMALCHORD
Combination of DMUS_PLAYMODE_CHORD_ROOT and DMUS_PLAYMODE_CHORD_INTERVALS. This is the prevalent playback mode. The notes track the intervals in the chord, which is based on the chord root. If there is a scale component to the music value, the additional intervals are pulled from the scale and added. If the chord does not have an interval to match the chord component of the music value, the note is silent.
DMUS_PLAYMODE_PEDALPOINT
Combination of DMUS_PLAYMODE_KEY_ROOT and DMUS_PLAYMODE_SCALE_INTERVALS. The key root is used and the notes only track the intervals in the scale. The chord root and intervals are completely ignored. This is useful for melodic lines that play relative to the key root.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicPerformance::MIDIToMusic, IDirectMusicPerformance::MusicToMIDI, DMUS_NOTE_PMSG, DMUS_IO_STYLENOTE, DMUS_IO_STYLEPART, Music Values and MIDI Notes


DMUS_PMSGF_FLAGS

The members of the DMUS_PMSGF_FLAGS enumeration are used in the dwFlags member of the DMUS_PMSG structure.

enum enumDMUS_PMSGF_FLAGS {
    DMUS_PMSGF_REFTIME        = 1,
    DMUS_PMSGF_MUSICTIME      = 2,
    DMUS_PMSGF_TOOL_IMMEDIATE = 4,
    DMUS_PMSGF_TOOL_QUEUE     = 8,
    DMUS_PMSGF_TOOL_ATTIME    = 16,
    DMUS_PMSGF_TOOL_FLUSH     = 32
} DMUS_PMSGF_FLAGS;

Members

DMUS_PMSGF_REFTIME
rtTime is valid.
DMUS_PMSGF_MUSICTIME
mtTime is valid.
DMUS_PMSGF_TOOL_IMMEDIATE
Message should be processed immediately, regardless of its timestamp.
DMUS_PMSGF_TOOL_QUEUE
Message should be processed just before its timestamp, allowing for port latency.
DMUS_PMSGF_TOOL_ATTIME
Message should be processed at the time stamp.
DMUS_PMSGF_TOOL_FLUSH
Message is being flushed.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicPerformance::SendPMsg, IDirectMusicTool::GetMsgDeliveryType


DMUS_PMSGT_TYPES

The members of the DMUS_PMSGT_TYPES enumeration are used in the dwType member of the DMUS_PMSG structure to identify the type of message.

typedef enum enumDMUS_PMSGT_TYPES {
    DMUS_PMSGT_MIDI             = 0,
    DMUS_PMSGT_NOTE             = 1,
    DMUS_PMSGT_SYSEX            = 2,
    DMUS_PMSGT_NOTIFICATION     = 3,
    DMUS_PMSGT_TEMPO            = 4,
    DMUS_PMSGT_CURVE            = 5,
    DMUS_PMSGT_TIMESIG          = 6,
    DMUS_PMSGT_PATCH            = 7,
    DMUS_PMSGT_TRANSPOSE        = 8,
    DMUS_PMSGT_CHANNEL_PRIORITY = 9,
    DMUS_PMSGT_STOP             = 10,
    DMUS_PMSGT_DIRTY            = 11,
    DMUS_PMSGT_USER             = 255
} DMUS_PMSGT_TYPES;

Members

DMUS_PMSGT_MIDI
MIDI channel message. See DMUS_MIDI_PMSG.
DMUS_PMSGT_NOTE
Music note. See DMUS_NOTE_PMSG.
DMUS_PMSGT_SYSEX
MIDI system exclusive message. See DMUS_SYSEX_PMSG.
DMUS_PMSGT_NOTIFICATION
Notification message. See DMUS_NOTIFICATION_PMSG.
DMUS_PMSGT_TEMPO
Tempo message. See DMUS_TEMPO_PMSG.
DMUS_PMSGT_CURVE
Control change / pitch bend curve. See DMUS_CURVE_PMSG.
DMUS_PMSGT_TIMESIG
Time signature. See DMUS_TIMESIG_PMSG.
DMUS_PMSGT_PATCH
Patch change. See DMUS_PATCH_PMSG.
DMUS_PMSGT_TRANSPOSE
Transposition. See DMUS_TRANSPOSE_PMSG.
DMUS_PMSGT_CHANNEL_PRIORITY
Channel priority change. See DMUS_CHANNEL_PRIORITY_PMSG.
DMUS_PMSGT_STOP
Stop message. See DMUS_PMSG.
DMUS_PMSGT_DIRTY
A control segment has started or ended. See DMUS_PMSG.
DMUS_PMSGT_USER
User-defined message.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.


DMUS_SEGF_FLAGS

The members of the DMUS_SEGF_FLAGS enumeration are passed to various methods of IDirectMusicPerformance in order to control the timing and other aspects of actions on a segment.

typedef enum enumDMUS_SEGF_FLAGS {
    DMUS_SEGF_REFTIME          = 64,
    DMUS_SEGF_SECONDARY        = 128,
    DMUS_SEGF_QUEUE            = 256,
    DMUS_SEGF_CONTROL          = 512
    DMUS_SEGF_AFTERPREPARETIME = 1<<10,
    DMUS_SEGF_GRID             = 1<<11,
    DMUS_SEGF_BEAT             = 1<<12,
    DMUS_SEGF_MEASURE          = 1<<13,
    DMUS_SEGF_DEFAULT          = 1<<14,
    DMUS_SEGF_NOINVALIDATE     = 1<<15,
} DMUS_SEGF_FLAGS;

Members

DMUS_SEGF_REFTIME
Time parameter is in reference time.
DMUS_SEGF_SECONDARY
Secondary segment.
DMUS_SEGF_QUEUE
Put at the end of the primary segment queue (primary segment only).
DMUS_SEGF_CONTROL
Play as a control segment (secondary segments only). See Remarks.
DMUS_SEGF_AFTERPREPARETIME
Play after the prepare time. See IDirectMusicPerformance::GetPrepareTime.
DMUS_SEGF_GRID
Play on grid boundary.
DMUS_SEGF_BEAT
Play on beat boundary.
DMUS_SEGF_MEASURE
Play on measure boundary.
DMUS_SEGF_DEFAULT
Use segment's default boundary.
DMUS_SEGF_NOINVALIDATE
Setting this flag in IDirectMusicPerformance::PlaySegment for a primary or control segment will cause the new segment not to cause an invalidation. Without this flag, an invalidation will occur, cutting off and resetting any currently playing curve or note. This flag should be combined with DMUS_SEGF_AFTERPREPARETIME so that there is no danger of notes in the new segment playing over top of notes played by the old segment.

Remarks

Normally the primary segment is the control segment. The DMUS_SEGF_CONTROL flag can be used to make a secondary segment the control segment. There should be only one control segment at a time. (It is possible to create multiple control segments, but there is no guarantee of which one will actually be used by DirectMusic as the control segment.) When a track calls GetParam on a another track, it does so on the control segment. Also, by default only the control segment sends tempo messages.

If the DMUS_SEGF_CONTROL flag is set, DMUS_SEGF_SECONDARY is assumed.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.

See Also

IDirectMusicPerformance::Invalidate, IDirectMusicPerformance::PlaySegment, IDirectMusicPerformance::Stop, IDirectMusicSegment::GetDefaultResolution, IDirectMusicSegment::SetDefaultResolution, DMUS_TIME_RESOLVE_FLAGS


DMUS_SHAPET_TYPES

The members of the DMUS_SHAPET_TYPES enumeration are used in the wShape members of the IDirectMusicComposer::ComposeSegmentFromShape and IDirectMusicComposer::ComposeTemplateFromShape methods to specify the desired pattern of the groove level.

typedef enum enumDMUS_SHAPET_TYPES {
    DMUS_SHAPET_FALLING  = 0,
    DMUS_SHAPET_LEVEL    = 1,
    DMUS_SHAPET_LOOPABLE = 2,
    DMUS_SHAPET_LOUD     = 3,
    DMUS_SHAPET_QUIET    = 4,
    DMUS_SHAPET_PEAKING  = 5,
    DMUS_SHAPET_RANDOM   = 6,
    DMUS_SHAPET_RISING   = 7,
    DMUS_SHAPET_SONG     = 8
} DMUS_SHAPET_TYPES;

Members

DMUS_SHAPET_FALLING
The groove level falls.
DMUS_SHAPET_LEVEL
The groove level remains even.
DMUS_SHAPET_LOOPABLE
The segment is arranged to loop back to the beginning.
DMUS_SHAPET_LOUD
The groove level is high.
DMUS_SHAPET_QUIET
The groove level is low.
DMUS_SHAPET_PEAKING
The groove level rises to a peak, then falls.
DMUS_SHAPET_RANDOM
The groove level is random.
DMUS_SHAPET_RISING
The groove level rises.
DMUS_SHAPET_SONG
The segment is in a song form. Several phrases of 6 to 8 bars are composed and put together to give a verse-chorus effect, with variations in groove level.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.


DMUS_TIME_RESOLVE_FLAGS

The member of the DMUS_TIME_RESOLVE_FLAGS enumeration are used in the dwFlags member of the DMUS_PMSG structure and in the dwTimeResolveFlags parameter of the IDirectMusicPerformance::GetResolvedTime method.

typedef enum enumDMUS_TIME_RESOLVE_FLAGS {
    DMUS_TIME_RESOLVE_AFTERPREPARETIME = 1<<10,
    DMUS_TIME_RESOLVE_GRID             = 1<<11,
    DMUS_TIME_RESOLVE_BEAT             = 1<<12,
    DMUS_TIME_RESOLVE_MEASURE          = 1<<13
} DMUS_TIME_RESOLVE_FLAGS;

Members

DMUS_TIME_RESOLVE_AFTERPREPARETIME
Resolve to a time after the prepare time.
DMUS_TIME_RESOLVE_GRID
Resolve to a time on a grid boundary.
DMUS_TIME_RESOLVE_BEAT
Resolve to a time on a beat boundary.
DMUS_TIME_RESOLVE_MEASURE
Resolve to a time on a measure boundary.

Remarks

These flags can be used interchangeably with the corresponding DMUS_SEGF_FLAGS.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.


DMUS_TRACKF_FLAGS

The DMUS_TRACKF_FLAGS values are used in the dwFlags parameter of the IDirectMusicTrack::Play method.

typedef enum enumDMUS_TRACKF_FLAGS {
    DMUS_TRACKF_SEEK   = 1,
    DMUS_TRACKF_LOOP   = 2,
    DMUS_TRACKF_START  = 4,
    DMUS_TRACKF_FLUSH  = 8,
    DMUS_TRACKF_DIRTY  = 16
} DMUS_TRACKF_FLAGS;

Members

DMUS_TRACKF_SEEK
IDirectMusicTrack::Play was called in response to seeking, meaning that the mtStart parameter is not necessarily the same as the previous call's mtEnd.
DMUS_TRACKF_LOOP
Play was called in response to a loop.
DMUS_TRACKF_START
This is the first call to IDirectMusicTrack::Play. DMUS_TRACKF_SEEK may also be set if the track is not playing from the beginning.
DMUS_TRACKF_FLUSH
Play was called in response to a flush or invalidation that requires the track to replay something it played previously. In this case, DMUS_TRACKF_SEEK will be set as well.
DMUS_TRACKF_DIRTY
A control segment has begun or ended. Tracks that normally wait till mtNext to call IDirectMusicTrack::GetParam should make the call right away instead of waiting, because their data may now be invalid. For more information on setting control segments, see DMUS_SEGF_FLAGS.

Remarks

When Play is called in response to a repeat, DMUS_TRACKF_LOOP and DMUS_TRACKF_SEEK are set.

Tracks must support seeking in order to support invalidation.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dmusici.h.


Return Values

The following table lists the values typically returned by DirectMusic interface methods. For a list of the error codes each method can return, see the individual method descriptions. Note that these lists are not necessarily comprehensive.

DMUS_E_ALL_TOOLS_FAILED
The graph object was unable to load all tools from the IStream object data, perhaps because of errors in the stream, or because the tools are incorrectly registered on the client.
DMUS_E_ALL_TRACKS_FAILED
The segment object was unable to load all tracks from the IStream object data, perhaps because of errors in the stream, or because the tracks are incorrectly registered on the client.
DMUS_E_ALREADY_ACTIVATED
The port has been activated and the parameter cannot be changed.
DMUS_E_ALREADY_DOWNLOADED
Buffer has already been downloaded.
DMUS_E_ALREADY_EXISTS
The tool is already contained in the graph. You must create a new instance.
DMUS_E_ALREADY_INITED
The object has already been initialized.
DMUS_E_ALREADY_LOADED
DLS collection is already open.
DMUS_E_ALREADY_SENT
The message has already been sent.
DMUS_E_ALREADYCLOSED
The port is not open.
DMUS_E_ALREADYOPEN
Port was already opened.
DMUS_E_BADARTICULATION
Invalid articulation chunk in DLS collection.
DMUS_E_BADINSTRUMENT
Invalid instrument chunk in DLS collection.
DMUS_E_BADOFFSETTABLE
Offset table has errors.
DMUS_E_BADWAVE
Corrupt wave header.
DMUS_E_BADWAVELINK
Wavelink chunk in DLS collection points to invalid wave.
DMUS_E_BUFFER_EMPTY
There is no data in the buffer.
DMUS_E_BUFFER_FULL
The specified number of bytes exceeds the maximum buffer size.
DMUS_E_BUFFERNOTAVAILABLE
The buffer is not available for download.
DMUS_E_BUFFERNOTSET
No buffer was prepared for the data.
DMUS_E_CANNOT_CONVERT
The requested conversion between music and MIDI values could not happen. This usually occurs when the provided DMUS_CHORD_KEY structure has an invalid chord or scale pattern.
DMUS_E_CANNOT_FREE
The message could not be freed, either because it was not allocated or has already been freed.
DMUS_E_CANNOT_OPEN_PORT
The default system port could not be opened.
DMUS_E_CANNOTREAD
Error occurred when trying to read from the IStream object.
DMUS_E_CANNOTSEEK
The IStream object does not support Seek.
DMUS_E_CANNOTWRITE
The IStream object does not support Write.
DMUS_E_CHUNKNOTFOUND
A chunk with the specified header could not be found.
DMUS_E_DESCEND_CHUNK_FAIL
Attempt to descend into a chunk failed.
DMUS_E_DEVICE_IN_USE
Device is already in use (possibly by a non-DirectMusic client) and cannot be opened again.
DMUS_E_DMUSIC_RELEASED
Operation cannot be performed because the final instance of the DirectMusic object was released. Ports cannot be used after final release of the DirectMusic object.
DMUS_E_DRIVER_FAILED
An unexpected error was returned from a device driver, indicating possible failure of the driver or hardware.
DMUS_E_DSOUND_ALREADY_SET
A DirectSound object has already been set.
DMUS_E_DSOUND_NOT_SET
Port could not be created because no DirectSound object has been specified.
DMUS_E_GET_UNSUPPORTED
Getting the parameter is not supported.
DMUS_E_INSUFFICIENTBUFFER
Buffer is not large enough for requested operation.
DMUS_E_INVALID_BAND
File does not contain a valid band.
DMUS_E_INVALID_DOWNLOADID
Invalid download identifier was used in the process of creating a download buffer.
DMUS_E_INVALID_EVENT
The event either is not a valid MIDI message or makes use of running status, and cannot be packed into the buffer.
DMUS_E_INVALID_TOOL_HDR
The IStream object's data contains an invalid tool header and therefore cannot be read by the graph object.
DMUS_E_INVALID_TRACK_HDR
The IStream object's data contains an invalid track header and therefore cannot be read by the segment object.
DMUS_E_INVALIDBUFFER
Invalid DirectSound buffer was handed to port.
DMUS_E_INVALIDFILE
Not a valid file.
DMUS_E_INVALIDOFFSET
Wave chunks in DLS collection file are at incorrect offsets.
DMUS_E_INVALIDPATCH
No instrument in the collection matches the patch number.
DMUS_E_INVALIDPOS
Error reading wave data from DLS collection. Indicates bad file.
DMUS_E_LOADER_BADPATH
The file path is invalid.
DMUS_E_LOADER_FAILEDCREATE
Object could not be found or created.
DMUS_E_LOADER_FAILEDOPEN
File open failed because the file doesn't exist or is locked.
DMUS_E_LOADER_FORMATNOTSUPPORTED
The object cannot be loaded because the data format is not supported.
DMUS_E_LOADER_NOCLASSID
No class ID was supplied in DMUS_OBJECTDESC.
DMUS_E_LOADER_NOFILENAME
No filename was supplied in DMUS_OBJECTDESC.
DMUS_E_LOADER_OBJECTNOTFOUND
The object was not found.
DMUS_E_NO_MASTER_CLOCK
There is no master clock in the performance. Make sure to call the IDirectMusicPerformance::Init method.
DMUS_E_NOARTICULATION
Articulation missing from instrument in DLS collection.
DMUS_E_NOSYNTHSINK
No sink is connected to the synthesizer.
DMUS_E_NOT_DOWNLOADED_TO_PORT
The object cannot be unloaded because it is not present on the the port.
DMUS_E_NOT_FOUND
The requested item is not contained by the object.
DMUS_E_NOT_INIT
A required object is not initialized or failed to initialize.
DMUS_E_NOTADLSCOL
The object being loaded is not a valid DLS collection.
DMUS_E_NOTMONO
Wave chunk has more than one interleaved channel. DLS format requires mono.
DMUS_E_NOTPCM
Wave data is not in PCM format.
DMUS_E_OUT_OF_RANGE
The requested time is outside the range of the segment.
DMUS_E_PORT_NOT_CAPTURE
Not a capture port.
DMUS_E_PORT_NOT_RENDER
Not an output port.
DMUS_E_PORTS_OPEN
The requested operation cannot be performed while there are instantiated ports in any process in the system.
DMUS_E_SEGMENT_INIT_FAILED
Segment initialization failed, likely because of a critical memory situation.
DMUS_E_SET_UNSUPPORTED
Setting the parameter is not supported.
DMUS_E_SYNTHACTIVE
The synthesizer has been activated and the parameter cannot be changed.
DMUS_E_SYNTHINACTIVE
The synthesizer has not been activated and cannot process data.
DMUS_E_SYNTHNOTCONFIGURED
The synthesizer is not properly configured or opened.
DMUS_E_TIME_PAST
The time requested is in the past.
DMUS_E_TOOL_HDR_NOT_FIRST_CK
The IStream object's data does not have a tool header as the first chunk, and therefore cannot be read by the graph object.
DMUS_E_TRACK_HDR_NOT_FIRST_CK
The IStream object's data does not have a track header as the first chunk, and therefore cannot be read by the segment object.
DMUS_E_TRACK_NOT_FOUND
There is no track of the requested type.
DMUS_E_TYPE_DISABLED
Track parameter is unavailable because it has been disabled.
DMUS_E_TYPE_UNSUPPORTED
Parameter is unsupported on this track.
DMUS_E_UNKNOWNDOWNLOAD
Synthesizer does not support this type of download.
DMUS_E_UNKNOWN_PROPERTY
The property set or item is not implemented by this port.
DMUS_E_UNSUPPORTED_STREAM
The IStream object does not contain data supported by the loading object.
DMUS_E_WAVEFORMATNOTSUPPORTED
Invalid buffer format was handed to the synthesizer sink.
DMUS_S_DOWN_OCTAVE
The note has been lowered by one or more octaves to fit within the range of MIDI values.
DMUS_S_END
The operation succeeded and reached the end of the data.
DMUS_S_FREE
The allocated memory should be freed.
DMUS_S_LAST_TOOL
There are no more tools in the graph.
DMUS_S_OVER_CHORD
No MIDI values has been calculated, because the music value has the note at a position higher than the top note of the chord.
DMUS_S_PARTIALLOAD
The object could only load partially. This can happen if some components are not registered properly, such as embedded tracks and tools.
DMUS_S_REQUEUE
The message should be passed to the next tool.
DMUS_S_STRING_TRUNCATED
The method succeeded but the returned string had to be truncated.
DMUS_S_UP_OCTAVE
The note has been raised by one or more octaves to fit within the range of MIDI values.
E_FAIL
The method did not succeed.
E_INVALIDARG
Invalid argument. Often this error results from failing to initialize the dwSize member of a structure before passing it to the method.
E_NOAGGREGATION
Aggregation is not supported. The LPUNKNOWN parameter should be set to NULL.
E_NOINTERFACE
No object interface is available.
E_NOTIMPL
The method is not implemented. This value may be returned if a driver does not support a feature necessary for the operation.
E_OUTOFMEMORY
Insufficient memory to complete task.
E_POINTER
An invalid pointer (usually NULL) was passed as a parameter.
REGDB_E_CLASSNOTREG
Object class is not registered.
S_FALSE
The method succeeded, but there was nothing to do.
S_OK
The operation was completed successfully.


DirectMusic Samples

The following sample applications demonstrate the use and capabilities of the DirectMusic™ application programming interface:

  • 3DMusic Sample
  • DMBoids Sample
  • DMDonuts Sample
  • DirectMusic MIDI Sample
  • DirectMusic Shell Sample
  • EchoTool Sample
  • MusicLines Sample
  • PlayMotif Sample
  • PlayPrimary Sample

Although DirectX® samples include Microsoft® Visual C++® project workspace files, you might need to verify other settings in your development environment to ensure that the samples compile properly. For more information, see Compiling DirectX Samples and Other DirectX Applications.


3DMusic Sample

Description

The 3DMusic sample shows how to play a MIDI file into a custom DirectSound 3-D buffer.

Path

Source: (SDK root)\Samples\Multimedia\Dmusic\Src\3DMusic

Executable: (SDK root)\Samples\Multimedia\DMusic\Bin

User's Guide

The icons represents a listener and a sound source in a 3-D environment, although movement and orientation are possible in only two dimensions.

Use the arrow keys to move the sound source. Use the numeric keypad to change the orientation of the listener.

Choosing Play Stereo Drip from the File menu causes a dripping sound to play at random pan and volume, illustrating how pseudo–3-D effects can be achieved with a 2-D buffer.

Programming Notes

The program uses the registry key set up by the DirectX SDK setup to find the media file path.

Helper.cpp contains useful functions that set up DirectMusic. These functions are called from Sound.cpp.


DMBoids Sample

Description

DMBoids is a version of Boids that adds DirectMusic support. As objects fly over a simple landscape, the music responds to user input and events on the screen.

Path

Source: (SDK root)\Samples\Multimedia\Dmusic\Src\DMBoids

Executable: (SDK root)\Samples\Multimedia\DMusic\Bin

User's Guide

Press F10 to access the main menu. The Drivers menu allows you to change the driver, device, and video mode. The application runs only in full-screen modes.

The A (alignment), C (cohesion) and O (obstacle) keys alter behavior of the boids in various ways as long as they are held down.

Hold down the S key or the spacebar and the birds flock in closer. Release the key and they spread apart. Note the use of motifs to track this behavior.

Hold down the M key and the birds wander off their path. Notice that the music completely changes. Release and the birds will eventually get back on the path.

Press the ESC key to quit.

Programming Notes

DirectMusic features illustrated include the following:

  • Software synthesis with DLS. In addition to the musical instruments from the GS sound set, the application uses custom downloadable sounds such as the voices that appear to come from the planets.
  • Composing and performing style-based segments.
  • Musical transitions using style-based motifs and segment cues.
  • Echo/articulation tool coded that uses the proximity of the birds to adjust the echoes and note durations of the music as it plays.


DMDonuts Sample

Description

DM Donuts is a variation of the Space Donuts sample that adds interactive music.

Path

Source: (SDK root)\Samples\Multimedia\Dmusic\Src\DMDonuts

Executable: (SDK root)\Samples\Multimedia\DMusic\Bin

User's Guide

Before running the program, make sure that you've set your MIDI control panel to your default MIDI device. DirectMusic will use this for hardware MIDI. If there is no sound when you run DMDonuts, it was unable to find the music subdirectory.

While the donut floats in space, notice that the music is subtle and spacey. Press the arrow keys to move the ship. Bounce around and see how the music and rhythm respond.

Shoot the donut by firing with the space bar. Immediately there is an explosion of music and the background music grows in intensity.

Press the 7 key on the numeric keypad. This turns on the shields. Notice how the music becomes muted as if you were listening from inside the shield.

When all the donut fragments are destroyed, notice that the music immediately transitions into an ending, then starts the next level on the start of the next musical theme.

Notice that the music is never the same.

You can control the ship with the joystick if you prefer, by changing the input device under the Game menu.

The following is a complete list of game commands. All numbers must be entered from the numeric keypad. "Joy" refers to a joystick button.

Key | Command
ESC, F12 | Quit
4 | Turn left
6 | Turn right
5 (Joy 3) | Stop
8 | Accelerate forward
2 | Accelerate backward
7 (Joy 2) | Shields
SPACEBAR (Joy 1) | Fire
ENTER | Start game
F1 | Toggle trailing afterimage effect on/off
F5 | Toggle frame rate display on/off
F7 | Turn music on/off
F10 | Main menu

The display defaults to 640x480 at 256 colors. You can specify a different resolution and pixel depth on the command line.

The game uses the following command line switches, which are case-sensitive:

e | Use software emulation, not hardware acceleration
t | Test mode, no input required
x | Stress mode. Never halt if you can help it

These switches may be followed by three option numbers representing x-resolution, y-resolution, and bits per pixel. For example:

donuts -t 800 600 16

Programming Notes

Techniques illustrated include the following:

  • Composing and performing style-based segments.
  • Autotransitions on game state changes.
  • Motifs (short musical clips) to highlight actions. Because the motifs track the rhythm and harmony of the underlying music, they add to the music while providing sonic reinforcement.
  • Dynamic bands that change the orchestration in response to real-time events.

By default, this sample runs on the software synthesizer. In Windows 95 and Windows 98, undefine the _SOFTWARE_SYNTH_ compile flag and recompile the sample to receive the best sound when using good wavetable synthesizers (that follow the GS/DLS1 standards for volume and velocity behavior). The newly compiled version will not run on Windows 2000.


DirectMusic MIDI Sample

Description

The DirectMusic MIDI sample is a simple MIDI file player.

Path

Source: (SDK root)\Samples\Multimedia\Dmusic\Src\DMusMIDI

Executable: (SDK root)\Samples\Multimedia\DMusic\Bin

User's Guide

Load a MIDI file by choosing Open from the File menu. (There is a sample file in the \Samples\Multimedia\DMusic\Media folder.) You can also load a file by drag-and-drop. If Autoplay Dropped Files is selected on the Options menu, a dropped file automatically starts playing.

Once a file is loaded, you can play, pause, or stop it by choosing from the File menu or the toolbar.

The Options menu provides a choice for adding reverberation to the music, and several choices for the interface. The time can be displayed in hours, minutes, and seconds from the start of play, or in music time ticks.

When no music is playing, you can select a port from the Device menu. Note that to hear music from the "MIDI Out" port, you must have an external synthesizer attached.

Programming Notes

The application demonstrates how to load a MIDI file as a segment, play it, stop it, and restart it either at the beginning or at the point where it was stopped. It also shows how to set the reverb property.

The code is written in pure C, so methods are called through pointers to vtables. For more information, see Accessing COM Objects by Using C.


DirectMusic Shell Sample

Description

The DirectMusic Shell sample demonstrates interactive music that responds to Windows system events.

Path

Source: (SDK root)\Samples\Multimedia\Dmusic\Src\DMShell

Executable: (SDK root)\Samples\Multimedia\DMusic\Bin

User's Guide

When you run the program, its icon appears in the tray on the taskbar. Click on the icon to see a menu that allows you to change music schemes, select the output device, start and stop the music, and close the program.

Listen to the music and note how it changes and how motifs are introduced in response to system events such as minimizing, restoring, or closing a window, opening an application menu or the Start menu, and pressing a key (there are special sounds for a few keys).

Programming Notes

The Windows system messages are obtained in Dmhook.dll, the source code for which is found in the (SDK root)\Samples\Multimedia\Dmusic\Src\DMHook folder. (Dmhook.dll must be compiled with a Microsoft compiler.)


EchoTool Sample

Description

The EchoTool sample shows how to implement a tool in DirectMusic.

Path

Source: (SDK root)\Samples\Multimedia\Dmusic\Src\EchoTool

Executable: (SDK root)\Samples\Multimedia\DMusic\Bin

User's Guide

Select an option button to change the delay of the echoes. Click the Close button to exit the application.

Programming Notes

The tool creates up to four delayed echoes of the music playing through it.

Helper.cpp contains useful functions that set up DirectMusic. These functions are called from Main.cpp. Echotool.cpp contains the tool code.

For more information, see Tutorial 2: Using Tools.


MusicLines Sample

Description

The MusicLines sample demonstrates interactive music elements in a simple game, and in particular how game elements can be driven by the music.

Path

Source: (SDK root)\Samples\Multimedia\Dmusic\Src\MusicLines

Executable: (SDK root)\Samples\Multimedia\DMusic\Bin

User's Guide

In the opening dialog box, choose windowed or full-screen mode and a difficulty level, and set the players to human or computer. If two humans are playing, one can use the arrow keys while the other uses the keys AZSW.

The object of the game is to force the other player to collide with an existing line.

Change the direction of your line by pressing the arrow keys or the equivalent letter keys. Observe how the main music changes to reflect the current state of play, how motifs are used to signal events such as collisions, and how the speed of the lines is actually controlled by the music.

If you win against the computer, you can continue extending your line or bring the game to an end by deliberately colliding. Play again by pressing the space bar. Quit by pressing ALT+F4.

Programming Notes

The music logic is in Mlmusic.cpp and is amply commented.


PlayMotif Sample

Description

This sample application shows how motifs can be played over a primary segment.

Path

Source: (SDK root)\Samples\Multimedia\Dmusic\Src\PlayMotf

Executable: (SDK root)\Samples\Multimedia\DMusic\Bin

User's Guide

Click the buttons to play the various secondary segments (motifs) on top of the main playing primary segment. Click Close to exit the application.

Programming Notes

The program uses the registry key set up by the DirectX SDK setup to find the media file path.

Helper.cpp contains useful functions that set up DirectMusic. These functions are called from Main.cpp.


PlayPrimary Sample

Description

The PlayPrimary sample shows how to play a primary segment based on an authored music section.

Path

Source: (SDK root)\Samples\Multimedia\Dmusic\Src\PlayPri

Executable: (SDK root)\Samples\Multimedia\DMusic\Bin

User's Guide

Click Close to quit the program.

Programming Notes

The program uses the registry key set up by the DirectX SDK setup to find the media file path.

Helper.cpp contains useful functions that set up DirectMusic. These functions are called from Main.cpp.


Direct3D Immediate Mode

Direct3D® Immediate Mode application programming interface (API) is part of the three-dimensional (3-D) graphics component of DirectX®. The information on Direct3D Immediate Mode is organized into the following topics:

  • About Direct3D Immediate Mode
  • Why Use Direct3D Immediate Mode?
  • Getting Started with Immediate Mode
  • Direct3D Immediate Mode Architecture
  • Direct3D Immediate Mode Essentials
  • Direct3D Immediate Mode Tutorials
  • Direct3D Immediate Mode Reference
  • Direct3D Immediate Mode Samples


About Direct3D Immediate Mode

Direct3D is designed to enable world-class game and interactive three-dimensional (3-D) graphics on a computer running Microsoft® Windows®. Its mission is to provide device-dependent access to 3-D video-display hardware in a device-independent manner. Simply put, Direct3D is a drawing interface for 3-D hardware.

You can use Direct3D in either of two modes: Immediate Mode or Retained Mode. Retained Mode is a high-level 3-D application programming interface (API) for programmers who require rapid development or who want the help of Retained Mode's built-in support for hierarchies and animation.

Microsoft developed the Direct3D Immediate Mode as a low-level 3-D API. Immediate Mode is ideal for developers who need to port games and other high-performance multimedia applications to the Microsoft Windows operating system. Immediate Mode is a device-independent way for applications to communicate with accelerator hardware at a low level. Direct3D Retained Mode is built on top of Immediate Mode.

These are some of the advanced features of Direct3D:

  • Switchable depth buffering (using z-buffers or w-buffers)
  • Flat and Gouraud shading
  • Multiple lights and light types
  • Full material and texture support, including mipmapping
  • Robust software emulation drivers
  • Transformation and clipping
  • Hardware independence
  • Full support on Windows NT/Windows 2000
  • Support for the Intel MMX architecture

Developers who use Immediate Mode instead of Retained Mode are typically experienced in high-performance programming issues, and may also be experienced in 3-D graphics. Your best source of information about Immediate Mode is probably the sample code included with this SDK; it illustrates how to put Direct3D Immediate Mode to work in real-world applications.


Why Use Direct3D Immediate Mode?

The world management of Immediate Mode is based on vertices, polygons, and commands that control them. It allows immediate access to the transformation, lighting, and rasterization 3-D graphics pipeline. If hardware isn't present to accelerate rendering, Direct3D offers applications a choice of software emulation drivers. Developers with existing 3-D applications and developers who need to achieve maximum performance by maintaining the thinnest possible layer between their application and the hardware should use Immediate Mode instead of Retained Mode.

There are two ways to use Immediate Mode: you can use the DrawPrimitive methods or you can work with execute buffers (display lists). Most developers who have never worked with Immediate Mode before will use the DrawPrimitive methods. Developers who already have an investment in code that uses execute buffers will probably continue to work with them. Neither technique is faster than the other — which you choose will depend on the needs of your application and your preferred programming style. For more information about these two ways to work with Immediate Mode, see The DrawPrimitive Methods and Execute Buffers.

Immediate Mode allows a low-overhead connection to 3-D hardware. This low-overhead connection comes at a price; you must provide explicit calls for transformations and lighting, you must provide all the necessary matrices, and you must determine what kind of hardware is present and what its capabilities are.


Getting Started with Immediate Mode

The following sections describe some of the technical concepts you need to understand before you write programs that incorporate 3-D graphics. This is not a discussion of broad architectural details, nor is it an in-depth analysis of specific Direct3D components. For information about these topics, see Direct3D Immediate Mode Architecture and Direct3D Immediate Mode Essentials.

If you are already experienced in producing 3-D graphics, simply scan the following sections for information that is unique to Direct3D.

Information in this section is divided into the following groups:

  • 3-D Coordinate Systems and Geometry
  • Matrices and Transformations


3-D Coordinate Systems and Geometry

Programming Direct3D applications requires a working familiarity of 3-D geometric principles. This section introduces the most important geometric concepts needed for creating 3-D scenes in the following sections:

  • 3-D Coordinate Systems
  • 3-D Primitives
  • Triangle Rasterization Rules
  • Shading


3-D Coordinate Systems

Typically 3-D graphics applications use two types of Cartesian coordinate systems: left-handed and right-handed. In both coordinate systems, the positive x-axis points to the right and the positive y-axis points up. You can remember which direction the positive z-axis points by pointing the fingers of either your left or right hand in the positive x-direction and curling them into the positive y-direction. The direction your thumb points, either toward or away from you, is the direction the positive z-axis points for that coordinate system.

Direct3D uses a left-handed coordinate system. If you are porting an application that relies on right-handedness, you can do so by making two simple changes to the data passed to Direct3D.

  • Flip the order of triangle vertices so that the system traverses them clockwise from the front. In other words, if the vertices are v0, v1, v2, pass them to Direct3D as v0, v2, v1.
  • Use the view matrix to scale world space by -1 in the z-direction. To do this, flip the sign of the _31, _32, _33, and _34 member of the D3DMATRIX structure that you use for your view matrix.

It is important to note that there are a wide variety of other coordinate systems used in 3-D software. Left- and right-handed coordinates are the most common. However, it is not unusual for 3-D modeling programs to use a coordinate system in which the y-axis points toward or away from the viewer, and the z-axis points up. In this case, right-handedness is defined as any positive axis (x, y, or z) pointing toward the viewer. Left-handedness is defined as any positive axis (x, y, or z) pointing away from the viewer. If you are porting a left-handed modeling application where the z-axis points up, then in addition to the previous steps you need to do a rotation on all of the vertex data.

The essential operations performed on objects defined in a 3-D coordinate system are translate, rotate, and scale. You can combine these basic transformations to create a transform matrix. For details, see 3-D Transformations.

Remember that when you combine these operations, the results are not commutative—the order in which you multiply matrices is important.


3-D Primitives

A 3-D primitive is a collection of vertices that form a single 3-D entity. The simplest primitive is a collection of points in a 3-D coordinate system, which is called a point list in Direct3D.

Often, 3-D primitives are polygons. A polygon in Direct3D is a closed 3-D figure delineated by at least three vertices. The simplest polygon is a triangle. Direct3D uses triangles to compose most of its polygons because all three of the vertices in a triangle are guaranteed to be coplanar. Rendering non-planar vertices is inefficient. You can composite triangles together to form large, complex polygons and meshes.

The following illustration shows a cube. Two triangles form each face of the cube. The entire set of triangles taken together forms one cubic primitive. You can apply textures and materials to the surfaces of primitives to make them appear to be a single solid form. For details, see Materials and Textures.

You can also use triangles to create primitives whose surfaces appear to be smooth curves. The following illustration shows how a sphere can be simulated with triangles. After a material is applied, it looks curved when it is rendered. This is especially true if using Gouraud shading. For details, see Gouraud Shading


Triangle Rasterization Rules

Often the points specified for vertices do not precisely match the pixels on the screen. When this happens, Direct3D applies triangle rasterization rules to decide which pixels apply to a given triangle.

Direct3D uses a top-left filling convention for filling geometry. This is the same convention that is used for rectangles in GDI and OpenGL. In Direct3D the center of the pixel is the point at which decisions are made. If the center is inside a triangle, the pixel is part of the triangle. Pixel centers are at integer coordinates.

This description of triangle-rasterization rules used by Direct3D does not necessarily apply to all available hardware. Your testing may uncover minor variations in the implementation of these rules.

The following illustration shows a rectangle whose upper-left corner is at (0, 0) and whose lower-right corner is at (5, 5). This rectangle fills 25 pixels, just as you would expect. The width of the rectangle is defined as right minus left. The height is defined as bottom minus top.

In the top-left filling convention, the word "top" refers to the vertical location of horizontal spans, and the word "left" refers to the horizontal location of pixels within a span. An edge cannot be a top edge unless it is horizontal—in the general case, most triangles will have only left and right edges.

The top-left filling convention determines the action taken by Direct3D when a triangle passes through the center of a pixel. The following illustration shows two triangles, one at (0, 0), (5, 0), and (5, 5), and the other at (0, 5), (0, 0), and (5, 5). The first triangle in this case gets 15 pixels, whereas the second gets only 10, because the shared edge is the left edge of the first triangle.

If, for example, you define a rectangle with its upper-left corner at (0.5, 0.5) and its lower-right corner at (2.5, 4.5), the center point of this rectangle would be at (1.5, 2.5). When the Direct3D rasterizer tessellates this rectangle, the center of each pixel would be unambiguously inside each of the four triangles, and the top-left filling convention would not be needed. The following drawing illustrates this. The pixels in the rectangle are labeled according to the triangle in which Direct3D includes them.

If you move the rectangle in the previous example so that its upper-left corner is at (1.0, 1.0), its lower-right corner at (3.0, 5.0), and its center point at (2.0, 3.0), Direct3D applies the top-left filling convention. Most of the pixels in this rectangle would straddle the border between two or more triangles, as the next illustration shows.

Notice that for both rectangles, the same pixels are affected.


Shading

This section describes techniques used in Direct3D to control the shading of 3-D polygons.

  • Shade Modes
  • Comparing Shading Modes
  • Setting the Shade Mode
  • Face and Vertex Normal Vectors
  • Triangle Interpolants


Shade Modes

The shading mode used to render a polygon has a profound effect on its appearance. Shading modes determine the intensity of color and lighting at any point on a polygon's face. Direct3D currently supports two shading modes:

  • Flat Shading
  • Gouraud Shading


Flat Shading

In the flat shade mode, the Direct3D rendering pipeline renders a polygon using the color of the polygon's material at its first vertex as the color for the entire polygon. 3-D objects that are rendered with flat shading have visibly sharp edges between polygons if they aren't coplanar.

The following figure shows a teapot rendered with flat shading. The outline of each polygon is clearly visible. Flat shading is computationally the least expensive form of shading.


Gouraud Shading

When Direct3D renders a polygon using Gouraud shading, it computes a color for each vertex by using the vertex normal and lighting parameters. Then, it interpolates the color across the face of the polygons (See Face and Vertex Normal Vectors). The interpolation is done linearly. For example, if the red component of the color of vertex 1 is 0.8 and the red component of vertex 2 is 0.4, utilizing the Gouraud shade mode and the RGB color model, the Direct3D lighting module would assign a red component of 0.6 to the pixel at the midpoint of the line between these vertices.

The following figure demonstrates Gouraud shading. This teapot is composed of many flat, triangular polygons. However, Gouraud shading makes the surface of the object appear curved and smooth.

The Gouraud shade mode can also be used to display objects with sharp edges. For details, see Face and Vertex Normal Vectors.


Comparing Shading Modes

In the flat shade mode, the following pyramid would be displayed with a sharp edge between adjoining faces. In the Gouraud shade mode, however, shading values would be interpolated across the edge, and the final appearance would be of a curved surface.

The Gouraud shade mode lights flat surfaces more realistically than the flat shade mode. A face in the flat shade mode is a uniform color, but Gouraud shading allows light to fall across a face correctly. This effect is particularly obvious if there is a nearby point source.

Gouraud shading smoothes out the sharp edges between polygons that are visible with flat shading. However, it can result in Mach bands, which are bands of color or light that are not smoothly blended across adjacent polygons. Your application can reduce the appearance of Mach bands by increasing the number of polygons in an object, increasing screen resolution, or by increasing the color depth of the application.

Gouraud shading can miss some details. One example is the case shown by the following illustration, in which a spotlight is completely contained within a polygonal face.

In this case, the Gouraud shade mode, which interpolates between vertices, would miss the spotlight altogether; the face would be rendered as though the spotlight did not exist.


Setting the Shade Mode

Direct3D allows one shade mode to be selected at a time. By default, Gouraud shading is selected. The shade mode can be changed by calling the IDirect3DDevice3::SetRenderState method. The dwRenderStateType parameter should be set to D3DRENDERSTATE_SHADEMODE. The dwRenderState parameter must be set to a member of the D3DSHADEMODE enumeration. The following sample code fragments illustrate how the current shade mode of a Direct3D application can be set to flat or Gouraud shading mode.

// Set to flat shading.
// This code fragment assumes that lpDev3 is a valid pointer to
// an IDirect3DDevice3 interface.
hr = lpDev3->SetRenderState(D3DRENDERSTATE_SHADEMODE, D3DSHADE_FLAT);
if(FAILED(hr))
{
    // Code to handle the error goes here.
}

// Set to Gouraud shading (this is the default for Direct3D).
hr = lpDev3->SetRenderState(D3DRENDERSTATE_SHADEMODE,
                            D3DSHADE_GOURAUD);
if(FAILED(hr))
{
    // Code to handle the error goes here.
}


Face and Vertex Normal Vectors

Each face in a mesh has a perpendicular normal vector. The vector's direction is determined by the order in which the vertices are defined and by whether the coordinate system is right- or left-handed. The face normal points away from the front side of the face. In Direct3D, only the front side of a face is visible. A front face is one in which vertices are defined in clockwise order.

Any face that is not a front face is a back face. Direct3D does not always render back faces, therefore back faces are said to be culled. (You can change the culling mode to render back faces, if so desired. See Culling State for more information.)

Direct3D applications do not need to specify face normals; the system calculates them automatically when they are needed. The system uses face normals in the flat shade mode. In Gouraud shade mode, Direct3D uses the vertex normal. It also uses the vertex normal for controlling lighting and texturing effects.

Direct3D applications typically use the D3DVERTEX type for their vertices. The members of the D3DVERTEX structure describe the position and orientation of the vertex. The orientation is indicated by a vertex normal vector. The following code fragment demonstrates how vertex values, including the vertex normal, can be set. The normal vectors are pointing toward the viewport, which is at the origin of the world coordinate system. The vertex positions in this example are specified in world coordinates.

D3DVERTEX lpVertices[3];

// A vertex can be specified one structure member at a time.
lpVertices[0].x = 0;
lpVertices[0].y = 5;
lpVertices[0].z = 5;
lpVertices[0].nx = 0;    // X component of the normal vector.
lpVertices[0].ny = 0;    // Y component of the normal vector.
lpVertices[0].nz = -1;   // Points the normal back at the origin.
lpVertices[0].tu = 0;    // Only used if a texture is being used.
lpVertices[0].tv = 0;    // Only used if a texture is being used.

// Vertices can also by specified on one line of code for each vertex
// by using some of the D3DOVERLOADS macros.
lpVertices[1] = D3DVERTEX(D3DVECTOR(-5,-5,5),D3DVECTOR(0,0,-1),0,0);
lpVertices[2] = D3DVERTEX(D3DVECTOR(5,-5,5),D3DVECTOR(0,0,-1),0,0);

When applying Gouraud shading to a polygon, Direct3D uses the vertex normals to calculate the angle between the light source and the surface. It calculates the color and intensity values for the vertices and interpolates them for every point across all of the primitive's surfaces. Direct3D calculates the light intensity value by using the angle. The greater the angle, the less light is shining on the surface.

If you are creating an object that is flat, then the vertex normals should be set to point perpendicular to the surface. The following illustration demonstrates this. A flat surface composed of two triangles is defined. The vertex normals all point perpendicular to the surface.

It is more likely, however, that your object is made up of triangle strips, and that the triangles are not coplanar. One simple way to get smooth shading across all of the triangles in the strip is to first calculate the surface normal vector for each polygonal face with which the vertex is associated. The vertex normal can be set to make an equal angle with each of the surface normals. Note, however, that this method may not be efficient enough for complex primitives.

This method is illustrated by the following figure, which shows two surfaces, S1 and S2 seen edge-on from above. The normal vectors for S1 and S2 are shown in blue. The vertex normal vector is shown in red. The angle that the vertex normal vector makes with the surface normal of S1 is the same as the angle between the vertex normal and the surface normal of S2. When these two surfaces are lit and shaded with Gouraud shading, the result will be a smoothly-shaded, smoothly-rounded edge between them.

If the vertex normal leans toward one of the faces with which it is associated, it causes the light intensity to increase or decrease for points on that surface, depending on the angle it makes with the light source. An example is shown in the following figure. Again, these surfaces are seen edge-on. The vertex normal leans toward S1, causing it to have a smaller angle with the light source than it would if the vertex normal had equal angles with the surface normals.

You can use the Gouraud shade mode to display some of the objects in a 3-D scene with sharp edges. If you are using execute buffers, your application needs to duplicate the vertex normal vectors at any intersection of faces where a sharp edge was required, as shown in the following illustration.

If you are using the IDirect3DDevice3::DrawPrimitive or IDirect3DDevice3::DrawIndexedPrimitive methods to render your scene, you must define the object with sharp edges as a triangle list, rather than a triangle strip. When you define an object as a triangle strip, Direct3D treats it as a single polygon composed of multiple triangular faces. Gouraud shading is applied both across each face of the polygon and between adjacent faces. The result is an object that is smoothly shaded from face to face. Since a triangle list is a polygon composed of a series of disjoint triangular faces, Direct3D applies Gouraud shading across each face of the polygon. However it is not applied from face to face. If two or more triangles of a triangle list are adjacent, they appear to have a sharp edge between them.

Another alternative is to change to flat shading mode when rendering objects with sharp edges. This is computationally the most efficient method, but it may result in objects in the scene that are not rendered as realistically as the objects that are Gouraud-shaded.


Triangle Interpolants

The system interpolates the characteristics of a triangle's vertices across the triangle when it renders a face. These are the triangle interpolants:

  • Color
  • Specular
  • Alpha

All of the triangle interpolants are modified by the current shade mode:

Flat | No interpolation is done. Instead, the color of the first vertex in the triangle is applied across the entire face.
Gouraud | Linear interpolation is performed between all three vertices.

The color and specular interpolants are treated differently, depending on the color model. In the RGB color model, the system uses the red, green, and blue color components in the interpolation. In the monochromatic or "ramp" model, the system uses only the blue component of the vertex color.

The alpha component of a color is treated as a separate interpolant because device drivers can implement transparency in two different ways: by using texture blending or by using stippling.

An application uses the dwShadeCaps member of the D3DPRIMCAPS structure to determine what forms of interpolation the current device driver supports.


Matrices and Transformations

You use matrices in Direct3D to define world, view, and projection transformations. If you haven't programmed for 3-D graphics before, this section will help you familiarize yourself with the key concepts you need to understand in order to get started. If you have prior experience in 3-D programming, you can skip this section, or you could skim the following topics to refresh your memory:

  • Matrices
  • 3-D Transformations


Matrices

Although you needn't be an expert in linear algebra to work with matrices, you should have a passing acquaintance with them. For a refresher in a few of the basics, see 3-D Transformations.

Matrices in Direct3D are represented by a 4×4 homogenous matrix, defined by the D3DMATRIX structure.

The D3D_OVERLOADS implementation of the D3DMATRIX structure (D3DMATRIX (D3D_OVERLOADS)) implements a parentheses ("()") operator. This operator offers convenient access to values in the matrix for C++ programmers. Instead of having to refer to the structure members by name, C++ programmers can refer to them by row and column number, and simply index these numbers as needed. These indices are zero-based, so for example the element in the third row, second column would be M(2, 1). To use the D3D_OVERLOADS operators, you must define D3D_OVERLOADS before including the D3dtypes.h header file.

Also, the D3dutil.cpp source file provides helper functions for creating and concatenating matrices. Feel free to use these functions as they are, or use them as a basis to write your own matrix manipulation functions.

Execute buffer notes When working with execute buffers, matrices appear to you only as handles. These handles (defined by the D3DMATRIXHANDLE type) are used in the D3DOP_MATRIXLOAD and D3DOP_MATRIXMULTIPLY execute buffer opcodes.

You can create a Direct3D matrix by calling the IDirect3DDevice::CreateMatrix method. You can set the contents of a matrix by calling the IDirect3DDevice::SetMatrix method.


3-D Transformations

Direct3D uses matrices to perform 3-D transformations. This section explains how matrices create 3-D transformations, describes some common uses for transformations, and details how you can combine matrices to produce a single matrix that encompasses multiple transformations. Information is divided into the following categories:

  • About 3-D Transformations
  • Translation
  • Rotation
  • Scaling
  • Matrix Concatenation

For more information about transformations in Direct3D Immediate Mode, see The Geometry Pipeline.


About 3-D Transformations

In programs that work with 3-D graphics, you can use geometrical transformations to:

  • Express the location of an object relative to another object.
  • Rotate and size objects.
  • Change viewing positions, directions, and perspectives.

You can transform any point into another point by using a 4×4 matrix. In the following example, a matrix is used to reinterpret the point (x, y, z), producing the new point (x', y', z'):

You perform the following operations on (x, y, z) and the matrix to produce the point (x', y', z'):

The most common transformations are translation, rotation, and scaling. You can combine the matrices that produce these effects into a single matrix to calculate several transformations at once. For example, you can build a single matrix to translate and rotate a series of points. For more information, see Matrix Concatenation.

Matrices are written in row-column order. A matrix that evenly scales vertices along each axis (known as uniform scaling) is represented by the following matrix (using mathematical notation):

Direct3D Immediate Mode declares matrices as a two dimensional array, using the D3DMATRIX structure. The following example shows how you would initialize a D3DMATRIX structure to act as a uniform scaling matrix:

D3DMATRIX scale = {
    D3DVAL(s),    0,            0,            0,
    0,            D3DVAL(s),    0,            0,
    0,            0,            D3DVAL(s),    0,
    0,            0,            0,            D3DVAL(1)
};


Translation

The following transformation translates the point (x, y, z) to a new point (x', y', z'):

You can create a translation matrix by hand, or by using the Translate helper function in the D3dutil.cpp file that is included with this documentation. The following example shows the source code for the Translate function:

D3DMATRIX Translate(const float dx, const float dy, const float dz)
{
    D3DMATRIX ret = IdentityMatrix();
    ret(3, 0) = dx;
    ret(3, 1) = dy;
    ret(3, 2) = dz;
    return ret;
}    // end of Translate()


Rotation

The transformations described here are for left-handed coordinate systems, and so may be different from transformation matrices you have seen elsewhere. For more information, see 3-D Coordinate Systems.

The following transformation rotates the point (x, y, z) around the x-axis, producing a new point (x', y', z')

The following transformation rotates the point around the y-axis:

The following transformation rotates the point around the z-axis:

Note that in these example matrices, the Greek letter theta (θ) stands for the angle of rotation, specified in radians. Angles are measured clockwise when looking along the rotation axis toward the origin.

You can leverage the RotateX, RotateY, and RotateZ helper functions in the D3dutil.cpp file to create rotation matrices. The following is the sample code for the RotateX helper function:

D3DMATRIX RotateX(const float rads)
{
    float    cosine, sine;

    cosine = cos(rads);
    sine = sin(rads);
    D3DMATRIX ret = IdentityMatrix();
    ret(1,1) = cosine;
    ret(2,2) = cosine;
    ret(1,2) = -sine;
    ret(2,1) = sine;
    return ret;
}   // end of RotateX()


Scaling

The following transformation scales the point (x, y, z) by arbitrary values in the x-, y-, and z-directions to a new point (x', y', z'):


Matrix Concatenation

One of the primary advantages of using matrices is that you can combine the effects of two or more matrices by multiplying them. This means that, to rotate a model and then translate it to some location, you don't need to apply two matrices. Instead, you multiply the rotation and translation matrices to produce a composite matrix that contains the whole of their effects. This process often called matrix concatenation, and can be written with the following formula:

In this formula, C is the composite matrix being created, and M1 through Mn are the individual transformations that matrix C will contain. In most cases, you'll only concatenate two or three matrices, but there is no limit.

(The D3dmath.cpp source file that is included with the DirectX documentation contains the D3DMath_MatrixMultiply helper function to perform matrix multiplication.)

Notice the order in which the matrix multiplication is performed—the order you use is crucial. The preceding formula reflects the right-to-left rule of matrix concatenation. That is, the visible effects of the matrices you use to create a composite matrix occur in right-to-left order. Let's use a typical world transformation matrix as an example. Imagine you were creating the world transformation matrix for a stereotypical "flying saucer." You would probably want to spin the UFO around its center (the y-axis of model space) and translate it to someplace in your scene. To accomplish this effect, you should first create a translation matrix, then multiply it by a rotation matrix, as in the following formula:

In this formula, Tw is a translation to some position in world coordinates, and Ry is a matrix for rotation about the y-axis.

The order in which you multiply the matrices is important because, unlike multiplying two scalar values, matrix multiplication is not commutative. Multiplying the translate and rotate matrices in the opposite order would have the visual effect of translating the UFO to its world space position, then rotating it around the world origin.

No matter what type of matrix you're trying to create, keep the right-to-left rule in mind to ensure that you achieve the expected effects.


Direct3D Immediate Mode Architecture

This section provides high-level information about the organization of the Direct3D® Immediate Mode documentation. Information is divided into the following groups:

  • Architectural Overview of Immediate Mode
  • Immediate Mode Object Types
  • Immediate Mode COM Interfaces
  • DrawPrimitive Methods and Execute Buffers


Architectural Overview of Direct3D Immediate Mode

Architectural Overview of Immediate Mode

Direct3D applications communicate with graphics hardware in a similar fashion, whether they use Retained Mode or Immediate Mode. They may or may not take advantage of software emulation before interacting with the HAL. Since Direct3D is an interface to a DirectDraw® object, the HAL is referred to as the DirectDraw/Direct3D HAL.

Direct3D is tightly integrated with the DirectDraw component of DirectX®. DirectDraw surfaces are used as rendering targets (front and back surfaces) and as z-buffers. The Direct3D COM interface is actually an interface to a DirectDraw object.


Immediate Mode Object Types

Direct3D Immediate Mode is made up of a series of objects. You work with these objects to manipulate your virtual world and build a Direct3D application.

DirectDraw Object
A DirectDraw object provides the functionality of Direct3D; IDirect3D, IDirect3D2 and IDirect3D3 are interfaces to a DirectDraw object. Since a DirectDraw object represents the display device, and the display device implements many of the most important features of Direct3D, it makes sense that the abilities of Direct3D are incorporated into DirectDraw. You create a DirectDraw object by calling the DirectDrawCreate function. For more information, see the IDirect3D3 Interface.
DirectDrawSurface Object
A DirectDrawSurface object that was created as a texture map contains the bitmap(s) that your Direct3D application will use as textures. You can retrieve the IDirect3DTexture2 interface for the surface by calling the IUnknown::QueryInterface method, specifying the IID_IDirect3DTexture2 reference identifier.

For more information, see Textures.

Direct3DDevice Object
A Direct3DDevice object encapsulates and stores the rendering state for an Immediate Mode application; it can be thought of as a rendering target for Direct3D. Prior to DirectX 5, Direct3D devices were interfaces to DirectDrawSurface objects. DirectX 5 introduced a new device-object model, in which a Direct3DDevice object is entirely separate from DirectDraw surfaces. This new object supports the IDirect3DDevice3 interface.

You can call the IDirect3D3::CreateDevice method to create a Direct3DDevice object and retrieve an IDirect3DDevice3 interface. (Notice that you do not call QueryInterface to retrieve IDirect3DDevice3.) If necessary, you can retrieve an IDirect3DDevice interface by calling the IDirect3DDevice3::QueryInterface method.

For more information, see and Direct3D Devices.

Direct3DMaterial Object
A Direct3DMaterial object describes the illumination properties of a visible element in a three-dimensional scene, including how it handles light and whether it uses a texture. You can create a Direct3DMaterial object by calling the IDirect3D3::CreateMaterial method. You can use the IDirect3DMaterial3 interface to get and set materials and to retrieve material handles.

For more information, see Materials.

Direct3DViewport Object
A Direct3DViewport object defines the rectangle into which a three-dimensional scene is projected. You can create an IDirect3DViewport3 interface by calling the IDirect3D3::CreateViewport method. For more information, see Viewports and Clipping.
Direct3DLight Object
A Direct3DLight object describes the characteristics of a light in your application. You can use the IDirect3DLight interface to get and set lights. You can create an IDirect3DLight interface by calling the IDirect3D3::CreateLight method.

For more information, see Lights.

Direct3DVertexBuffer Object
A Direct3DVertexBuffer object is a memory buffer that contains vertices to be rendered with the vertex-buffer rendering methods offered in the IDirect3DDevice3 interface. Vertex buffers are not to be confused with execute buffers. A vertex buffer contains only vertex data to be processed by a Direct3DDevice object, and offers features that you can use to improve performance during rendering.

For additional information, see Vertex Buffers.

Direct3DExecuteBuffer Object
A Direct3DExecuteBuffer object is a buffer full of vertices and instructions about how to handle them. Prior to DirectX 5, Immediate Mode programming was done exclusively by using Direct3DExecuteBuffer objects. The introduction of the DrawPrimitive methods in DirectX 5, however, has made it unnecessary for most applications to work with execute buffers.

For more information about execute buffers, see Execute Buffers.


Immediate Mode COM Interfaces

The Direct3D Immediate Mode API consists primarily of the following COM interfaces:

IDirect3D3 | Root interface, used to obtain other interfaces
IDirect3DDevice | 3D Device for execute-buffer based programming
IDirect3DDevice3 | 3D Device for DrawPrimitive-based programming
IDirect3DLight | Interface used to work with lights
IDirect3DMaterial3 | Surface-material interface
IDirect3DTexture2 | Texture-map interface
IDirect3DVertexBuffer | Interface used to work with vertex buffers.
IDirect3DViewport3 | Interface to define the viewport's characteristics.
IDirect3DExecuteBuffer | Interface for working with execute buffers

For backward compatibility with previous versions of DirectX, all former interface versions are still supported in DirectX 6.0.


DrawPrimitive Methods and Execute Buffers

DirectX 5 introduced a radically new way to use Direct3D Immediate Mode. Previously, you had to fill and execute the execute buffers to accomplish any task. Now, you can use the DrawPrimitive methods, which allow you to draw primitives directly.

The IDirect3DDevice interface supports execute buffers. The IDirect3DDevice3 interface supports the DrawPrimitive methods. Despite the names of these interfaces, IDirect3DDevice3 is not a COM iteration of the IDirect3DDevice interface. Although there is some overlap in the functionality of the interfaces, they are separate implementations. This means that you cannot call IDirect3DDevice::QueryInterface to retrieve an IDirect3DDevice3 interface. You must call the IDirect3D3::CreateDevice method, instead.

For more information about the DrawPrimitive methods, see Rendering. For more information about working with execute buffers, see Using Execute Buffers. For more information about device objects, see Direct3D Devices.


Direct3D Immediate Mode Essentials

Direct3D Immediate Mode consists of a relatively small number of API elements that create objects, fill them with data, and link them together. The API is based on the COM model. The Immediate Mode API are a very thin layer over the Direct3D drivers.

This section provides technical information about the components Direct3D Immediate Mode. Information is divided into the following groups.

  • Immediate Mode Changes for DirectX 6.0
  • Direct3D and DirectDraw
  • Direct3D Devices
  • The Geometry Pipeline
  • Lighting and Materials
  • Vertex Formats
  • Textures
  • Depth Buffers
  • Stencil Buffers
  • Vertex Buffers
  • Common Techniques and Special Effects
  • GUIDs
  • Performance Optimization
  • Troubleshooting


Immediate Mode Changes for DirectX 6.0

DirectX 6.0 is backward compatible with all prior versions of DirectX, and offers several features that improve performance, increase ease-of-use, and exploit new hardware features:

Performance enhancements:

  • Support for buffers to contain vertex data, called "vertex buffers," acting as staging points for more efficient transformation and rendering of vertices. Vertex buffers can be optimized to make it possible to transform vertex data more efficiently, and transformed vertices in a vertex buffer can be reused (rather than transforming them multiple times). The IDirect3DDevice3 interface introduces the IDirect3DDevice3::DrawPrimitiveVB and IDirect3DDevice3::DrawIndexedPrimitiveVB to render vertices from a vertex buffer.
  • Applications can increase the performance of Direct3D by setting the DDSCL_FPUSETUP DirectDraw cooperative level. This cooperative level eliminates overhead incurred when Direct3D is forced to check and reset the FPU precision mode for each rendering cycle. For more information, see DirectDraw Cooperative Levels and FPU Precision.
  • Direct3D now includes a reference driver that, although not intended for shipping applications, produces extremely accurate output for testing and demonstration purposes.

Ease-of-use improvements

  • Automatically managed texture surfaces. See Automatic Texture Management for details.
  • More flexible ways to declare vertices in memory. Applications are no longer required to use only predefined vertex types, and can even include per-vertex color components for lit vertices. For more information, see Vertex Formats.
  • Support for discrete or interleaved arrays of vertex component data. For additional discussion of strided vertices, see Strided Vertex Format.

Support for cutting-edge hardware features:

  • Direct3D Immediate Mode supports hardware that can perform single-pass multiple texture blending. Direct3D exposes the concepts of texture stages, blending operations, and blending arguments in the new IDirect3DDevice3 interface, through the IDirect3DDevice3::SetTextureStageState method. For more information, see Multiple Texture Blending.
  • You can use the new texture blending features of Direct3D to perform bump mapping. The bump-mapping model, offered through the multiple texture blending interface, utilizes special bump-map surfaces to perturb the texture coordinates applied to environment maps.
  • Support for an alternative form of depth buffering that uses eye-space Z in the depth buffer, often called "w-buffering." For more information, see Depth Buffers.
  • Support for stencil buffers (also known as "stencil planes"). For more information, see Stencil Buffers.

DirectX 6.0 uses the same object model that was utilized in DirectX 5.0. (This is a different object model than was used in DirectX 3, however), however the programming approaches offered by legacy interfaces are still supported in DirectX 6.0.


Direct3D and DirectDraw

This section describes the close relation between Direct3D and DirectDraw. It offers information on the following topics:

  • DirectDraw, Direct3D, and the Direct3D Interfaces
  • Direct3D Interfaces
  • Retrieving an IDirect3D3 Interface
  • Using the IDirect3D3 Interface
  • DirectDraw Cooperative Levels and FPU Precision


DirectDraw, Direct3D, and the Direct3D Interfaces

Direct3D is implemented through COM objects and interfaces. The Direct3D interfaces are interfaces to the DirectDraw object. DirectDraw presents programmers with a single, unified object that encapsulates both the DirectDraw and Direct3D states. The DirectDraw object is the first object your application creates (by calling DirectDrawCreate) and the last object your application releases. Since the DirectDraw object represents the display device, and the display device implements many of the most important features of Direct3D, it makes sense that the abilities of Direct3D are incorporated into DirectDraw.

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 to that object—whether they are DirectDraw or Direct3D references—have been released. Therefore, if you release a Direct3D interface while holding a reference to a DirectDraw driver interface, and then query the Direct3D interface again, the Direct3D state will be preserved.

The DirectDraw object contains three Direct3D interfaces: IDirect3D, IDirect3D2, and IDirect3D3. The IDirect3D and IDirect3D2 interfaces are obsolete. They are provided for backward compatibility. New applications should use the IDirect3D3 interface to create other Direct3D objects such as viewports, lights, textures, and materials. For details, see Direct3D Interfaces.


Direct3D Interfaces

The functionality of Direct3D objects is accessed through the interfaces IDirect3D, IDirect3D2 and IDirect3D3. This section presents information on all three of these interfaces.

  • IDirect3D Interface
  • IDirect3D2 Interface
  • IDirect3D3 Interface


IDirect3D Interface

The IDirect3D interface supports the use of execute buffers. It is provided for compatibility with existing code. New applications should use the IDirect3D3 interface (see IDirect3D3 Interface).

If your application uses execute buffers, it must obtain a pointer to the IDirect3D interface from a DirectDraw object using the QueryInterface method.


IDirect3D2 Interface

A more straightforward style of Direct3D programming was introduced with the IDirect3D2 interface. This programming style is based on rendering primitives with a single call rather than rendering through an execute buffer. Devices exposed two methods for this new rendering style, IDirect3DDevice2::DrawPrimitive and IDirect3DDevice2::DrawIndexedPrimitive methods; these methods are supported in the most recent device interface, IDirect3DDevice3.

Applications get a pointer to the IDirect3D2 interface from a DirectDraw object using the QueryInterface method.

The IDirect3D2 interface is the starting point for creating other Direct3D Immediate Mode interfaces. Using it, your application can find and enumerate the types of Direct3D devices supported by a particular DirectDraw object. It also has methods needed to create other Direct3D Immediate Mode objects, such as viewports, materials and lights.

One of the most important differences between IDirect3D2 and its predecessor, IDirect3D, is that IDirect3D2 implements an IDirect3D2::CreateDevice method. This method creates a Direct3D device that supports the DrawPrimitive methods. For more information about the devices created by the IDirect3D2::CreateDevice method, see Direct3D Devices.

Note also that You cannot use new features that the IDirect3DDevice2 interface offers with IDirect3DDevice interface pointers. If your application calls the QueryInterface method on a DirectDraw surface and retrieves an IDirect3DDevice, it cannot access the features supported by later device interfaces. In addition, it cannot call the QueryInterface method on a device object created in this way to retrieve an IDirect3DDevice2 interface.


IDirect3D3 Interface

Like the IDirect3D2 interface, the IDirect3D3 interface supports the DrawPrimitive style of Direct3D programming. In addition, the IDirect3D3 interface extends the functionality of the DrawPrimitive-style programming by introducing the IDirect3DDevice3 interface. This new interface supports flexible vertex formats, vertex buffers, and new texturing capabilities. For additional information, see Vertex Formats, Textures, Vertex Buffers and Rendering.

Applications obtain a pointer to the IDirect3D3 interface from a DirectDraw object using the QueryInterface method. For details, see Retrieving an IDirect3D3 Interface.


Retrieving an IDirect3D3 Interface

When a Direct3D application starts up, it must obtain a pointer to an IDirect3D3 interface to access Direct3D functionality. Use the following steps to obtain a pointer to the IDirect3D3 interface:

To obtain a pointer to the IDirect3D3 interface

  1. Call DirectDrawCreate to create a DirectDraw device.
  2. Call the IUnknown::QueryInterface method to get a pointer to an IDirect3D3 interface.

The following diagram illustrates these steps:

The following code fragment demonstrates how to query for an IDirect3D3 interface:

LPDIRECTDRAW    lpDD;               // IDirectDraw Interface
LPDIRECT3D3     lpD3D;              // IDirect3D3 Interface

// Get an IDirectDraw interface.
// Use the current display driver.
hResult = DirectDrawCreate (NULL, &lpDD, NULL);
if (FAILED (hResult))
{
    // Code to handle an error goes here.
}

// Get D3D interface
hResult =
    lpDD->QueryInterface (IID_IDirect3D3, (void **)&lpD3D);
if (FAILED (hResult))
{
    // Code to handle the error goes here.
}


Using the IDirect3D3 Interface

Applications use the IDirect3D3 interface to create Direct3D devices, viewports, lights, and materials. In addition, the IDirect3D3 interface creates textures. Textures under the IDirect3D2 interface were manipulated using texture handles. The IDirect3D3 interface significantly extends the texturing capabilities of Direct3D. To accommodate these changes, the IDirect3D3 interface no longer utilizes texture handles. Instead, it makes use of texture interfaces. For more information, see Textures.

Direct3D creates devices by invoking the IDirect3D3::CreateDevice method. For details, see Direct3D Devices.

The IDirect3D3::CreateViewport method is called when creating viewports. For more information, see Viewports and Clipping.

Lights and materials are created through calls to the IDirect3D3::CreateLight and IDirect3D3::CreateMaterial methods respectively. For more information, see Lighting and Materials.


DirectDraw Cooperative Levels and FPU Precision

Direct3D always uses single-precision floating point calculations to increase the performance of rendering a 3-D scene. By default, Direct3D checks the precision state of the FPU (usually it's set for double precision), sets it to single precision, performs the necessary operations, then sets the FPU back to double precision before returning control to the calling application. This process is repeated for each rendering cycle.

You can improve the performance of Direct3D by including the DDSCL_FPUSETUP cooperative level flag when setting the DirectDraw cooperative level. Basically, this flag informs the system that your application does not rely on the FPU being set to double-precision. When you use DDSCL_FPUSETUP, Direct3D sets the FPU to single precision once, reinstating double-precision FPU calculations only when Direct3D is shut down, saving considerable performance overhead by eliminating the process of setting and resetting the FPU for each rendering cycle.

Obviously, if you set DDSCL_FPUSETUP, your application will be subject to the limitations of single-precision floating point values. As a result, this cooperative level setting should only be used when single-precision floating point values are acceptable for your application. If you require some double-precision floating point calculations, you can manually set the FPU precision mode to double as needed, but you must reset it to single precision before calling any Direct3D method. Failing to reset the FPU to single-precision mode when DDSCL_FPUSETUP will result in degraded performance.

Floating-point precision is thread specific, so when developing multi-threaded applications, be careful to check the FPU precision state to ensure that it is set and reset as appropriate for each thread.

Important Loading some dynamic link libraries (DLLs) at runtime can cause the FPU to be reset to double-precision mode. Some compilers, such as Microsoft Visual C++, set the default DLL entry point to _DllMainCrtStartup, a function that the compiler supplies to initialize the C/C++ runtime components. This function also sets the FPU precision mode to double precision. If an application sets the DDSCL_FPUSETUP cooperative level, then loads a DLL, Direct3D will not detect that the FPU has been reset, and performance will suffer.

If your application loads DLLs at runtime, it should check and reset the FPU precision mode immediately after the LoadLibrary Win32 function returns, and before calling any Direct3D functions. You can reset the precision mode explicitly or by calling the IDirectDraw4::SetCooperativeLevel method again, including the DDSCL_FPUSETUP flag. Using SetCooperativeLevel to set the FPU precision mode can also cause DirectDraw surfaces to be lost.

(You can explicitly set the entry point for DLLs you compile by using the /ENTRY: linker switch, but if you do, the C/C++ runtime will not be initialized automatically.)

The following is a sample source file for a console application that checks and sets the FPU precision setting by using in-line assembly language:

#include <windows.h>
#include <math.h>

// This function evaluates whether the floating-point
// control word is set to single precision/round to nearest/
// exceptions disabled. If these conditions don't hold, the
// function changes the control word to set them and returns
// TRUE, putting the old control word value in the passback
// location pointed to by pwOldCW.
BOOL MungeFPCW( WORD *pwOldCW )
{
    BOOL ret = FALSE;
    WORD wTemp, wSave;

    __asm fstcw wSave
    if (wSave & 0x300 ||            // Not single mode
        0x3f != (wSave & 0x3f) ||   // Exceptions enabled
        wSave & 0xC00)              // Not round to nearest mode
    {
        __asm
        {
            mov ax, wSave
            and ax, not 300h    ;; single mode
            or  ax, 3fh         ;; disable all exceptions
            and ax, not 0xC00   ;; round to nearest mode
            mov wTemp, ax
            fldcw   wTemp
        }
        ret = TRUE;
    }
    *pwOldCW = wSave;
    return ret;
}

void RestoreFPCW(WORD wSave)
{
    __asm fldcw wSave
}

void __cdecl main()
{
    WORD wOldCW;
    BOOL bChangedFPCW = MungeFPCW( &wOldCW );
    // Do something with control word as set by MungeFPCW.
    if ( bChangedFPCW )
        RestoreFPCW( wOldCW );
}


Direct3D Devices

This section provides an overview of the purpose for and uses of Direct3D devices. The overview is divided the following topics:

  • What Is a Direct3D Device?
  • Direct3D Device Types
  • Device Interfaces
  • Using Devices
  • Emulation Modes
  • AGP Surfaces and Direct3D Devices
  • Execute Buffers


What Is a Direct3D Device?

A Direct3D device is the rendering component of Direct3D. It encapsulates and stores the rendering state. In addition, a Direct3D device performs transformations and lighting operations, and rasterizes an image to a DirectDraw surface. Architecturally, Direct3D devices contain a transformation module, a lighting module, and a rasterizing module, as the following illustration shows.

Direct3D enables applications that utilize custom transformation and lighting models to bypass the Direct3D device's transformation and lighting modules. For details, see Vertex Formats.

Direct3D Immediate Mode devices support three device interfaces: IDirect3DDevice, IDirect3DDevice2, and IDirect3DDevice3. The IDirect3DDevice interface provides methods used for programming with execute buffers. However, this is a form of Direct3D development that is provided primarily for backward compatibility. The IDirect3DDevice2 interface introduced the DrawPrimitive methods of Direct3D programming. The IDirect3DDevice3 extends the DrawPrimitive functionality. The DrawPrimitive methods represent the preferred rendering approach. The interfaces share a few common methods that are useful in either programming style, and these methods are provided by all three interfaces for your convenience. For more information about the two rendering approaches, see Rendering.

Prior to the introduction of the IDirect3DDevice2 interface in DirectX 5.0, Direct3D devices were interfaces to DirectDrawSurface objects. The IDirect3DDevice2 interface implements a device-object model in which a Direct3DDevice object is entirely separate from DirectDraw surfaces. The IDirect3DDevice3 interface uses and extends the same device-object model. Because they are separated from DirectDraw surfaces and have independent lifetimes, Direct3D device objects are now able to use different DirectDraw surfaces as render targets at different times, if the application requires it. For information about rendering targets, see IDirect3DDevice3::SetRenderTarget.


Direct3D Device Types

This section introduces Direct3D devices, and presents information for each type of device. The following topics are discussed:

  • About Device Types
  • HAL Device
  • MMX Device
  • RGB Device
  • Ramp Device

Note The D3d.h header file defines a fifth device identifier (IID_IDirect3DRefDevice) for the reference rasterizer. The reference rasterizer is not intended for retail applications, and should only be used for reference or feature demonstration purposes. The reference rasterizer is not normally enumerated; you must set the EnumReference named value in the HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Direct3D\Drivers registry key to a nonzero DWORD value to enable its enumeration.


About Device Types

Direct3D supports four types of Direct3D devices. The Direct3D device that an application creates must correspond to the capabilities of the hardware on which the application is running. Direct3D provides rendering capabilities either by accessing 3-D hardware that is installed in the computer, or by emulating the capabilities of 3-D hardware in software. Therefore, Direct3D provides devices for both hardware access and for software emulation.

Hardware-accelerated devices give better performance than software-emulated devices. In most cases, your application will target machines that have hardware acceleration of some kind, and fall back on software emulation to accommodate lower-end computers.

With the exception of the reference rasterizer, software devices do not always support the same features as a hardware device. For example, software devices do not support assigning a texture to more than one texture stage at a time. Applications should always query for device capabilities to determine which features are supported.


HAL Device

If the computer on which your application is running is equipped with a display adapter that supports Direct3D, your application should use it for 3-D operations. Direct3D-compatible accelerator cards implement all or part of the transformation, lighting, and rasterizing modules in hardware.

Applications do not access 3-D cards directly. They call Direct3D functions and methods. Direct3D access the hardware through the hardware abstraction layer (HAL). If the computer your application is running on supports the HAL, it will gain the best performance using a HAL device.

To create a HAL device, your application calls IDirect3D3::CreateDevice, and passes the value IID_IDirect3DHALDevice as the first parameter. For details, see Creating a Direct3D Device.

Note Unlike the software emulation devices (MMX, RGB, reference rasterizer, and the legacy ramp device), hardware devices cannot render to 8-bit render target surfaces.


MMX Device

MMX is a special instruction set that some microprocessors support which provides increased performance for multimedia and 3-D processing. Direct3D uses MMX support, if it is installed, to increase rendering speed.

MMX devices are not hardware-accelerated devices like HAL devices. The transformation, lighting, and rasterizing modules are completely implemented in software. However, MMX devices provide much better performance than other types of software-emulated Direct3D devices.

If your application uses the IDirect3D2 interface, it must explicitly create an MMX device. However, beginning with the IDirect3D3 interface, MMX and RGB devices implement exactly the same feature set (see RGB Device). If an application attempts to create an RGB device and the microprocessor supports MMX technology, Direct3D will automatically create an MMX device.

Your application creates an MMX device by invoking the IDirect3D3::CreateDevice method and passing the value IID_IDirect3DMMXDevice in the first parameter. For additional information on creating Direct3D devices, see Creating a Direct3D Device. If the application explicitly requests that an MMX device is created and the user's computer does not support MMX technology, CreateDevice will fail.


RGB Device

If the user's computer provides no special hardware acceleration for 3-D operations, your application may emulate 3-D hardware in software. If the user's computer does not support MMX but has sufficient processing power, your application can create an RGB device. RGB devices emulate the functions of color 3-D hardware in software. Because an RGB device is software-emulated, it runs more slowly than a HAL device. It is also slower than an MMX device. For details, see Emulation Modes.

If the computer your application is running on provides MMX support, the IDirect3D3 interface will automatically create an MMX device when the program attempts to create an RGB device. For details, see MMX Device.

Applications create an RGB device with the IDirect3D3::CreateDevice function. Pass the value IID_IDirect3DRGBDevice as the first parameter. For additional information on creating Direct3D devices, see Creating a Direct3D Device.


Ramp Device

Note The ramp software emulation driver is obsolete, and not supported by interfaces added in DirectX 6.0 and later. You cannot create a Direct3D ramp device by using the IDirect3D3 interface, nor can you query an existing ramp device for the IDirect3DDevice3 interface. In short, ramp devices do not support any multiple texture blending options. For emulation of these features use the MMX or RGB software emulation devices.

A ramp device is a software-emulated device that provides monochrome lighting. Applications can select it when the user's computer does not have sufficient processing power to support any other types of Direct3D devices. For details, see Emulation Modes.

Ramp devices are provided primarily for backward compatibility with legacy applications. In general, computers that do not have sufficient processing power to support RGB devices are not suited to 3-D applications.

An application creates a ramp device by invoking the IDirect3D2::CreateDevice method and passing the value IID_IDirect3DRampDevice as the first parameter. For additional information on creating Direct3D devices, see Creating a Direct3D Device.


Device Interfaces

You use a device interface to manipulate a Direct3DDevice object's rendering states, lighting states, and to perform rendering operations. Although devices support three iterations of the device interface (IDirect3DDevice, IDirect3DDevice2, and IDirect3DDevice3), it is unlikely that your applications will need to use more than one of them at a time. Which interface you use should be determined by the rendering approach—the DrawPrimitive methods or execute buffers—your application is going to use. The following paragraphs provide additional information about these interfaces and the rendering approaches they represent:

Execute buffers

The IDirect3DDevice interface supports rendering through execute buffers; the original method of Direct3D programming. This interface is supported mostly for backward compatibility, as the DrawPrimitive rendering architecture is easier to use. It is recommended that you use the IDirect3DDevice3 interface for developing new applications, unless your application specifically targets versions of DirectX prior to DirectX 5.0.

All Direct3D device types support the IDirect3DDevice interface.

DrawPrimitive rendering

The two most recent iterations of the device interface, IDirect3DDevice3 and IDirect3DDevice2, support the DrawPrimitive family of rendering methods in favor of rendering with execute buffers. The DrawPrimitive methods greatly simplify the process of preparing and rendering vertices to the render target surface, and are widely considered the preferred rendering approach.

If your application uses the DrawPrimitive methods, there is little reason to use anything but the newest version of the device interface (in fact, this documentation provides information only for the most recent version). Direct3D, in compliance with COM standards for backward compatibility, supports all interface versions, but it is recommended that you use the most recent version to take advantage of any new features and performance enhancements.

The IDirect3DDevice2 interface, created for DirectX 5.0, introduced the DrawPrimitive rendering architecture. DrawPrimitive-based rendering methods are simpler to use than execute buffers and provide a more direct style of Direct3D programming. For details, see Rendering. All Direct3D device types support the IDirect3DDevice2 interface.

Like the IDirect3DDevice2 interface, the IDirect3DDevice3 interface provides support for the DrawPrimitive methods. In conjunction with the IDirect3D3 interface, it also sports an enhanced feature set which includes multiple texture blending, vertex buffers, and enhancements to the 3-D geometry rendering pipeline. The IDirect3DDevice3 interface furnishes the same methods that the IDirect3DDevice2 interface did. However, it adds new render states to the IDirect3DDevice3::SetRenderState method to support multiple texture blending.

All Direct3D device types support the IDirect3DDevice3 interface.


Using Devices

This section provides information about using Direct3D devices in a Direct3D Immediate Mode application. Information is divided into the following topics:

  • Enumerating Direct3D Devices
  • Creating a Direct3D Device
  • Setting Transformations
  • Rendering
  • Lighting States


Enumerating Direct3D Devices

This section contains information on two primary tasks involved in enumerating Direct3D Devices. Information is organized into the following topics:

  • Starting Device Enumeration
  • Selecting an Enumerated Device


Starting Device Enumeration

Applications can query the hardware they run on to detect which types of Direct3D devices it supports. The most important API element in this task is IDirect3D3::EnumDevices, which enumerates all of the Direct3D devices that the hardware is capable of supporting. It invokes the D3DEnumDevicesCallback function to select the device that will be used. The D3DEnumDevicesCallback function is supplied by you in your application. Note that because this callback function is supplied by your application, its name can be anything you want.

The following code fragment illustrates the process of enumerating and selecting a Direct3D device. In this example, the device enumeration callback function is named EnumDeviceCallback. A pointer to EnumDeviceCallback is passed to the IDirect3D3::EnumDevices method, which calls EnumDeviceCallback for each device being enumerated.

// In this code fragment, the variable lpd3d contains a valid
// pointer to the IDirect3D3 interface that the application obtained
// prior to executing this code.

BOOL fDeviceFound = FALSE;
hRes = lpd3d->EnumDevices(EnumDeviceCallback, &fDeviceFound);
if (FAILED(hRes))
{
    // Code to handle the error goes here.
}

if (!fDeviceFound)
{
    // Code to handle the error goes here.
}


Selecting An Enumerated Device

The D3DEnumDevicesCallback function is invoked for each Direct3D device installed on the system. When it is called, its first parameter is a globally unique ID (GUID) for the device that is being enumerated. The value of the GUID will be IID_IDirect3DHALDevice, IID_IDirect3DMMXDevice, IID_IDirect3DRGBDevice, or IID_IDirect3DRampDevice. The D3DEnumDevicesCallback function selects the device that is most appropriate for your application based on this information.

The second and third parameters to the D3DEnumDevicesCallback function are text strings containing the name and user-friendly description of the device.

The fourth parameter is a pointer to a D3DDEVICEDESC structure containing information about the hardware capabilities of the device. Even if the device being enumerated is a HAL device, the particular hardware may not support all of the capabilities that the Direct3D API allows.

The fifth parameter to the D3DEnumDevicesCallback function contains a pointer to a D3DDEVICEDESC structure that describes the software-emulated capabilities of the computer on which your application is running. This information is relevant when you are using a software-emulated device (MMX, RGB, or RAMP device).

The last parameter is a programmer-defined value. Your application passes this value to the IDirect3D3::EnumDevices method. It in turn passes this value to the D3DEnumDevicesCallback function.

The following code fragment illustrates how to create a D3DEnumDevicesCallback function. In this example, the application-supplied callback function is named EnumDeviceCallback. The EnumDeviceCallback function uses the following algorithm to choose an appropriate Direct3D device:

  1. Discard any devices which don't match the current display depth.
  2. Discard any devices which can't do Gouraud-shaded triangles.
  3. If a hardware device is found which matches points 1 and 2, use it. However, if the application is running in debug mode, it will not use the hardware device.
  4. Otherwise favor Mono/Ramp mode software renderers over RGB ones; until MMX is widespread, Mono will be faster.

The code for the EnumDeviceCallback function is shown in the following example:

// This function is written with the assumption that the following
// global variables are declared in the program.
// DWORD                   dwDeviceBitDepth          = 0;
// GUID                    guidDevice;
// char                    szDeviceName[MAX_DEVICE_NAME];
// char                    szDeviceDesc[MAX_DEVICE_DESC];
// D3DDEVICEDESC           d3dHWDeviceDesc;
// D3DDEVICEDESC           d3dSWDeviceDesc;

static HRESULT WINAPI
EnumDeviceCallback(LPGUID          lpGUID,
                   LPSTR           lpszDeviceDesc,
                   LPSTR           lpszDeviceName,
                   LPD3DDEVICEDESC lpd3dHWDeviceDesc,
                   LPD3DDEVICEDESC lpd3dSWDeviceDesc,
                   LPVOID          lpUserArg)
{
    BOOL            fIsHardware;
    LPD3DDEVICEDESC lpd3dDeviceDesc;

    // If there is no hardware support the color model is zero.

    fIsHardware     = (lpd3dHWDeviceDesc->dcmColorModel != 0);
    lpd3dDeviceDesc = (fIsHardware ? lpd3dHWDeviceDesc :
                                     lpd3dSWDeviceDesc);

    // Does the device render at the depth we want?
     if ((lpd3dDeviceDesc->dwDeviceRenderBitDepth & dwDeviceBitDepth)
        == 0)
    {
        // If not, skip this device.

        return D3DENUMRET_OK;
    }

    // The device must support Gouraud-shaded triangles.

    if (D3DCOLOR_MONO == lpd3dDeviceDesc->dcmColorModel)
    {
        if (!(lpd3dDeviceDesc->dpcTriCaps.dwShadeCaps &
              D3DPSHADECAPS_COLORGOURAUDMONO))
        {
            // No Gouraud shading. Skip this device.

            return D3DENUMRET_OK;
        }
    }
    else
    {
        if (!(lpd3dDeviceDesc->dpcTriCaps.dwShadeCaps &
              D3DPSHADECAPS_COLORGOURAUDRGB))
        {
            // No Gouraud shading. Skip this device.

            return D3DENUMRET_OK;
        }
    }

    // If a software device was found on a previous invocation
    // of this callback function.
    if (!fIsHardware && *lpUserArg &&
           (D3DCOLOR_RGB == lpd3dDeviceDesc->dcmColorModel))
    {
        // If this is software RGB and we already have found
        // a software monochromatic renderer, we are not
        // interested. Skip this device.

        return D3DENUMRET_OK;
    }

    //
    // This is a device we are interested in. Save the details.
    //
    *lpUserArg = TRUE;
    CopyMemory(&guidDevice, lpGUID, sizeof(GUID));
    strcpy(szDeviceDesc, lpszDeviceDesc);
    strcpy(szDeviceName, lpszDeviceName);
    CopyMemory(&d3dHWDeviceDesc, lpd3dHWDeviceDesc,
               sizeof(D3DDEVICEDESC));
    CopyMemory(&d3dSWDeviceDesc, lpd3dSWDeviceDesc,
               sizeof(D3DDEVICEDESC));

    // If this is a hardware device, we have found
    // what we are looking for.
     if (fIsHardware)
        return D3DENUMRET_CANCEL;

    // Otherwise, keep looking.

    return D3DENUMRET_OK;
}


Creating a Direct3D Device

When creating a device, you must choose which style of Direct3D programming your application will use — execute buffers or the DrawPrimitive methods. This choice determines which type of interface pointer your application needs to obtain when it creates the device. If you elect to use execute buffers, your application must obtain a pointer to the IDirect3DDevice interface. If you choose to render with the DrawPrimitive methods, your application must obtain a pointer to the IDirect3DDevice3 interface.

The following topics provide details on how to create a device for your application's needs:

  • Creating a Device for Execute Buffers
  • Creating a Device for the DrawPrimitive Methods

Note Some popular hardware devices require that the render target and depth buffer surfaces use the same bit depth. On such hardware, if your application uses a 16-bit render target surface, the attached depth buffer must also be 16-bits. For a 32-bit render target surface, the depth buffer must be 32-bits, of which 8-bits can be used for stencil buffering (if needed).

If the hardware upon which your application is running has this requirement, and your application fails to meet it, any attempts to create a rendering device that uses the non-compliant surfaces will fail. You can use the DirectDraw method, IDirectDraw4::GetDeviceIdentifier to track hardware that imposes this limitation.


Creating a Device for Execute Buffers

To use execute buffers methods, your application must first initialize DirectDraw in the normal manner and obtain a pointer to the IDirect3D3 interface. For details, see Retrieving an IDirect3D3 Interface. Your application should create a surface that includes the DDSCAPS_3DDEVICE capability. For information on creating surfaces, see Creating Surfaces. It must then call the IUnknown::QueryInterface method for that surface to obtain a pointer to an IDirect3DDevice interface. Use the IDirect3DDevice::CreateExecuteBuffer to create an execute buffer and obtain a pointer to an IDirect3DExecuteBuffer interface. The following figure illustrates this process.


Creating a Device for the DrawPrimitive Methods

To use the DrawPrimitive methods, your application must first initialize the DirectDraw object in the normal manner and obtain a pointer to the IDirect3D3 interface. For details, see Retrieving an IDirect3D3 Interface. It must then call the IDirect3D3::CreateDevice method to create a Direct3D device. This method will pass a pointer to the IDirect3DDevice3 interface your application.

The following figure illustrates the process for creating a Direct3D device that supports the DrawPrimitive methods.

This code fragment illustrates this process:

LPDIRECTDRAW    lpDD;               // DirectDraw Interface
LPDIRECT3D3     lpD3D;              // Direct3D3 Interface
LPDIRECTDRAWSURFACE4  lpddsRender;  // Rendering surface
LPDIRECT3DDEVICE3     lpd3dDevice;  // D3D Device

// Create DirectDraw interface.
// Use the current display driver.
hResult = DirectDrawCreate (NULL, &lpDD, NULL);
if (FAILED (hResult))
{
    // Code to handle the error goes here.
}

// Get an IDirect3D3 interface
hResult =
    lpDD->QueryInterface (IID_IDirect3D3, (void **)&lpD3D);
if (FAILED (hResult))
{
    // Code to handle the error goes here.
}

//
// Code for the following tasks is omitted for clarity.
//
// Applications will need to set the cooperative level at this point.
// Full-screen applications will probably need to set the display
// mode.
// The primary surface should be created here.
// The rendering surface must be created at this point. It is
// assumed in this code fragment that, once created, the rendering
// surface is pointed to by the variable lpddsRender.
// If a z-buffer is being used, it should be created here.
// Direct3D device enumeration can be done at this point.

hResult = lpD3D->CreateDevice (IID_IDirect3DHALDevice,
                               lpddsRender,
                               &lpd3dDevice,
                               NULL);

The preceding sample invokes the IDirect3D3::CreateDevice method to create the Direct3D device. In the case of this sample, a Direct3D HAL device is created if the call is successful.

Note that the target DirectDraw rendering surface that your application creates must be created for use as a Direct3D rendering target. To do this, it must pass a DDSURFACEDESC2 structure to the IDirectDraw4::CreateSurface method. The DDSURFACEDESC2 structure has a member called ddsCaps, which is a structure of type DDSCAPS. The DDSCAPS structure contains a member named dwCaps, which must be set to DDSCAPS_3DDEVICE when IDirectDraw4::CreateSurface is invoked.

The render target surface you use must be created in display memory (with the DDSCAPS_VIDEOMEMORY flag) when it will be use with a hardware-accelerated rendering device, and in system memory (using the DDSCAPS_SYSTEMMEMORY flag) otherwise.


Setting Transformations

Transformations are applied using the IDirect3DDevice3::SetTransform method. For example, you could use code like this to set the view transformation:

    HRESULT hr
    D3DMATRIX  view;

    // Fill in the view matrix.

    hr = lpDev->SetTransform(D3DTRANSFORMSTATE_VIEW, &view);

    if(FAILED(hr))
        return hr;

There are three possible settings for the first parameter in a call to IDirect3DDevice3::SetTransform: D3DTRANSFORMSTATE_WORLD, D3DTRANSFORMSTATE_VIEW, and D3DTRANSFORMSTATE_PROJECTION. These transformation states are defined in the D3DTRANSFORMSTATETYPE enumerated type.


Rendering

Direct3D offers the DrawPrimitive family of methods to make rendering a 3-D scene a simple and flexible process. The DrawPrimitive architecture is recommended over the execute buffer rendering model. As a result, the following topics present a DrawPrimitive-centered discussion about rendering:

  • About Rendering
  • Beginning and Ending a Scene
  • Clearing Surfaces
  • Rendering Primitives
  • Primitive Types
  • Render States

Although most applications will use the DrawPrimitive family of rendering methods, Direct3D still supports the use of execute buffers. For more information about rendering with execute buffers, see Execute Buffers.


About Rendering

Direct3D device interfaces later than the first device interface (IDirect3DDevice) support the DrawPrimitive rendering architecture. The DrawPrimitive family of methods—introduced in DirectX 5.0 with the IDirect3DDevice2 interface, and extended by IDirect3DDevice3—can render different types of primitives such as points, lines, or collections of triangles. (Primitives are discussed in detail in Primitive Types.)

You can group vertices for a primitive in two basic ways:

  • In an array that includes all vertices for the primitive, in order.
  • In an unordered array of vertices, accompanied by an ordered array of values, where each value is the index of a vertex in the unordered array. Primitives of this type are sometimes referred to as "indexed primitives."

The DrawPrimitive architecture makes it possible to render groups of vertices that define a primitive in a single call, or to render the vertices that comprise a primitive one-by-one. For more information, see Rendering Primitives.


Beginning and Ending a Scene

You notify Direct3D that scene rendering is about to begin by calling the IDirect3DDevice3::BeginScene method. BeginScene causes the system to check its internal data structures, the availability and validity of rendering surfaces, and sets an internal flag to signal that a scene is in progress. After you begin a scene, you can call the various rendering methods to render the primitives or individual vertices that make up the objects in the scene. Attempts to call rendering methods when a scene is not in progress will fail, returning D3DERR_SCENE_NOT_IN_SCENE. For more information about the rendering methods, see Rendering Primitives.

After you complete the scene, call the IDirect3DDevice3::EndScene method. The EndScene method clears an internal flag that signals when a scene is in progress, flushes cached data, and verifies the integrity of the rendering surfaces.

All rendering methods must be bracketed by calls to the BeginScene and EndScene methods. If surfaces are lost, or if internal errors occur, the scene methods return error values. You must call EndScene for each time you call the BeginScene method, even if BeginScene fails. For example, some simple scene code might look like this:

HRESULT hr;

if(SUCCEEDED(lpD3D->BeginScene()))
{
    // Render primitives only if the scene
    // started successfully.
}

// Always close the scene, even if BeginScene fails.
hr = lpD3D->EndScene();
if(FAILED(hr))
    return hr;

You cannot embed scenes; that is, you must complete rendering a scene before you can begin another one. Calling IDirect3DDevice3::EndScene when IDirect3DDevice3::BeginScene has not been called will return the D3DERR_SCENE_NOT_IN_SCENE error value. Likewise, calling BeginScene when a previous scene has not been completed (with the EndScene method) results in the D3DERR_SCENE_IN_SCENE error.

You should not attempt to call GDI functions on DirectDraw surfaces, such as the render target or textures, while a scene is being rendered (between BeginScene and EndScene calls). Attempts to do so can prevent the results of the GDI operations from being visible. If your application uses GDI functions, make sure that all GDI calls are made outside of the scene functions.


Clearing Surfaces

Before rendering objects in a scene, you should clear the viewport on the render target surface (or a subset of the viewport). Clearing the viewport causes the system to set the desired portion of the render target surface and any attached depth or stencil buffers to a desired state. This resets the areas of the surface that will be rendered again and resets the corresponding areas of the depth and stencil buffers, if any are in use. Clearing a render target surface can set the desired region to a default color or texture. For depth and stencil buffers, this can set a depth or stencil value.

The IDirect3DViewport3 interface offers the IDirect3DViewport3::Clear and IDirect3DViewport3::Clear2 methods to clear the viewport. For more information about using these methods, see Clearing a Viewport in the Viewports and Clipping section.


Rendering Primitives

The following topics introduce the DrawPrimitive rendering methods and provides information about using them in your application:

  • The DrawPrimitive Methods
  • Rendering Strided Vertices


The DrawPrimitive Methods

Direct3D offers several methods to render primitives and indexed primitives in a single call or as individual vertices. All rendering methods in the IDirect3DDevice3 interface accept a combination of flexible vertex format flags that describe the vertex type your application uses; these flags also determine which parts of the geometry pipeline the system will apply. (This differs from the version of the methods in the IDirect3DDevice2, which accept only the concrete vertex formats identified by members of the D3DPRIMITIVETYPE enumeration.) For more information about these descriptors, see Vertex Formats.

The DrawPrimitive family of rendering methods can be subdivided according to the style of primitive (non-indexed or indexed) a given method is capable of rendering. The system offers methods for both primitive styles, specified as groups of vertices or one vertex at a time. The following paragraphs reflect this subdivision:

Non-indexed and Indexed Primitive Methods
IDirect3DDevice3::DrawPrimitive, IDirect3DDevice3::DrawPrimitiveStrided, and IDirect3DDevice3::DrawPrimitiveVB render groups of non-indexed vertices, strided vertices, and non-indexed vertices contained within vertex buffers.

The IDirect3DDevice3::DrawIndexedPrimitive, IDirect3DDevice3::DrawIndexedPrimitiveStrided, and IDirect3DDevice3::DrawIndexedPrimitiveVB methods render vertex groups by indexing into a provided array of vertices, strided vertices, or by indexing into vertices within a vertex buffer.

Non-indexed and Indexed Vertex Methods
The IDirect3DDevice3::Begin method informs the system that you are beginning a sequence of vertices, and you can render the vertices with subsequent calls to IDirect3DDevice3::Vertex. When you are done with a sequence of vertices, you must call the IDirect3DDevice3::End method.

Similar to the non-indexed vertex rendering methods, the system offers the IDirect3DDevice3::BeginIndexed method to begin rendering vertices by their index, followed by calls to IDirect3DDevice3::Index for each vertex. (Just like non-indexed vertices, you finish the vertex sequence by calling IDirect3DDevice3::End.)

When you render a primitive, the associated methods accept parameters that describe the type of primitive being rendered (such as a triangle strip, a triangle list, or another primitive type), the vertex format, rendering behavior flags, and vertex information. These flags and their effects are documented in the references for the rendering methods.

Note that the number of vertices you need to provide for the methods depends on the type of primitive you are rendering. For instance, if you're rendering a line list, you must provide at least two vertices to define a single line, and the total number must be an even value. Likewise for a triangle list, you must include at least three vertices, with the total evenly divisible by three. For information about vertex counts for other types of primitives, see Primitive Types and D3DPRIMITIVETYPE.

Vertex buffers, and the methods to render from them, provide performance and ease-of-use enhancements that improve upon rendering vertices from your own data structures. For more information, see Vertex Buffers.


Rendering Strided Vertices

Because of the indirection provided by strided vertices—detailed in the Strided Vertex Format section—applications must take care to set up the vertices properly. Often, developers forget to include a vertex component in the associated D3DDRAWPRIMITIVESTRIDEDDATA structures. This oversight doesn't necessarily cause the rendering methods to fail, but can result in "missing" geometry that is difficult to troubleshoot.

The following code shows one way that you might set up and render strided vertices:

//---------------------------------------------
// A custom vertex format that includes XYZ, a
// diffuse color & two sets of texture coords.
//---------------------------------------------
struct MTVERTEX
{
    FLOAT x, y, z;
    DWORD dwColor;
    FLOAT tuBase, tvBase;
    FLOAT tuLightMap, tvLightMap;
};

// Make an array of custom vertices.
MTVERTEX g_avVertices[36];
// Fill the array.
//  (vertex at index 0)
//  .
//  .
//  .
//  (vertex at index 35)

// Construct strided vertices vertex using the array of
// custom vertices already defined.
D3DDRAWPRIMITIVESTRIDEDDATA g_StridedData;

// Assign the addresses of the various interleaved components
// to their corresponding strided members.
g_StridedData.position.lpvData          = &g_avWallVertices[24].x;
g_StridedData.diffuse.lpvData           = &g_avWallVertices[24].dwColor;
g_StridedData.textureCoords[0].lpvData  = &g_avWallVertices[24].tuBase;
g_StridedData.textureCoords[1].lpvData  = &g_avWallVertices[24].tuLightMap;
g_StridedData.position.dwStride         = sizeof(MTVERTEX);
g_StridedData.diffuse.dwStride          = sizeof(MTVERTEX);
g_StridedData.textureCoords[0].dwStride = sizeof(MTVERTEX);
g_StridedData.textureCoords[1].dwStride = sizeof(MTVERTEX);

// Render the vertices with multiple texture blending (Modulate).
g_pd3dDevice->SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_MODULATE );
g_pd3dDevice->SetTexture( 0, g_BaseTextureMap);
g_pd3dDevice->SetTexture( 1, g_LightMap);
g_pd3dDevice->DrawPrimitiveStrided( D3DPT_TRIANGLELIST,
                        D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX2,
                        &g_StridedData, 12, NULL );


Primitive Types

Direct3D can create and manipulate the following types of primitives:

  • Point Lists
  • Line Lists
  • Line Strips
  • Triangle Lists
  • Triangle Strips
  • Triangle Fans

You render all of these primitive types with the IDirect3DDevice3::DrawPrimitive or IDirect3DDevice3::DrawIndexedPrimitive methods. For more information, see Rendering.


Point Lists

A point list is a collection of vertices that are rendered as isolated points. Your application can use them in 3-D scenes for star fields, or dotted lines on the surface of a polygon.

Create a point list by filling an array of vertices, as in the following code fragment:

const DWORD TOTAL_VERTS=6;
D3DVERTEX lpVerts[TOTAL_VERTS];

lpVerts[0] = D3DVERTEX(D3DVECTOR(-5,-5,0),D3DVECTOR(0,0,-1),0,0);
lpVerts[1] = D3DVERTEX(D3DVECTOR(0,5,0),D3DVECTOR(0,0,-1),0,0);
lpVerts[2] = D3DVERTEX(D3DVECTOR(5,-5,0),D3DVECTOR(0,0,-1),0,0);
lpVerts[3] = D3DVERTEX(D3DVECTOR(10,5,0),D3DVECTOR(0,0,-1),0,0);
lpVerts[4] = D3DVERTEX(D3DVECTOR(15,-5,0),D3DVECTOR(0,0,-1),0,0);
lpVerts[5] = D3DVERTEX(D3DVECTOR(20,5,0),D3DVECTOR(0,0,-1),0,0);

Render the point list using the IDirect3DDevice3::DrawPrimitive method. The following code fragment illustrates the use of IDirect3DDevice3::DrawPrimitive for drawing the point list in the preceding example. All calls to IDirect3DDevice3::DrawPrimitive must occur between IDirect3DDevice3::BeginScene and IDirect3DDevice3::EndScene.

HRESULT hResult;
// This code fragment assumes that lpDirect3DDevice3 is a valid
// pointer to an IDirect3DDevice3 interface.
hResult =
    lpDirect3DDevice3->DrawPrimitive(D3DPT_POINTLIST,
                                     D3DFVF_VERTEX,
                                     lpVerts,
                                     TOTAL_VERTS,
                                     D3DDP_WAIT);

The following illustration shows the resulting points.

Your application can apply materials and textures to a point list. The colors in the material or texture only appear at the points drawn, and not anywhere between the points.


Line Lists

A line list is a list of isolated, straight line segments. Line lists are useful for such tasks as adding sleet or heavy rain to a 3-D scene.

Create a line list by filling an array of vertices, as in the following code fragment. The number of vertices in a line list must be greater than or equal to two, and it must be even.

const DWORD TOTAL_VERTS=6;
D3DVERTEX lpVerts[TOTAL_VERTS];

lpVerts[0] = D3DVERTEX(D3DVECTOR(-5,-5,0),D3DVECTOR(0,0,-1),0,0);
lpVerts[1] = D3DVERTEX(D3DVECTOR(0,5,0),D3DVECTOR(0,0,-1),0,0);
lpVerts[2] = D3DVERTEX(D3DVECTOR(5,-5,0),D3DVECTOR(0,0,-1),0,0);
lpVerts[3] = D3DVERTEX(D3DVECTOR(10,5,0),D3DVECTOR(0,0,-1),0,0);
lpVerts[4] = D3DVERTEX(D3DVECTOR(15,-5,0),D3DVECTOR(0,0,-1),0,0);
lpVerts[5] = D3DVERTEX(D3DVECTOR(20,5,0),D3DVECTOR(0,0,-1),0,0);

Render the line list using the IDirect3DDevice3::DrawPrimitive method. The following code fragment illustrates the use of IDirect3DDevice3::DrawPrimitive for drawing the line list in the preceding example. Remember that all calls to IDirect3DDevice3::DrawPrimitive must occur between IDirect3DDevice3::BeginScene and IDirect3DDevice3::EndScene.

HRESULT hResult;
// This code fragment assumes that lpDirect3DDevice3 is a valid
// pointer to an IDirect3DDevice3 interface.
hResult =
    lpDirect3DDevice3 ->DrawPrimitive(D3DPT_LINELIST,
                                      D3DFVF_VERTEX,
                                      lpVerts,
                                      TOTAL_VERTS,
                                      D3DDP_WAIT);

The following illustration shows the resulting lines.

You can apply materials and textures to a line list. The colors in the material or texture only appear along the lines drawn, not at any point in between the lines.


Line Strips

A line strip is a primitive that is composed of connected line segments. Your application can use line strips for creating polygons that are not closed. A closed polygon is a polygon whose last vertex is connected to its first vertex by a line segment. If your application makes polygons based on line strips, the vertices are not guaranteed to be coplanar.

You create a line strip by filling an array of vertices, as in the following code fragment:

const DWORD TOTAL_VERTS=6;
D3DVERTEX lpVerts[TOTAL_VERTS];

lpVerts[0] = D3DVERTEX(D3DVECTOR(-5,-5,0),D3DVECTOR(0,0,-1),0,0);
lpVerts[1] = D3DVERTEX(D3DVECTOR(0,5,0),D3DVECTOR(0,0,-1),0,0);
lpVerts[2] = D3DVERTEX(D3DVECTOR(5,-5,0),D3DVECTOR(0,0,-1),0,0);
lpVerts[3] = D3DVERTEX(D3DVECTOR(10,5,0),D3DVECTOR(0,0,-1),0,0);
lpVerts[4] = D3DVERTEX(D3DVECTOR(15,-5,0),D3DVECTOR(0,0,-1),0,0);
lpVerts[5] = D3DVERTEX(D3DVECTOR(20,5,0),D3DVECTOR(0,0,-1),0,0);

Render the line list using the IDirect3DDevice3::DrawPrimitive method. The following code fragment illustrates the use of IDirect3DDevice3::DrawPrimitive for drawing the line strip in the preceding example. Remember that all calls to IDirect3DDevice3::DrawPrimitive must occur between IDirect3DDevice3::BeginScene and IDirect3DDevice3::EndScene.

HRESULT hResult;
// This code fragment assumes that lpDirect3DDevice3 is a valid
// pointer to an IDirect3DDevice3 interface.
hResult =
    lpDirect3DDevice3 ->DrawPrimitive(D3DPT_LINESTRIP,
                                      D3DFVF_VERTEX,
                                      lpVerts,
                                      TOTAL_VERTS,
                                      D3DDP_WAIT);

The following illustration shows the line strip that the previous code produces.


Triangle Lists

A triangle list is a list of isolated triangles. They may or may not be near each other. A triangle list must have at least three vertices. The total number of vertices must be divisible by three.

Use triangle lists when you want to create an object that is composed of disjoint pieces. For instance, one way to create a force field wall in a 3-D game is to specify a large list of small, unconnected triangles. Then apply a material or texture to the triangle list that emits light. Each triangle in the wall appears to glow. The scene behind the wall becomes partially visible through the gaps between the triangles, as players might expect when looking at a force field.

Triangle lists are also useful for creating primitives that have sharp edges and are shaded with Gouraud shading. See Face and Vertex Normal Vectors.

Create a triangle list by filling an array of vertices, as in the following code fragment:

const DWORD TOTAL_VERTS=6;
D3DVERTEX lpVerts[TOTAL_VERTS];

lpVerts[0] = D3DVERTEX(D3DVECTOR(-5,-5,0),D3DVECTOR(0,0,-1),0,0);
lpVerts[1] = D3DVERTEX(D3DVECTOR(0,5,0),D3DVECTOR(0,0,-1),0,0);
lpVerts[2] = D3DVERTEX(D3DVECTOR(5,-5,0),D3DVECTOR(0,0,-1),0,0);
lpVerts[3] = D3DVERTEX(D3DVECTOR(10,5,0),D3DVECTOR(0,0,-1),0,0);
lpVerts[4] = D3DVERTEX(D3DVECTOR(15,-5,0),D3DVECTOR(0,0,-1),0,0);
lpVerts[5] = D3DVERTEX(D3DVECTOR(20,5,0),D3DVECTOR(0,0,-1),0,0);

Render a triangle list using the IDirect3DDevice3::DrawPrimitive method. The following code fragment illustrates the use of IDirect3DDevice3::DrawPrimitive for drawing the triangle list in the preceding example. Remember that all calls to IDirect3DDevice3::DrawPrimitive must occur between IDirect3DDevice3::BeginScene and IDirect3DDevice3::EndScene.

HRESULT hResult;
// This code fragment assumes that lpDirect3DDevice3 is a valid
// pointer to an IDirect3DDevice3 interface.
hResult =
    lpDirect3DDevice3 ->DrawPrimitive(D3DPT_TRIANGLELIST,
                                      D3DFVF_VERTEX,
                                      lpVerts,
                                      TOTAL_VERTS,
                                      D3DDP_WAIT);

The following illustration depicts the resulting triangles.


Triangle Strips

A triangle strip is a series of connected triangles. Because the triangles are connected, the application does not need to repeatedly specify all three vertices for each triangle. For example, you only need seven vertices to define the following triangle strip.

The system uses vertices v1, v2, and v3 to draw the first triangle, v2, v4, and v3 to draw the second triangle, v3, v4, and v5 to draw the third, v4, v6, and v5 to draw the fourth, and so on. Notice that the vertices of the second and fourth triangles are out of order; this is required to make sure that all of the triangles are drawn in a clockwise orientation.

Most objects in 3-D scenes are composed of triangle strips. This is because triangle strips can be used to specify complex objects in a way that makes efficient use of memory and processing time. Triangle strips are also much easier to use than the D3DTRIANGLE structure that is used in conjunction with execute buffers.

Create a triangle strip by filling an array of vertices, as in the following code fragment:

const DWORD TOTAL_VERTS=6;
D3DVERTEX lpVerts[TOTAL_VERTS];

lpVerts[0] = D3DVERTEX(D3DVECTOR(-5,-5,0),D3DVECTOR(0,0,-1),0,0);
lpVerts[1] = D3DVERTEX(D3DVECTOR(0,5,0),D3DVECTOR(0,0,-1),0,0);
lpVerts[2] = D3DVERTEX(D3DVECTOR(5,-5,0),D3DVECTOR(0,0,-1),0,0);
lpVerts[3] = D3DVERTEX(D3DVECTOR(10,5,0),D3DVECTOR(0,0,-1),0,0);
lpVerts[4] = D3DVERTEX(D3DVECTOR(15,-5,0),D3DVECTOR(0,0,-1),0,0);
lpVerts[5] = D3DVERTEX(D3DVECTOR(20,5,0),D3DVECTOR(0,0,-1),0,0);

Your application can then render the triangle strip using the IDirect3DDevice3::DrawPrimitive method. The following code fragment illustrates the use of IDirect3DDevice3::DrawPrimitive for drawing the triangle strip in the preceding example. Remember that all calls to IDirect3DDevice3::DrawPrimitive must occur between IDirect3DDevice3::BeginScene and IDirect3DDevice3::EndScene.

HRESULT hResult;
// This code fragment assumes that lpDirect3DDevice3 is a valid
// pointer to an IDirect3DDevice3 interface.
hResult =
    lpDirect3DDevice3 ->DrawPrimitive(D3DPT_TRIANGLESTRIP,
                                      D3DFVF_VERTEX,
                                      lpVerts,
                                      TOTAL_VERTS,
                                      D3DDP_WAIT);

The following illustration shows the resulting triangle strip.


Triangle Fans

A triangle fan is similar to a triangle strip, except that all of the triangles share one vertex, as shown in the following illustration.

The system uses vertices v2, v3, and v1 to draw the first triangle, v3, v4, and v1 to draw the second triangle, v4, v5, and v1 to draw the third triangle, and so on. (When flat shading is enabled, the system shades the triangle with the color from its first vertex.)

Your application can create a triangle fan by filling an array of vertices, as shown in the following code fragment:

const DWORD TOTAL_VERTS=6;
D3DVERTEX lpVerts[TOTAL_VERTS];

lpVerts[0] = D3DVERTEX(D3DVECTOR(0,0,0),D3DVECTOR(0,0,-1),0,0);
lpVerts[1] = D3DVERTEX(D3DVECTOR(-5,-5,0),D3DVECTOR(0,0,-1),0,0);
lpVerts[2] = D3DVERTEX(D3DVECTOR(-3,7,0),D3DVECTOR(0,0,-1),0,0);
lpVerts[3] = D3DVERTEX(D3DVECTOR(0,10,0),D3DVECTOR(0,0,-1),0,0);
lpVerts[4] = D3DVERTEX(D3DVECTOR(3,7,0),D3DVECTOR(0,0,-1),0,0);
lpVerts[5] = D3DVERTEX(D3DVECTOR(5,5,0),D3DVECTOR(0,0,-1),0,0);

It can then render the triangle fan using the IDirect3DDevice3::DrawPrimitive method. The following code fragment illustrates the use of IDirect3DDevice3::DrawPrimitive for drawing the triangle fan in the preceding example. Remember that all calls to IDirect3DDevice3::DrawPrimitive must occur between IDirect3DDevice3::BeginScene and IDirect3DDevice3::EndScene.

HRESULT hResult;
// This code fragment assumes that lpDirect3DDevice3 is a valid
// pointer to an IDirect3DDevice3 interface.
hResult =
    lpDirect3DDevice3->DrawPrimitive(D3DPT_TRIANGLEFAN,
                                     D3DFVF_VERTEX,
                                     lpVerts,
                                     TOTAL_VERTS,
                                     D3DDP_WAIT);

This illustration depicts the resulting triangle fan.


Render States

This section introduces the concept of render states, contrasting them to texture stage states, and discusses the various render states in detail. Information in this section is organized into the following topics:

  • About Render States
  • Current Texture
  • Antialiasing States
  • Texture Addressing State
  • Texture Wrapping State
  • Texture Borders
  • Texture Perspective State
  • Texture Filtering State
  • Outline and Fill States
  • Shading State
  • Fog State
  • Alpha States
  • Texture Blending State
  • Culling State
  • Depth Buffering State
  • Ramp State
  • Subpixel Correction State
  • Plane Masking State
  • Color Keying State
  • Render Command Batching State
  • Stencil Buffer State

Note that the discussions in the topics listed here present techniques for controlling the rendering states when using the IDirect3DDevice3 interface, which supports the DrawPrimitive methods. When using execute buffers under the IDirect3DDevice interface, the rendering states are controlled using the D3DOP_STATERENDER opcode.


About Render States

Device render states control the behavior of the Direct3D device's rasterization module. By altering the attributes of the rendering state, what type of shading is used, fog attributes, and many other rasterizer operations.

Applications control the other characteristics of the rendering state by invoking the IDirect3DDevice3::SetRenderState method. The D3DRENDERSTATETYPE enumerated type specifies all of the possible rendering states. Your application passes a value from the D3DRENDERSTATETYPE enumeration as the first parameter to the IDirect3DDevice3::SetRenderState method.

Render states also can control the style of texturing and how texture filtering is done. For DirectX 6.0 and later, all texture-related render states are superseded by corresponding features offered by the IDirect3DDevice3::SetTextureStageState method. The superseded render states still work, but are mapped to affect the corresponding state in the first texture stage (stage 0). For best performance, applications should use the features in the SetTextureStageState method if favor of the legacy render states. The following list shows the superseded render states and lists the corresponding states offered in the new texturing model:

D3DRENDERSTATE_TEXTUREADDRESS
Superseded by the D3DTSS_ADDRESS, D3DTSS_ADDRESSU, D3DTSS_ADDRESSV texture stage states for stage 0.
D3DRENDERSTATE_BORDERCOLOR
Superseded by the D3DTSS_BORDERCOLOR texture stage state for stage 0.
D3DRENDERSTATE_TEXTUREMAG
Superseded by the D3DTSS_MAGFILTER texture stage state for stage 0.
D3DRENDERSTATE_TEXTUREMIN
Superseded by the D3DTSS_MINFILTER texture stage state for stage 0. Mipmap minification filtering is superseded by D3DTSS_MIPFILTER.
D3DRENDERSTATE_TEXTUREMAPBLEND
Superseded by the D3DTSS_COLOROP and D3DTSS_ALPHAOP texture stage states for stage 0.


Current Texture

By default, Direct3D does not apply any textures to primitives being rendered. When your application selects a texture as the current texture, it instructs the Direct3D device to apply the texture to all primitives that are rendered from that time until the current texture is changed again. If each primitive in a 3-D scene has its own texture, the texture must be set before each primitive is rendered.

The IDirect3D2 interface required the use of texture handles. With the IDirect3D3 interface, textures are created as individual objects. An application accesses the functionality of textures through the IDirect3DTexture2 interface. For information on obtaining a pointer to an IDirect3DTexture2 interface, see Obtaining a Texture Interface Pointer. Your application can use a texture interface pointer to assign up to eight current textures. For more information, see Assigning the Current Textures.

If your application uses texture handles, it must pass the value D3DRENDERSTATE_TEXTUREHANDLE as the first parameter to IDirect3DDevice3::SetRenderState. The second parameter is the handle to the texture.

Applications can disable texturing by passing NULL as the second parameter to the IDirect3DDevice3::SetRenderState method.


Antialiasing States

Antialiasing is a method of making lines and edges appear smoother on the screen. Direct3D supports two ways to perform antialiasing, called edge antialiasing and full-scene antialiasing. For details about these techniques, see Antialiasing in the Common Techniques and Special Effects section.

By default, Direct3D default doesn't perform antialiasing. The D3DRENDERSTATE_ANTIALIAS render state can be set to one of the members of the D3DANTIALIASMODE to enable full-scene antialiasing. (The default value, D3DANTIALIAS_NONE disables full-scene antialiasing.)

To enable edge-antialiasing (which requires a second rendering pass), set the D3DRENDERSTATE_EDGEANTIALIAS render sate to TRUE. To disable it, set D3DRENDERSTATE_EDGEANTIALIAS to FALSE.


Texture Addressing State

The U and V texture addressing states, set through the D3DRENDERSTATE_TEXTUREADDRESS, D3DRENDERSTATE_TEXTUREADDRESSU, and D3DRENDERSTATE_TEXTUREADDRESSV render states, have been superseded by the texture addressing features offered by the IDirect3DDevice3 interface. However, applications that use the IDirect3DDevice2 interface can still work with texture addressing modes as before.

Both approaches to texture addressing modes are discussed in Setting and Retrieving Texture Addressing Modes.


Texture Wrapping State

The U and V wrapping render states D3DRENDERSTATE_WRAPU and D3DRENDERSTATE_WRAPV have been superseded by the D3DRENDERSTATE_WRAP0 through D3DRENDERSTATE_WRAP7 renderstates.

These new render states enable and disable U and V wrapping for various textures in the device's multitexture cascade. Set these render states to a combination of the D3DWRAP_U and D3DWRAP_V flags to enable wrapping in the corresponding direction, or omit use a value of zero to disable wrapping. Texture wrapping is disabled in all directions for all texture stages by default. For a conceptual overview, see Texture Wrapping.

Note Although D3DRENDERSTATE_WRAPU and D3DRENDERSTATE_WRAPV are superseded, the IDirect3DDevice3 interface still recognizes them. These older render states, when passed to the IDirect3DDevice3::SetRenderState affect U and V texture wrapping for the first texture stage (stage 0).


Texture Borders

The texture border color state has been superseded by the D3DTSS_BORDERCOLOR texture stage state supported by the IDirect3DDevice3::SetTextureStageState method. If your application uses IDirect3DDevice3 interface, you should use SetTextureStageState to change the border color for each texture stage.

Applications that still use the legacy IDirect3DDevice2 interface can work with texture border colors as before. In this case, set or retrieve the texture border color textures by passing the D3DRENDERSTATE_BORDERCOLOR enumerated value as the first parameter to IDirect3DDevice2::SetRenderState. The second parameter is the RGBA border color.

For more information, see About the Border Color Texture Address Mode.


Texture Perspective State

Applications can apply perspective correction to textures to make them fit properly onto primitives that diminish in size as they get farther away from the viewer. See D3DRENDERSTATE_TEXTUREPERSPECTIVE.

The following code fragment illustrates the process of enabling texture perspective correction:

// This code fragment assumes that lpD3DDevice3 is a valid pointer to
// a Direct3DDevice3.

// Enable texture perspective.
lpD3DDevice3->SetRenderState(D3DRENDERSTATE_TEXTUREPERSPECTIVE,
                             TRUE);

For the IDirect3DDevice3 interface, the default value is TRUE to enable perspective correct texture mapping. For earlier interfaces, the default is FALSE. Note that many 3-D adapters apply texture perspective correction unconditionally. Perspective correction must be enabled to use w-based fog, and w-buffers. For more information, see Eye-relative vs. Z-Based Depth in the Fog section, and Enabling Depth Buffering in the Depth Buffers section.


Texture Filtering State

How your application sets texture filtering states depends largely on which version of the Direct3D device interface it uses. If your application uses the IDirect3DDevice3 interface, the render states discussed here are effectively superseded by the texture filtering options offered by the IDirect3DDevice3::SetTextureStageState method. For a conceptual overview and more information on using SetTextureStageState for texture filtering, see Texture Filtering.

Note Although the render states discussed here are superseded by texture stage states, the IDirect3DDevice3::SetRenderState (as opposed to the IDirect3DDevice2 version) does not fail if you attempt to use them. Rather, the system maps the effects of these render states to the first stage in the multi-texture cascade, stage 0. Applications should not mix the legacy render states with their corresponding texture stage states, as unpredictable results can occur.

If your application is using the legacy IDirect3DDevice2 interface, you set texture filtering states through the IDirect3DDevice2::SetRenderState method. Direct3D supports nearest point sampling, bilinear filtering, anisotropic texture filtering, and mipmap filtering. The filtering method is selected using the D3DTEXTUREFILTER enumerated type.

When an application magnifies a texture, it can use Direct3D devices to select a texture filtering method by passing the D3DRENDERSTATE_TEXTUREMAG enumerated value as the first parameter to the IDirect3DDevice2::SetRenderState method. It must pass one of the enumerated values in the D3DTEXTUREFILTER enumerated type as the second parameter. To select the filtering method used when the texture is being made smaller, set the first parameter of the IDirect3DDevice2::SetRenderState method to D3DRENDERSTATE_TEXTUREMIN. Set the second parameter to one of the enumerated values in the D3DTEXTUREFILTER enumerated type. When applications use software-emulated devices, they should use the same filtering methods for both D3DRENDERSTATE_TEXTUREMAG and D3DRENDERSTATE_TEXTUREMIN. Performance degradation will occur if they are not the same. Direct3D hardware devices (HAL and MMX) do not have this performance limitation.

Anisotropic filtering is disabled when the D3DRENDERSTATE_TEXTUREMAG state is set to D3DFILTER_NEAREST. Anisotropic filtering is only enabled when the D3DRENDERSTATE_TEXTUREMAG state is set to D3DFILTER_LINEAR. For the filter controlled by the D3DRENDERSTATE_TEXTUREMIN enumerated value, anisotropy is enabled when its state is set to D3DFILTER_LINEAR, D3DFILTER_MIPLINEAR, or D3DFILTER_LINEARMIPLINEAR.

Applications that use anisotropic texture filtering should set the degree of filtering to a value that is appropriate for their use. Anisotropic filtering is disabled when it is set to 1, and enabled by setting it to a value greater than 1. See Anisotropic Texture Filtering. and D3DRENDERSTATE_ANISOTROPY.

When using mipmap filtering, your application can select either mipmap near-point sampling or linear mipmap filtering. Mipmap near-point sampling selects the mipmap texture that most closely approximates the resolution of the final output texture, then uses nearest point sampling to obtain the color information. Linear mipmap filtering selects a color from the two closest mipmaps, then linearly interpolates color data between them. See Texture Filtering With Mipmaps and D3DTEXTUREFILTER.

Applications can perform special filtering effects by controlling the mipmap level of detail (LOD) bias. A positive bias on a mipmap texture results in a sharper, but more aliased image. A negative bias causes a texture image to appear blurred. See D3DRENDERSTATE_MIPMAPLODBIAS.


Outline and Fill States

Primitives that have no textures are rendered with the color specified by their material, or with the colors specified for the vertices, if any. The method used to fill them can be selected with the D3DFILLMODE enumerated type. See D3DRENDERSTATE_FILLMODE.

Direct3D uses the standard Windows ROP2 binary raster operations when it fills a primitive. The default value is R2_COPYPEN, which sets the pixel to the current pen color. For details, see GetROP2 and SetROP2 in the Platform SDK documentation. Although most applications will not need to change the default value, your application can change the raster fill operation by using the D3DRENDERSTATE_ROP2 enumerated value.

If you want your applications to enable dithering, it must pass the D3DRENDERSTATE_DITHERENABLE enumerated value as the first parameter to IDirect3DDevice3::SetRenderState. It must set the second parameter to TRUE to enable dithering, and FALSE to disable it.

A stippled fill pattern can be used if stippling is enabled. See D3DRENDERSTATE_STIPPLEENABLE. A 32x32 stipple pattern is specified using the enumerated values D3DRENDERSTATE_STIPPLEPATTERN00 through D3DRENDERSTATE_STIPPLEPATTERN31. Each of these enumerated values corresponds to one line of the stipple pattern. For example, to set the first line of the stipple pattern, pass D3DRENDERSTATE_STIPPLEPATTERN00 as the first parameter to IDirect3DDevice3::SetRenderState. Pass the hexadecimal value of the stipple pattern as the second parameter.

At times, drawing the last pixel in a line can cause unsightly overlap with surrounding primitives. This can be controlled using the D3DRENDERSTATE_LASTPIXEL enumerated value. However, this setting should not be altered without some forethought. Under some conditions, suppressing the rendering of the last pixel can cause unsightly gaps between primitives.

By default, Direct3D devices use a solid outline for primitives. The outline pattern can be changed using the D3DLINEPATTERN structure. See D3DRENDERSTATE_LINEPATTERN.


Shading State

Direct3D supports both flat and Gouraud shading. The default is Gouraud shading. To control the current shade mode, your application uses the D3DSHADEMODE enumerated type. See D3DRENDERSTATE_SHADEMODE.

The following code fragment demonstrates the process of setting the shading state to flat shading mode:

// This code fragment assumes that lpD3DDevice3 is a valid pointer to
// a Direct3DDevice3.

// Set the shading state.
lpD3DDevice3->SetRenderState(D3DRENDERSTATE_SHADEMODE,
                             D3DSHADE_FLAT);


Fog State

Fog effects can give a 3-D scene greater realism. Fog effects can be used for more than simulating fog. They can also be used to decrease the clarity of a scene with distance. This mirrors what happens in the real world. As objects get more distant from the viewer, their detail becomes less distinct. For more information about using fog in your application, see Fog.

The current Direct3D device enables and disables fog blending, controls fog color, and manipulates some fog parameters. You can enable fog by setting the D3DRENDERSTATE_FOGENABLE render state to TRUE. The fog color can be set to any D3DCOLOR value (the alpha component of the fog color is ignored). See D3DRENDERSTATE_FOGCOLOR.

For general information about using fog, see Fog, in the Common Techniques and Special Effects section.


Alpha States

The alpha value of a color controls its transparency. Enabling alpha blending allows colors, materials, and textures on a surface to be blended with transparency onto another surface. For more information, see Alpha Texture Blending and Multipass Texture Blending.

Alpha blending render states

Applications must use the D3DRENDERSTATE_ALPHABLENDENABLE enumerated value to enable alpha transparency blending. The Direct3D API allows many types of alpha blending. However, it is important to note the user's 3-D hardware may not support all of the blending states allowed by Direct3D.

The type of alpha blending that is done depends on the D3DRENDERSTATE_SRCBLEND and D3DRENDERSTATE_DESTBLEND render states. Source and destination blend states are used in pairs. The following code fragment demonstrates how the source blend state is set to D3DBLEND_SRCCOLOR and the destination blend state is set to D3DBLEND_INVSRCCOLOR.

// This code fragment assumes that lpD3DDevice3 is a valid pointer to
// an IDirect3DDevice3 interface.

// Set the source blend state.
lpD3DDevice3->SetRenderState(D3DRENDERSTATE_SRCBLEND,
                             D3DBLEND_SRCCOLOR);

// Set the destination blend state.
lpD3DDevice3->SetRenderState(D3DRENDERSTATE_DESTBLEND,
                             D3DBLEND_INVSRCCOLOR);

As a result of the calls in the preceding code fragment, Direct3D performs a linear blend between the source color (the color of the primitive being rendered at the current location) and the destination color (the color at the current location in the frame buffer). This gives an appearance similar to tinted glass. Some of the color of the destination object seems to be transmitted through the source object. The rest of it appears to be absorbed.

Altering the source and destination blend states can give the appearance of emissive objects in a foggy or dusty atmosphere. For instance, if your application models flames, force fields, plasma beams, or similarly radiant objects in a foggy environment, set the source and destination blend states to D3DBLEND_ONE.

Another application of alpha blending is controlling the lighting in a 3-D scene, also called light mapping. Setting the source blend state to D3DBLEND_ZERO and the destination blend state to D3DBLEND_SRCALPHA darkens a scene according to the source alpha information. The source primitive is used as a light map that scales the contents of the frame buffer to darken it when appropriate. This produces monochrome light mapping.

Color light mapping can be achieved by setting the source alpha blending state to D3DBLEND_ZERO and the destination blend state to D3DBLEND_SRCCOLOR.

Direct3D devices provide alpha value stippling if it is supported by the display hardware. See D3DRENDERSTATE_STIPPLEDALPHA. If your application creates an RGB or ramp software emulation device, Direct3D ignores this enumerated value.

Alpha-testing render states

Applications can use alpha testing to control when pixels are written to the render target surface. By using the D3DRENDERSTATE_ALPHATESTENABLE enumerated value, your application sets the current Direct3D device so that it tests each pixel according to an alpha test function. If the test succeeds, the pixel is written to the surface. If it doesn't, Direct3D ignores it. Select the alpha test function with the D3DRENDERSTATE_ALPHAFUNC enumerated value. Your application can set a reference alpha value for all pixels to be compared against by using the D3DRENDERSTATE_ALPHAREF render state.

The most common use for alpha testing is to improve performance when rasterizing objects that are nearly transparent. If the color data being rasterized is more opaque than the color already at a given pixel (D3DPCMPCAPS_GREATEREQUAL) then the pixel is written, otherwise the rasterizer ignores the pixel altogether, saving the processing required to blend the two colors. The following example checks to see if a given comparison function is supported and, if so, it sets the comparison function parameters required to improve performance during rendering.

// This example assumes that pd3dDeviceDesc is a
// D3DDEVICEDESC structure that was filled with a
// previous call to IDirect3DDevice3::GetCaps.
if (pd3dDeviceDesc->dpcTriCaps.dwAlphaCmpCaps & D3DPCMPCAPS_GREATEREQUAL)
{
    dev->SetRenderState( D3DRENDERSTATE_ALPHAREF, (DWORD)0x00000001);
    dev->SetRenderState( D3dRENDERSTATE_ALPHATESTENABLE, TRUE );
    dev->SetRenderState( D3DRS_ALPHACMP, D3DCMP_GREATEREQUAL );
}

// If the comparison isn't supported, render anyway.
// The only drawback is no performance gain.

Not all hardware supports all alpha testing features. You can check the device capabilities by calling the IDirect3DDevice3::GetCaps method. After retrieving the device capabilities, check the dwAlphaCmpCaps member of the D3DPRIMCAPS structure (contained by the associated D3DDEVICEDESC structure) for the desired comparison function. If the dwAlphaCmpCaps member contains only the D3DPCMPCAPS_ALWAYS capability or only the D3DPCMPCAPS_NEVER capability, the driver does not support alpha tests at all.


Texture Blending State

Your application can control the mode that is used to blend textures onto the surfaces of primitives. Applications that use texture handles set the texture blending state by invoking the IDirect3DDevice3::SetRenderState method and passing the enumerated value D3DRENDERSTATE_TEXTUREMAPBLEND as the first parameter. Pass a value from the D3DTEXTUREBLEND enumerated type as the second parameter.

Applications that use texture interface pointers set the texture blending state in the blending stages associated with the set of current textures. For more information, see Multiple Texture Blending.


Culling State

As Direct3D renders primitives, it culls those primitives that are facing away from the viewer. The culling mode of HAL and MMX devices can be set using the D3DCULL enumerated type. See D3DRENDERSTATE_CULLMODE. By default, Direct3D culls back faces with counterclockwise vertices.

The following code sample illustrates the processor setting the culling mode to cull back faces with clockwise vertices.

// This code fragment assumes that lpD3DDevice3 is a valid pointer to
// an IDirect3DDevice3 interface.

// Set the culling state.
lpD3DDevice3->SetRenderState(D3DRENDERSTATE_CULLMODE,
                             D3DCULL_CW);


Depth Buffering State

Depth buffering is a method of removing hidden lines and surfaces. For a conceptual overview, see What are Depth Buffers?. By default, Direct3D does not use depth buffering. You can update the depth buffering state with the D3DRENDERSTATE_ZENABLE render state, using one of the members of the D3DZBUFFERTYPE enumeration to specify the new state value.

If, for some reason, your application needs to prevent Direct3D from writing to the depth buffer, it can use the D3DRENDERSTATE_ZWRITEENABLE enumerated value, specifying FALSE as the second parameter for the call to IDirect3DDevice3::SetRenderState.

The following code fragment shows how the depth buffer state is set to enable z-buffering:

// This code fragment assumes that lpD3DDevice3 is a valid pointer to
// a Direct3DDevice3.

// Enable z-buffering.
lpD3DDevice3->SetRenderState(D3DRENDERSTATE_ZENABLE,
                             D3DZB_TRUE); // D3DZB_TRUE is the same as TRUE

Your application can also use the members of the D3DCMPFUNC enumerated type to select the comparison function that Direct3D uses when performing depth buffering. See D3DRENDERSTATE_ZFUNC.

Z-biasing is a method of displaying one surface in front of another even if their depth values are the same. You can use this technique for a variety of effects. A common example is rendering shadows on walls. Both the shadow and the wall have the same depth value. However, you want your application to show the shadow on the wall. Giving a z-bias to the shadow makes Direct3D display them properly (see D3DRENDERSTATE_ZBIAS).


Ramp State

The D3DRENDERSTATE_MONOENABLE render state is not currently used. Ramp lighting is automatically enabled when an application uses a ramp device. For more information, see Ramp Device.


Subpixel Correction State

The D3DRENDERSTATE_SUBPIXEL render state is not used, and the system ignores it.


Plane Masking State

Special effects can be achieved by using bit masks on the color channels. For instance, a scene with a strong, flashing red light can be simulated by selectively masking the blue and green channels so that they are darker, and the red channel so that it is brighter. Your program can turn the effect on and off alternately for intervals to simulate flashing.

To set the plane mask, call the IDirect3DDevice3::SetRenderState method with the first parameter set to D3DRENDERSTATE_PLANEMASK and the second set to the desired plane mask.

Note The D3DRENDERSTATE_PLANEMASK render state is not supported by the software rasterizers, and is often ignored by hardware drivers. To disable writes to the color buffer by using alpha blending, set D3DRENDERSTATE_SRCBLEND to D3DBLEND_ZERO and D3DRENDERSTATE_DESTBLEND to D3DBLEND_ONE.


Color Keying State

Setting a color key instructs Direct3D to treat the key color as transparent. When Direct3D applies a texture that was created with the DDSD_CKSRCBLT flag to a primitive, all texels that match the key color are not rendered on the primitive. Note that any textures that were not created with the DDSD_CKSRCBLT flag will not display color-key effects, even if they contain the color key.

Set color keys with the IDirectDrawSurface4::SetColorKey method for the surface that will be using the color key (in this case, the render target surface). However, color keying can be toggled on and off by calling the IDirect3DDevice3::SetRenderState method. Set the first parameter to D3DRENDERSTATE_COLORKEYENABLE. Your application should set the second parameter to TRUE to enable color keying and FALSE to disable it. The default is FALSE.

// This code fragment assumes that lpD3DDevice3 is a valid pointer to
// a Direct3DDevice3.

// Disable color keying.
lpD3DDevice3->SetRenderState(D3DRENDERSTATE_COLORKEYENABLE,
                             FALSE);


Render Command Batching State

By default, calls to IDirect3DDevice2::DrawPrimitive and IDirect3DDevice2::DrawIndexedPrimitive within a scene are batched. That is, they are buffered together and passed to the Direct3D device driver in one call. Changes in rendering states within the scene are also buffered. The buffer contents are passed to the device driver when the buffer is full or when the IDirect3DDevice2::EndScene method is invoked. This technique improves performance.

However, if an application makes change to the scene that are not changes to the rendering state, they may occur out of order with relation to the source code. For instance, if the contents of a texture are altered between calls to IDirect3DDevice2::DrawPrimitive or IDirect3DDevice2::DrawIndexedPrimitive, both primitives may be drawn with the new texture contents. Your application can resolve this problem by flushing the batching buffer before it makes scene changes that are not alterations of the rendering state.

An application flushes the batching buffer by calling IDirect3DDevice2::SetRenderState and passing the enumerated value D3DRENDERSTATE_FLUSHBATCH as the first parameter. The second parameter should be zero.

Note This render state is only useful to applications that render with texture handles (using the IDirect3DDevice2 interface). Batched primitives are implicitly flushed when rendering with the IDirect3DDevice3 interface, as well as when rendering with execute buffers.


Stencil Buffer State

Applications use the stencil buffer to determine whether or not a pixel is written to the rendering target surface. For details, see Stencil Buffers.

Enable or disable stenciling by calling the IDirect3DDevice3::SetRenderState method. Pass D3DRENDERSTATE_STENCILENABLE as the value of the first parameter. Set the value of the second parameter to TRUE or FALSE to enable or disable it respectively.

Set the comparison function that Direct3D uses to perform the stencil test by invoking the IDirect3DDevice3::SetRenderState method. Set the value of the first parameter to D3DRENDERSTATE_STENCILFUNC. Pass a member of the D3DCMPFUNC enumerated type as the value of the second parameter.

The stencil reference value is the value in the stencil buffer that the stencil function uses for its test. By default, the stencil reference value is zero. Your application can set it by calling the IDirect3DDevice3::SetRenderState method. Pass D3DRENDERSTATE_STENCILREF as the value of the first parameter. Set the value of the second parameter to the new reference value.

Before Direct3D module performs the stencil test for any pixel, it does a bitwise AND of the stencil reference value and a stencil mask value. The result is then compared against the contents of the stencil buffer using the stencil comparison function. Your application can set the stencil mask. Use the IDirect3DDevice3::SetRenderState method, and pass D3DRENDERSTATE_STENCILMASK as the value of the first parameter. Set the value of the second parameter to the new stencil mask.

To set the action that Direct3D takes when the stencil test fails, invoke the IDirect3DDevice3::SetRenderState method and pass D3DRENDERSTATE_STENCILFAIL as the first parameter. The second parameter must be a member of the D3DSTENCILOP enumerated type.

Your application can also control how Direct3D responds when the stencil test passes but the z-buffer test fails. Call the IDirect3DDevice3::SetRenderState method and pass D3DRENDERSTATE_STENCILZFAIL as the first parameter and use a member of the D3DSTENCILOP enumerated type for the second parameter.

In addition, your program can control what Direct3D does when both the stencil test and the z-buffer test pass. Use the IDirect3DDevice3::SetRenderState method and pass D3DRENDERSTATE_STENCILPASS as the first parameter. Again, the second parameter must be a member of the D3DSTENCILOP enumerated type.


Lighting States

In addition to the states discussed in Render States, Direct3D devices also control lighting states. When lighting states need to be changed, they are changed through the device interface. Therefore, your application can apply a particular rendering or lighting state to either a single primitive or a group of primitives.

The characteristics of the device lighting state are controlled by the IDirect3DDevice3::SetLightState method. All of the possible lighting states are specified by the D3DLIGHTSTATETYPE enumerated type, a member of which is passed as the first parameter to IDirect3DDevice3::SetLightState. The attributes of the lighting state are:

  • Vertex Color Lighting
  • Ambient Lighting
  • Ramp Mode Lighting
  • Vertex Fog Parameter States
  • Material State


Vertex Color Lighting

Vertices of type D3DVERTEX, D3DLVERTEX, and D3DTLVERTEX cannot contain both color and normal information. Because the default shading mode is Gouraud shading, which depends on both vertex color and normal information, Direct3D did not use vertex color in the lighting calculations.

With the introduction of the flexible vertex format, vertices may contain both vertex color and vertex normal information. By default, Direct3D uses this information when it calculates lighting. If you want your application to disable the use of vertex color lighting information, invoke the IDirect3DDevice3::SetLightState method and pass D3DLIGHTSTATE_COLORVERTEX as the first parameter. Set the second parameter to FALSE to disable vertex color lighting, or TRUE to enable it.

If D3DLIGHTSTATE_COLORVERTEX is set to TRUE and a diffuse vertex color is present, the output alpha is equal to the diffuse alpha for the vertex. Otherwise, output alpha is equal to the alpha component of diffuse material, clamped to the range [0, 255].


Ambient Lighting

Ambient light is the surrounding light that comes from all directions. Your application sets the color of the ambient lighting by invoking the IDirect3DDevice3::SetLightState method and passing the enumerated value D3DLIGHTSTATE_AMBIENT as the first parameter. The second parameter is a color in RGBA format. The default is zero.

// This code fragment assumes that lpD3DDevice3 is a valid pointer to
// a Direct3DDevice3.

// Set the ambient light.
D3DCOLOR d3dclrAmbientLightColor = D3DRGBA(1.0f,1.0f,1.0f,1.0f);
lpD3DDevice3->SetLightState(D3DLIGHTSTATE_AMBIENT,
                            d3dclrAmbientLightColor);

Ambient light levels should not be confused with direct light. For more information, see Direct Light vs. Ambient Light.


Ramp Mode Lighting

The D3DLIGHTSTATE_COLORMODEL light state is not used. Your application implicitly chooses the color model it uses when it creates a rendering device.


Vertex Fog Parameter States

Because vertex fog is applied during lighting, you control several vertex fog parameters through the lighting interface. For general information about using vertex fog, see Vertex Fog, in the Common Techniques and Special Effects section.

The D3DLIGHTSTATE_FOGMODE, D3DLIGHTSTATE_FOGSTART, D3DLIGHTSTATE_FOGEND, and D3DLIGHTSTATE_FOGDENSITY lighting states control vertex fog parameters.


Material State

The D3DLIGHTSTATE_MATERIAL lighting state controls the current rendering material. By default, no material is selected. You can set a new rendering material by calling the IDirect3DDevice3::SetLightState method, passing D3DLIGHTSTATE_MATERIAL in the first parameter and the material handle for the material to be used as the second parameter. To deselect materials, set the second parameter to NULL. When no material is selected, the Direct3D lighting engine is disabled.

For more information, see Materials.


Emulation Modes

Direct3D furnishes three devices that emulate 3-D hardware in software, MMX, RGB, and ramp devices. For details, see MMX Device, RGB Device and Ramp Device. Because these devices perform software emulation, they render more slowly than 3-D hardware. However, if the user's computer has no 3-D hardware support, these software-emulated modes may be sufficient for your application.

MMX and RGB modes provides the full range of capabilities offered by the Direct3D transformation and lighting modules. In these modes, your application can use 8-, 16-, 24-, or 32-bit textures.

Ramp mode utilizes the full range of the transformation module but does not support colored lighting. A ramp mode device uses the Direct3D lighting module for monochrome gray-scale lighting only. Therefore, lights in ramp mode have intensity but no color. The gray-scale value is stored in the blue component of the light color.

Colored materials and textures can be used in ramp mode. Direct3D uses the material or texture color as its base color. If white light (full intensity light) is shining on the material or texture, the base color is used. However, if the light strength is less than full intensity, Direct3D mixes gray or black into the color of the material or texture. If your application uses textures in ramp mode, it must set the D3DLIGHTSTATE_MATERIAL member of the D3DLIGHTSTATETYPE enumerated type. Only 8-bit textures can be used in ramp mode. For details, see Materials and Ramp Mode Lighting.

To control the number of color values available for a material or texture in ramp mode, your application must set the dwRampSize member of the D3DMATERIAL structure when it creates its materials. Direct3D uses the material and texture color as the base color. The value in the dwRampSize member determines how many gradients of the base color are available, depending on the brightness of the light. Direct3D creates a color palette with the number of entries (1-based) specified in the dwRampSize member. Since the maximum possible number of palette entries is less than 256 (256 minus the reserved colors that Windows uses), your application should specify the minimum number of gray-scale values required for the application.

For best results, make the ramp size for most or all of your application's materials the same value. When Direct3D runs out of palette entries, it searches through the existing materials to find the closest color match. Only materials with the same ramp size can be considered a match.


AGP Surfaces and Direct3D Devices

Using textures in 3-D applications can greatly enhance the appearance of realism in 3-D images. Memory for storing textures never seems as abundant as developers would like. DirectDraw and Direct3D support the Accelerated Graphics Port (AGP) architecture. The AGP architecture gives computers the ability to create DirectDraw surfaces in applications' memory spaces. This significantly extends the amount of memory available for storing textures.

Only the Direct3D HAL device supports the use of the AGP architecture. For more information on the use of the AGP architecture, see Using Non-local Video Memory Surfaces.


Execute Buffers

This section provides an introduction to execute buffers. The following topics are discussed:

  • About Execute Buffers
  • Using Execute Buffers
  • Direct3D Execute-Buffer Tutorial


About Execute Buffers

In the past, all programming with Direct3D Immediate Mode was done using execute buffers. Now that the DrawPrimitive methods have been introduced, however, most new Immediate Mode programs will not use execute buffers or the IDirect3DExecuteBuffer interface. For more information about the DrawPrimitive methods, see The DrawPrimitive Methods.

Execute buffers are similar to the display lists you may be familiar with if you have experience with OpenGL programming. Execute buffers contain a vertex list followed by an instruction stream. The instruction stream consists of operation codes, or opcodes, and the data that modifies those opcodes. Each execute buffer is bound to a single Direct3D device.

You can create an IDirect3DExecuteBuffer interface by calling the IDirect3DDevice::CreateExecuteBuffer method.

lpD3DDevice->CreateExecuteBuffer(
    lpDesc,       // Address of a DIRECT3DEXECUTEBUFFERDESC structure
    lplpDirect3DExecuteBuffer,  // Address to contain a pointer to the
                                // Direct3DExecuteBuffer object
    pUnkOuter);   // NULL

Execute-buffers reside on a device list. You can use the IDirect3DDevice::CreateExecuteBuffer method to allocate space for the actual buffer, which may be on the hardware device.

The buffer is filled with two contiguous arrays of vertices and opcodes by using the following calls to the IDirect3DExecuteBuffer::Lock, IDirect3DExecuteBuffer::Unlock, and IDirect3DExecuteBuffer::SetExecuteData methods:

lpD3DExBuf->Lock(
    lpDesc);.      // Address of a DIRECT3DEXECUTEBUFFERDESC structure
//  .
//  .  Store contents through the supplied address
//  .
lpD3DExBuf->Unlock();
lpD3DExBuf->SetExecuteData(
    lpData);       // Address of a D3DEXECUTEDATA structure

The last call in the preceding example is to the IDirect3DExecuteBuffer::SetExecuteData method. This method notifies Direct3D where the two parts of the buffer reside relative to the address that was returned by the call to the IDirect3DExecuteBuffer::Lock method.

You can use the IDirect3DExecuteBuffer interface to get and set execute data, and to lock, unlock, optimize, and validate the execute buffer.


Using Execute Buffers

As was pointed out earlier, there are two ways to use Immediate Mode: you can use the DrawPrimitive methods or you can work with execute buffers (display lists). Most developers who have never worked with Immediate Mode before will use the DrawPrimitive methods. Developers who already have an investment in code that uses execute buffers will probably continue to work with them. For more information about the DrawPrimitive methods, see The DrawPrimitive Methods.

Execute buffers are complex to understand and fill and are difficult to debug. On the other hand, they allow you to maximize performance. Since communicating with the driver is slow, it makes sense to perform the communication in batches—that is, by using execute buffers.

This section of the documentation describes the contents of execute buffers and how to use them.

  • Execute-Buffer Architecture
  • Execute-Buffer Contents
  • Creating an Execute Buffer
  • Locking the Execute Buffer
  • Filling the Execute Buffer
  • Unlocking the Execute Buffer
  • Executing the Execute Buffer
  • States and State Overrides


Execute-Buffer Architecture

Execute buffers are processed first by the transformation module. This module runs through the vertex list, generating transformed vertices by using the state information set up for the transformation module. Clipping can be enabled, generating additional clipping information by using the viewport parameters to clip against. The whole buffer can be rejected here if none of the vertices is visible. Then the vertices are processed by the lighting module, which adds color to them according to the lighting instructions in the execute buffer. Finally, the rasterization module parses the instruction stream, rendering primitives by using the generated vertex information.

When an application calls the IDirect3DDevice::Execute method, the system determines whether the vertex list needs to be transformed or transformed and lit. After these operations have been completed, the instruction list is parsed and rendered.

There are really two execute buffers: one for the application and one for the driver. The application data buffer is filled in by the application. It holds geometry (such as vertices and triangles) and state information (the transformation, lighting, and rasterization state) This information persists until the application explicitly changes it. The driver data buffer, on the other hand, holds the output of the transformation and lighting modules (that is, it holds transformed and lit geometry) and hands the data off to the rasterization module. There is only one of these "TL buffers" per driver. The following diagram shows the relationship of these data buffers:

You can disable the lighting module or both the lighting and transformation when you are working with execute buffers. This changes the way the vertex list is interpreted, allowing the user to supply pretransformed or prelit vertices only for the rasterization phase of the rendering pipeline. Note that only one vertex type can be used in each execute buffer. For more information about vertex types, see Vertex Formats.

In addition to execute buffers and state changes, Direct3D accepts a third calling mechanism. Either of the transformation or lighting modules can be called directly. This functionality is useful when rasterization is not required, such as when using the transformation module for bounding-box tests.


Execute-Buffer Contents

Execute buffers contain a list of vertices followed by stream of instructions about how to use those vertices. (All of these are DWORD-aligned.) This section contains information about working with vertices and instructions in an execute buffer. The following topics are discussed.

  • Execute Buffer Format
  • Execute Buffer Vertices
  • Execute Buffer Instructions


Execute Buffer Format

The following illustration shows the format of execute buffers. Note that all data in an execute buffer must be DWORD-aligned.

The instruction stream consists of operation codes, or opcodes, and the data that is operated on by those opcodes. The opcodes define how the vertex list should be lit and rendered. Direct3D opcodes are listed in the D3DOPCODE enumerated type. The D3DINSTRUCTION structure describes instructions in an execute buffer; it contains an opcode, the size of each instruction data unit, and a count of the relevant data units that follow.

One of the most common instructions is a triangle list (D3DOP_TRIANGLE), which is simply a list of triangle primitives that reference vertices in the vertex list. Because all the primitives in the instruction stream reference vertices in the vertex list only, it is easy for the transformation module to reject a whole buffer of primitives if its vertices are outside the viewing frustum.


Execute Buffer Vertices

Each execute buffer contains a vertex list followed by an instruction stream. The instruction stream defines how the vertex list should be rendered; it is based on indices into the vertex list.

Although you can choose to use transformed and lit vertices (D3DTLVERTEX), vertices that have only been lit (D3DLVERTEX), or vertices that have been neither transformed nor lit (D3DVERTEX), you can have only one of each type of vertex in a single Direct3DExecuteBuffer object. Some execute buffers are used only to change the state of one or more of the modules in the graphics pipeline; these execute buffers do not have vertices.

For more information about the handling of vertices in execute buffers, see Vertex Formats.


Execute Buffer Instructions

The vertex data in an execute buffer is followed by an instruction stream. Each instruction is represented by:

  • An instruction header
  • Opcode
  • Byte size
  • Number of times this opcode is to be repeated
  • Byte offset to first instruction

Execute buffer instructions are commands to the driver. Each instruction is identified by an operation code (opcode). All execute data is prefixed by an instruction header. Data accompanies each iteration of each opcode. Each opcode can have multiple arguments, including multiple triangles or multiple state changes. There are only a few main instruction types, as discussed in the following paragraphs:

Drawing Instructions

The most important of the drawing instructions defines a triangle. In a triangle, vertices are zero-based indices into the vertex list that begins the execute buffer. For more information about triangles, see Triangles.

Other important drawing instructions include line-drawing instructions (D3DLINE) and line-drawing instructions (D3DPOINT).

State-change Instructions

The system stores the state of each of the modules in the graphics pipeline until the state is overridden by an instruction in an execute buffer.

Transformation state | World, view and projection matrices
Light state | Surface material, fog, ambient lighting
Render state | Texture, antialiasing, z-buffering, and so on

Flow-control Instructions

The flow-control instructions allow you to branch on an instruction or to jump to a new position in the execute buffer, skipping or repeating instructions as necessary. This means that you can use the flow-control instructions as a kind of programming language.

The last flow-control instruction in an execute buffer must be D3DOP_EXIT.

Other Instructions

Some other execute-buffer instructions do not fall neatly into the other categories. These include:

Texturing | Download a texture to the device
Matrices | Download or multiply a matrix
Span, SetState | Advanced control for primitives and rendering states.


Creating an Execute Buffer

The tricky thing about creating an execute buffer is figuring out how much memory to allocate for it. There are two basic strategies for determining the correct size:

  • Add the sizes of the vertices, opcodes, and data you will be putting into the buffer.
  • Allocate a buffer of an arbitrary size and fill it from both ends, putting the vertices at the beginning and the opcodes at the end. When the buffer is nearly full, execute it and allocate another.

The hardware determines the size of the execute buffer. You can retrieve this size by calling the IDirect3DDevice2::GetCaps method and examining the dwMaxBufferSize member of the D3DDEVICEDESC structure. Typically, 64 KB is a good size for execute buffers when you are using a software driver, because this size makes the best use of the secondary cache. When your application can take advantage of hardware acceleration, however, it should use smaller execute buffers to take advantage of the primary cache.

After filling in D3DEXECUTEBUFFERDESC structure describing your execute buffer, you can call the IDirect3DDevice::CreateExecuteBuffer to create it.

For an example of calculating the size of the execute buffer and creating it, see Creating the Scene, in the Direct3D Execute-Buffer Tutorial.


Locking the Execute Buffer

You must lock execute buffers before you can modify them. This action prevents the driver from modifying the buffer while you are working with it.

To lock a buffer, call the IDirect3DExecuteBuffer::Lock method. This method takes a single parameter; a pointer to a D3DEXECUTEBUFFERDESC structure which, on return, specifies the actual location of the execute buffer's memory.

When working with execute buffers you need to manage three pointers: the execute buffer's start address (retrieved by IDirect3DExecuteBuffer::Lock), the instruction start address, and your current position in the buffer. You use these three pointers to compute vertex offsets, instruction offsets, and the overall size of the execute buffer. After you have finished filling the execute buffer, you use these pointers to describe the buffer to the driver; for more information, see Unlocking the Execute Buffer.


Filling the Execute Buffer

After you have finished filling your execute buffer, it contains the vertices describing your model and a series of instructions about how the vertices should be interpreted. The following sections describe filling an execute buffer:

  • Selecting the Vertex Type
  • Triangles
  • Processing Vertices
  • Finishing the Instructions

You can streamline the task of filling execute buffers by taking advantage of the helper macros that ship with the samples in the DirectX SDK. The D3dmacs.h header file in the Misc directory of the samples contains many useful macros that will simplify your work. In particular, the macros PUTD3DINSTRUCTION and VERTEX_DATA are useful for filling execute buffers.

For an example of filling an execute buffer, see Filling the Execute Buffer, in the Direct3D Execute-Buffer Tutorial.


Selecting the Vertex Type

Applications may use all or part of the Direct3D rendering pipeline. The type of vertex that you use in your program determines how much of the rendering pipeline is used. For details, see Vertex Formats.


Triangles

You use the D3DOP_TRIANGLE opcode to insert a triangle into an execute buffer. In a triangle, vertices are zero-based indices into the vertex list that begins the execute buffer. Triangles are described by the D3DTRIANGLE structure.

Triangles are the only geometry type that can be processed by the rasterization module. The screen coordinates range from (0, 0) for the top left of the device (screen or window) to (width – 1, height – 1) for the bottom right of the device. The depth values range from zero at the front of the viewing frustum to one at the back. Rasterization is performed so that if two triangles that share two vertices are rendered, no pixel along the line joining the shared vertices is rendered twice. The rasterizer culls back facing triangles by determining the winding order of the three vertices of the triangle. Only those triangles whose vertices are traversed in a clockwise orientation are rendered.

You should be sure that your triangle data is aligned on QWORD (8-byte) boundaries. The OP_NOP helper macro in D3dmacs.h can help you with this alignment task. Note that if you use this macro, you must always bracket it with opening and closing braces.


Processing Vertices

After filling in the vertices in your execute buffer, you typically use the D3DOP_PROCESSVERTICES opcode to set the lighting and transformations for the vertices.

The D3DPROCESSVERTICES structure describes how the vertices should be processed. The dwFlags member of this structure specifies the type of vertex you are using in your execute buffer. If you are using D3DTLVERTEX vertices, you should specify D3DPROCESSVERTICES_COPY for dwFlags. For D3DLVERTEX, specify D3DPROCESSVERTICES_TRANSFORM. For D3DVERTEX, specify D3DPROCESSVERTICES_TRANSFORMLIGHT.


Finishing the Instructions

The last opcode in your list of instructions should be D3DOP_EXIT. This opcode simply signals that the system can stop processing the data.


Unlocking the Execute Buffer

When you have finished filling the execute buffer, you must unlock it. This alerts the driver that it can work with the buffer. You can unlock the buffer by calling the IDirect3DExecuteBuffer::Unlock method.

When the execute buffer has been unlocked, call the IDirect3DExecuteBuffer::SetExecuteData method to give the driver some important details about the buffer. This method takes a pointer to a D3DEXECUTEDATA structure. Among the information you provide in this structure are the offsets of the vertices and instructions, which you have been tracking ever since locking the buffer, as described in Locking the Execute Buffer.


Executing the Execute Buffer

Executing an execute buffer is a simple matter of calling the IDirect3DDevice::Execute method with pointers to the execute buffer and to the viewport describing the rendering target. You should always check the return value from this method to verify that it was successful.

The dwFlags parameter of IDirect3DDevice::Execute specifies whether the vertices you supply should be clipped. You should specify D3DEXECUTE_UNCLIPPED if all primitives in the buffer are contained within the viewport and D3DEXECUTE_CLIPPED otherwise.

When you have executed an execute buffer, you can delete it. This is done simply by calling the IDirect3DExecuteBuffer::Release method. You could also use the RELEASE macro in D3dmacs.h, if you prefer.


States and State Overrides

Direct3D interprets the data in execute buffers according to the current state settings. Applications set up these states before instructing the system to render data. The D3DSTATE structure contains three enumerated types that expose this architecture: D3DTRANSFORMSTATETYPE, which sets the state of the transform module; D3DLIGHTSTATETYPE, for the lighting module; and D3DRENDERSTATETYPE, for the rasterization module.

Each state includes a Boolean value that is essentially a read-only flag. If this flag is set to TRUE, no further state changes are allowed.

Applications can override the read-only state of a module by using the D3DSTATE_OVERRIDE macro. This mechanism allows an application to reuse an execute buffer, changing its behavior by changing the system's state. Direct3D Retained Mode uses state overrides to accomplish some tasks that otherwise would require completely rebuilding an execute buffer. For example, the Retained Mode API uses state overrides to replace the material of a mesh with the material of a frame.

An application might use the D3DSTATE_OVERRIDE macro to lock and unlock the Gouraud shade mode, as shown in the following example. (The shade-mode render state is defined by the D3DRENDERSTATE_SHADEMODE member of the D3DRENDERSTATETYPE enumerated type.)

OP_STATE_RENDER(2, lpBuffer);
STATE_DATA(D3DRENDERSTATE_SHADEMODE, D3DSHADE_GOURAUD, lpBuffer);
STATE_DATA(D3DSTATE_OVERRIDE(D3DRENDERSTATE_SHADEMODE), TRUE, lpBuffer);

The OP_STATE_RENDER macro implicitly uses the D3DOP_STATERENDER opcode, one of the members of the D3DOPCODE enumerated type. D3DSHADE_GOURAUD is one of the members of the D3DSHADEMODE enumerated type.

After executing the execute buffer, the application could use the D3DSTATE_OVERRIDE macro again, to allow the shade mode to be changed:

STATE_DATA(D3DSTATE_OVERRIDE(D3DRENDERSTATE_SHADEMODE), FALSE, lpBuffer);

The OP_STATE_RENDER and STATE_DATA macros are defined in the D3dmacs.h header file in the Misc directory of the DirectX SDK sample.


Direct3D Execute-Buffer Tutorial

To create a Direct3D Immediate-Mode application based on execute buffers, you create DirectDraw and Direct3D objects, set render states, fill execute buffers, and execute those buffers.

This section includes a simple Immediate-Mode application that draws a single, rotating, Gouraud-shaded triangle. The triangle is drawn in a window whose size is fixed. For code clarity, we have chosen not to address a number of issues in this sample. For example, full-screen operation, resizing the window, and texture mapping are not included. Furthermore, we have not included some optimizations when their inclusion would have made the code more obscure. Code comments highlight the places in which we did not implement a common optimization.

  • Definitions, Prototypes, and Globals
  • Enumerating Direct3D Devices
  • Creating Objects and Interfaces
  • Creating the Scene
  • Filling the Execute Buffer
  • Animating the Scene
  • Rendering Using an Execute Buffer
  • Working with Matrices
  • Restoring and Redrawing
  • Releasing Objects
  • Error Checking
  • Converting Bit Depths
  • Main Window Procedure
  • WinMain Function


Definitions, Prototypes, and Globals

This section contains the definitions, function prototypes, global variables, constants, and other structural underpinnings for the Imsample.c code sample.

  • Header and Includes
  • Constants in Imsample.c
  • Macros in Imsample.c
  • Global Variables
  • Function Prototypes


Header and Includes
/***********************************************************************
 *
 * File :       imsample.c
 *
 * Author :     Colin D. C. McCartney
 *
 * Date :       1/7/97
 *
 * Version :    V1.1
 *
 **********************************************************************/

/***********************************************************************
 *
 * Include files
 *
 **********************************************************************/

#define  INITGUID
#include <windows.h>
#include <math.h>
#include <assert.h>
#include <ddraw.h>
#include <d3d.h>

#include "resource.h"


Constants in Imsample.c

// Class name for this application's window class.

#define WINDOW_CLASSNAME      "D3DSample1Class"

// Title for the application's window.

#define WINDOW_TITLE          "D3D Sample 1"

// String to be displayed when the application is paused.

#define PAUSED_STRING         "Paused"

// Half height of the view window.

#define HALF_HEIGHT           D3DVAL(0.5)

// Front and back clipping planes.

#define FRONT_CLIP            D3DVAL(1.0)
#define BACK_CLIP             D3DVAL(1000.0)

// Fixed window size.

#define WINDOW_WIDTH          320
#define WINDOW_HEIGHT         200

// Maximum length of the chosen device name and description of the
// chosen Direct3D device.

#define MAX_DEVICE_NAME       256
#define MAX_DEVICE_DESC       256

// Amount to rotate per frame.

#define M_PI                  3.14159265359
#define M_2PI                 6.28318530718
#define ROTATE_ANGLE_DELTA    (M_2PI / 300.0)

// Execute buffer contents

#define NUM_VERTICES          3
#define NUM_INSTRUCTIONS      6
#define NUM_STATES            7
#define NUM_PROCESSVERTICES   1
#define NUM_TRIANGLES         1


Macros in Imsample.c
// Extract the error code from an HRESULT

#define CODEFROMHRESULT(hRes) ((hRes) & 0x0000FFFF)

#ifdef _DEBUG
#define ASSERT(x)       assert(x)
#else
#define ASSERT(x)
#endif

// Used to keep the compiler from issuing warnings about any unused
// parameters.

#define USE_PARAM(x)    (x) = (x)


Global Variables
// Application instance handle (set in WinMain).

static HINSTANCE               hAppInstance              = NULL;

// Running in debug mode?

static BOOL                    fDebug                    = FALSE;

// Is the application active?

static BOOL                    fActive                   = TRUE;

// Has the application been suspended?

static BOOL                    fSuspended                = FALSE;

// DirectDraw interfaces

static LPDIRECTDRAW            lpdd                      = NULL;
static LPDIRECTDRAWSURFACE     lpddPrimary               = NULL;
static LPDIRECTDRAWSURFACE     lpddDevice                = NULL;
static LPDIRECTDRAWSURFACE     lpddZBuffer               = NULL;
static LPDIRECTDRAWPALETTE     lpddPalette               = NULL;

// Direct3D interfaces

static LPDIRECT3D              lpd3d                     = NULL;
static LPDIRECT3DDEVICE        lpd3dDevice               = NULL;
static LPDIRECT3DMATERIAL      lpd3dMaterial             = NULL;
static LPDIRECT3DMATERIAL      lpd3dBackgroundMaterial   = NULL;
static LPDIRECT3DVIEWPORT      lpd3dViewport             = NULL;
static LPDIRECT3DLIGHT         lpd3dLight                = NULL;
static LPDIRECT3DEXECUTEBUFFER lpd3dExecuteBuffer        = NULL;

// Direct3D handles

static D3DMATRIXHANDLE         hd3dWorldMatrix           = 0;
static D3DMATRIXHANDLE         hd3dViewMatrix            = 0;
static D3DMATRIXHANDLE         hd3dProjMatrix            = 0;
static D3DMATERIALHANDLE       hd3dSurfaceMaterial       = 0;
static D3DMATERIALHANDLE       hd3dBackgroundMaterial    = 0;

// Globals used for selecting the Direct3D device. They are
// globals because this makes it easy for the enumeration callback
// function to read and write from them.

static BOOL                    fDeviceFound              = FALSE;
static DWORD                   dwDeviceBitDepth          = 0;
static GUID                    guidDevice;
static char                    szDeviceName[MAX_DEVICE_NAME];
static char                    szDeviceDesc[MAX_DEVICE_DESC];
static D3DDEVICEDESC           d3dHWDeviceDesc;
static D3DDEVICEDESC           d3dSWDeviceDesc;

// The screen coordinates of the client area of the window. This
// rectangle defines the destination into which we blit to update
// the client area of the window with the results of the 3-D rendering.

static RECT                    rDstRect;

// This rectangle defines the portion of the rendering target surface
// into which we render. The top-left coordinates of this rectangle
// are always zero; the right and bottom coordinates give the size of
// the viewport.

static RECT                    rSrcRect;

// Angle of rotation of the world matrix.

static double                  dAngleOfRotation          = 0.0;

// Predefined transformations.

static D3DMATRIX d3dWorldMatrix =
{
    D3DVAL( 1.0), D3DVAL( 0.0), D3DVAL( 0.0), D3DVAL( 0.0),
    D3DVAL( 0.0), D3DVAL( 1.0), D3DVAL( 0.0), D3DVAL( 0.0),
    D3DVAL( 0.0), D3DVAL( 0.0), D3DVAL( 1.0), D3DVAL( 0.0),
    D3DVAL( 0.0), D3DVAL( 0.0), D3DVAL( 0.0), D3DVAL( 1.0)
};

static D3DMATRIX d3dViewMatrix =
{
    D3DVAL( 1.0), D3DVAL( 0.0), D3DVAL( 0.0), D3DVAL( 0.0),
    D3DVAL( 0.0), D3DVAL( 1.0), D3DVAL( 0.0), D3DVAL( 0.0),
    D3DVAL( 0.0), D3DVAL( 0.0), D3DVAL( 1.0), D3DVAL( 0.0),
    D3DVAL( 0.0), D3DVAL( 0.0), D3DVAL( 5.0), D3DVAL( 1.0)
};

static D3DMATRIX d3dProjMatrix =
{
    D3DVAL( 2.0), D3DVAL( 0.0), D3DVAL( 0.0), D3DVAL( 0.0),
    D3DVAL( 0.0), D3DVAL( 2.0), D3DVAL( 0.0), D3DVAL( 0.0),
    D3DVAL( 0.0), D3DVAL( 0.0), D3DVAL( 1.0), D3DVAL( 1.0),
    D3DVAL( 0.0), D3DVAL( 0.0), D3DVAL(-1.0), D3DVAL( 0.0)
};


Function Prototypes
static void           ReportError(HWND hwnd, int nMessage,
                                  HRESULT hRes);
static void           FatalError(HWND hwnd, int nMessage, HRESULT hRes);

static DWORD          BitDepthToFlags(DWORD dwBitDepth);
static DWORD          FlagsToBitDepth(DWORD dwFlags);

static void           SetPerspectiveProjection(LPD3DMATRIX lpd3dMatrix,
                                             double      dHalfHeight,
                                             double      dFrontClipping,
                                             double      dBackClipping);
static void           SetRotationAboutY(LPD3DMATRIX lpd3dMatrix,
                                        double      dAngleOfRotation);

static HRESULT        CreateDirect3D(HWND hwnd);
static HRESULT        ReleaseDirect3D(void);

static HRESULT        CreatePrimary(HWND hwnd);
static HRESULT        RestorePrimary(void);
static HRESULT        ReleasePrimary(void);

static HRESULT WINAPI EnumDeviceCallback(LPGUID       lpGUID,
                                      LPSTR           lpszDeviceDesc,
                                      LPSTR           lpszDeviceName,
                                      LPD3DDEVICEDESC lpd3dHWDeviceDesc,
                                      LPD3DDEVICEDESC lpd3dSWDeviceDesc,
                                      LPVOID          lpUserArg);
static HRESULT        ChooseDevice(void);

static HRESULT        CreateDevice(DWORD dwWidth, DWORD dwHeight);
static HRESULT        RestoreDevice(void);
static HRESULT        ReleaseDevice(void);

static LRESULT        RestoreSurfaces(void);

static HRESULT        FillExecuteBuffer(void);
static HRESULT        CreateScene(void);
static HRESULT        ReleaseScene(void);
static HRESULT        AnimateScene(void);

static HRESULT        UpdateViewport(void);

static HRESULT        RenderScene(void);
static HRESULT        DoFrame(void);
static void           PaintSuspended(HWND hwnd, HDC hdc);

static LRESULT        OnMove(HWND hwnd, int x, int y);
static LRESULT        OnSize(HWND hwnd, int w, int h);
static LRESULT        OnPaint(HWND hwnd, HDC hdc, LPPAINTSTRUCT lpps);
static LRESULT        OnIdle(HWND hwnd);

LRESULT CALLBACK      WndProc(HWND hwnd, UINT msg,
                              WPARAM wParam, LPARAM lParam);
int PASCAL            WinMain(HINSTANCE hInstance,
                              HINSTANCE hPrevInstance,
                              LPSTR lpszCommandLine, int cmdShow);


Enumerating Direct3D Devices

The first thing a Direct3D application should do is enumerate the available Direct3D device drivers. The most important API element in this job is IDirect3D2::EnumDevices.

This section contains the ChooseDevice function that selects among the available Direct3D devices and the EnumDeviceCallback function that implements the selection mechanism.

  • Enumeration Callback Function
  • Enumeration Function

This sample application does not demonstrate the enumeration of display modes, which you will need to do if your application supports full-screen rendering modes. To enumerate the display modes, call the IDirectDraw2::EnumDisplayModes method.


Enumeration Callback Function

The EnumDeviceCallback function is invoked for each Direct3D device installed on the system. For each device we retrieve its identifying GUID, a name and description, a description of its hardware and software capabilities, and an unused user argument.

The EnumDeviceCallback function uses the following algorithm to choose an appropriate Direct3D device:

  1. Discard any devices which don't match the current display depth.
  2. Discard any devices which can't do Gouraud-shaded triangles.
  3. If a hardware device is found which matches points one and two, use it. However, if we are running in debug mode we will skip hardware.
  4. Otherwise favor Mono/Ramp mode software renderers over RGB ones; until MMX is widespread, Mono will be faster.

This callback function is invoked by the ChooseDevice enumeration function, which is described in Enumeration Function.

Note that the first parameter passed to this callback function, lpGUID, is NULL for the primary device. All other devices should have a non-NULL pointer. You should consider saving the actual GUID for the device you choose, not the pointer to the GUID, in case the pointer is accidentally corrupted.

static HRESULT WINAPI
EnumDeviceCallback(LPGUID          lpGUID,
                   LPSTR           lpszDeviceDesc,
                   LPSTR           lpszDeviceName,
                   LPD3DDEVICEDESC lpd3dHWDeviceDesc,
                   LPD3DDEVICEDESC lpd3dSWDeviceDesc,
                   LPVOID          lpUserArg)
{
    BOOL            fIsHardware;
    LPD3DDEVICEDESC lpd3dDeviceDesc;

        // Call the USE_PARAM macro on the unused parameter to
        // avoid compiler warnings.

    USE_PARAM(lpUserArg);

        // If there is no hardware support the color model is zero.

    fIsHardware     = (0 != lpd3dHWDeviceDesc->dcmColorModel);
    lpd3dDeviceDesc = (fIsHardware ? lpd3dHWDeviceDesc :
                                     lpd3dSWDeviceDesc);

        // If we are in debug mode and this is a hardware device,
        // skip it.

    if (fDebug && fIsHardware)
        return D3DENUMRET_OK;

        // Does the device render at the depth we want?

    if (0 == (lpd3dDeviceDesc->dwDeviceRenderBitDepth &
              dwDeviceBitDepth))
    {
                // If not, skip this device.

        return D3DENUMRET_OK;
    }

        // The device must support Gouraud-shaded triangles.

    if (D3DCOLOR_MONO == lpd3dDeviceDesc->dcmColorModel)
    {
        if (!(lpd3dDeviceDesc->dpcTriCaps.dwShadeCaps &
              D3DPSHADECAPS_COLORGOURAUDMONO))
        {
                        // No Gouraud shading. Skip this device.

            return D3DENUMRET_OK;
        }
    }
    else
    {
        if (!(lpd3dDeviceDesc->dpcTriCaps.dwShadeCaps &
              D3DPSHADECAPS_COLORGOURAUDRGB))
        {
                        // No Gouraud shading. Skip this device.

            return D3DENUMRET_OK;
        }
    }

    if (!fIsHardware && fDeviceFound &&
           (D3DCOLOR_RGB == lpd3dDeviceDesc->dcmColorModel))
    {
                // If this is software RGB and we already have found
                // a software monochromatic renderer, we are not
                // interested. Skip this device.

        return D3DENUMRET_OK;
    }

        // This is a device we are interested in. Save the details.

    fDeviceFound = TRUE;
    CopyMemory(&guidDevice, lpGUID, sizeof(GUID));
    strcpy(szDeviceDesc, lpszDeviceDesc);
    strcpy(szDeviceName, lpszDeviceName);
    CopyMemory(&d3dHWDeviceDesc, lpd3dHWDeviceDesc,
               sizeof(D3DDEVICEDESC));
    CopyMemory(&d3dSWDeviceDesc, lpd3dSWDeviceDesc,
               sizeof(D3DDEVICEDESC));

        // If this is a hardware device, we have found
        // what we are looking for.

    if (fIsHardware)
        return D3DENUMRET_CANCEL;

        // Otherwise, keep looking.

    return D3DENUMRET_OK;
}


Enumeration Function

The ChooseDevice function invokes the EnumDeviceCallback function , which is described in Enumeration Callback Function.

static HRESULT
ChooseDevice(void)
{
    DDSURFACEDESC ddsd;
    HRESULT       hRes;

    ASSERT(NULL != lpd3d);
    ASSERT(NULL != lpddPrimary);

        // Since we are running in a window, we will not be changing the
        // screen depth; therefore, the pixel format of the rendering
        // target must match the pixel format of the current primary
        // surface. This means that we need to determine the pixel
        // format of the primary surface.

    ZeroMemory(&ddsd, sizeof(ddsd));
    ddsd.dwSize = sizeof(ddsd);
    hRes = lpddPrimary->lpVtbl->GetSurfaceDesc(lpddPrimary, &ddsd);
    if (FAILED(hRes))
        return hRes;

    dwDeviceBitDepth =
        BitDepthToFlags(ddsd.ddpfPixelFormat.dwRGBBitCount);

        // Enumerate the devices and pick one.

    fDeviceFound = FALSE;
    hRes = lpd3d->lpVtbl->EnumDevices(lpd3d, EnumDeviceCallback,
                                      &fDeviceFound);
    if (FAILED(hRes))
        return hRes;

    if (!fDeviceFound)
    {
                // No suitable device was found. We cannot allow
                // device-creation to continue.

        return DDERR_NOTFOUND;
    }

    return DD_OK;
}


Creating Objects and Interfaces

This section contains functions that create the primary DirectDraw surface, a DirectDrawClipper object, a Direct3D object, and a Direct3DDevice.

  • Creating the Primary Surface and Clipper Object
  • Creating the Direct3D Object
  • Creating the Direct3D Device


Creating the Primary Surface and Clipper Object

The CreatePrimary function creates the primary surface (representing the desktop) and creates and attaches a clipper object. If necessary, this function also creates a palette.

static HRESULT
CreatePrimary(HWND hwnd)
{
    HRESULT             hRes;
    DDSURFACEDESC       ddsd;
    LPDIRECTDRAWCLIPPER lpddClipper;
    HDC                 hdc;
    int                 i;
    PALETTEENTRY        peColorTable[256];

    ASSERT(NULL != hwnd);
    ASSERT(NULL != lpdd);
    ASSERT(NULL == lpddPrimary);
    ASSERT(NULL == lpddPalette);

    // Create the primary surface.

    ZeroMemory(&ddsd, sizeof(ddsd));
    ddsd.dwSize         = sizeof(ddsd);
    ddsd.dwFlags        = DDSD_CAPS;
    ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
    hRes = lpdd->lpVtbl->CreateSurface(lpdd, &ddsd, &lpddPrimary, NULL);
    if (FAILED(hRes))
        return hRes;

    // Create the clipper. We bind the application's window to the
    // clipper and attach it to the primary. This ensures that when we
    // blit from the rendering surface to the primary we don't write
    // outside the visible region of the window.

    hRes = DirectDrawCreateClipper(0, &lpddClipper, NULL);
    if (FAILED(hRes))
        return hRes;
    hRes = lpddClipper->lpVtbl->SetHWnd(lpddClipper, 0, hwnd);
    if (FAILED(hRes))
    {
        lpddClipper->lpVtbl->Release(lpddClipper);
        return hRes;
    }
    hRes = lpddPrimary->lpVtbl->SetClipper(lpddPrimary, lpddClipper);
    if (FAILED(hRes))
    {
        lpddClipper->lpVtbl->Release(lpddClipper);
        return hRes;
    }

    // We release the clipper interface after attaching it to the
    // surface because we don't need to use it again. The surface
    // holds a reference to the clipper when it has been attached.
    // The clipper will therefore be released automatically when the
    // surface is released.

    lpddClipper->lpVtbl->Release(lpddClipper);

    // If the primary surface is palettized, the device will be, too.
    // (The device surface must have the same pixel format as the
    // current primary surface if we want to double buffer with
    // DirectDraw.) Therefore, if the primary surface is palettized we
    // need to create a palette and attach it to the primary surface
    // (and to the device surface when we create it).

    ZeroMemory(&ddsd, sizeof(ddsd));
    ddsd.dwSize = sizeof(ddsd);
    hRes = lpddPrimary->lpVtbl->GetSurfaceDesc(lpddPrimary, &ddsd);
    if (FAILED(hRes))
        return hRes;
    if (ddsd.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8)
    {
    // Initializing the palette correctly is essential. Since we are
    // running in a window, we must not change the top ten and bottom
    // ten static colors. Therefore, we copy them from the system
    // palette and mark them as read only (D3DPAL_READONLY). The middle
    // 236 entries are free for use by Direct3D so we mark them free
    // (D3DPAL_FREE).

    // NOTE: In order that the palette entries are correctly
    // allocated it is essential that the free entries are
    // also marked reserved to GDI (PC_RESERVED).

    // NOTE: We don't need to specify the palette caps flag
    // DDPCAPS_INITIALIZE. This flag is obsolete. CreatePalette
    // must be given a valid palette-entry array and always
    // initializes from it.

        hdc = GetDC(NULL);
        GetSystemPaletteEntries(hdc, 0, 256, peColorTable);
        ReleaseDC(NULL, hdc);

        for (i = 0; i < 10; i++)
            peColorTable[i].peFlags = D3DPAL_READONLY;
        for (i = 10; i < 246; i++)
            peColorTable[i].peFlags = D3DPAL_FREE | PC_RESERVED;
        for (i = 246; i < 256; i++)
            peColorTable[i].peFlags = D3DPAL_READONLY;
        hRes = lpdd->lpVtbl->CreatePalette(lpdd,
            DDPCAPS_8BIT, peColorTable, &lpddPalette, NULL);

        if (FAILED(hRes))
            return hRes;

        hRes = lpddPrimary->lpVtbl->SetPalette(lpddPrimary,
                lpddPalette);
            return hRes;
    }

    return DD_OK;
}


Creating the Direct3D Object

The CreateDirect3D function creates the DirectDraw (Direct3D) driver objects and retrieves the COM interfaces for communicating with these objects. This function calls three crucial API elements: DirectDrawCreate, to create the DirectDraw object, IDirectDraw::SetCooperativeLevel, to determine whether the application will run in full-screen or windowed mode, and IDirectDraw::QueryInterface, to retrieve a pointer to the Direct3D interface.

static HRESULT
CreateDirect3D(HWND hwnd)
{
    HRESULT hRes;

    ASSERT(NULL == lpdd);
    ASSERT(NULL == lpd3d);

    // Create the DirectDraw/3D driver object and get the DirectDraw
    // interface to that object.

    hRes = DirectDrawCreate(NULL, &lpdd, NULL);
    if (FAILED(hRes))
        return hRes;

    // Since we are running in a window, set the cooperative level to
    // normal. Also, to ensure that the palette is realized correctly,
    // we need to pass the window handle of the main window.

    hRes = lpdd->lpVtbl->SetCooperativeLevel(lpdd, hwnd, DDSCL_NORMAL);
    if (FAILED(hRes))
        return hRes;

        // Retrieve the Direct3D interface to the DirectDraw/3D driver
        // object.

    hRes = lpdd->lpVtbl->QueryInterface(lpdd, &IID_IDirect3D, &lpd3d);
    if (FAILED(hRes))
        return hRes;

    return DD_OK;
}


Creating the Direct3D Device

The CreateDevice function creates an instance of the Direct3D device we chose earlier, using the specified width and height.

This function handles all aspects of the device creation, including choosing the surface-memory type, creating the device surface, creating the z-buffer (if necessary), and attaching the palette (if required). If you create a z-buffer, you must do so before creating an IDirect3DDevice interface.

static HRESULT
CreateDevice(DWORD dwWidth, DWORD dwHeight)
{
    LPD3DDEVICEDESC lpd3dDeviceDesc;
    DWORD           dwDeviceMemType;
    DWORD           dwZBufferMemType;
    DDSURFACEDESC   ddsd;
    HRESULT         hRes;
    DWORD           dwZBufferBitDepth;

    ASSERT(NULL != lpdd);
    ASSERT(NULL != lpd3d);
    ASSERT(NULL != lpddPrimary);
    ASSERT(NULL == lpddDevice);
    ASSERT(NULL == lpd3dDevice);

    // Determine the kind of memory (system or video) from which the
    // device surface should be allocated.

    if (0 != d3dHWDeviceDesc.dcmColorModel)
    {
        lpd3dDeviceDesc = &d3dHWDeviceDesc;

        // Device has a hardware rasterizer. Currently this means that
        // the device surface must be in video memory.

        dwDeviceMemType  = DDSCAPS_VIDEOMEMORY;
        dwZBufferMemType = DDSCAPS_VIDEOMEMORY;
    }
    else
    {
        lpd3dDeviceDesc = &d3dSWDeviceDesc;

        // Device has a software rasterizer. We will let DirectDraw
        // decide where the device surface resides unless we are
        // running in debug mode, in which case we will force it into
        // system memory. For a software rasterizer the z-buffer should
        // always go into system memory. A z-buffer in video memory will
        // seriously degrade the application's performance.

        dwDeviceMemType  = (fDebug ? DDSCAPS_SYSTEMMEMORY : 0);
        dwZBufferMemType = DDSCAPS_SYSTEMMEMORY;
    }

    // Create the device surface. The pixel format will be identical
    // to that of the primary surface, so we don't have to explicitly
    // specify it. We do need to explicitly specify the size, memory
    // type and capabilities  of the surface.

    ZeroMemory(&ddsd, sizeof(ddsd));
    ddsd.dwSize         = sizeof(ddsd);
    ddsd.dwFlags        = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
    ddsd.dwWidth        = dwWidth;
    ddsd.dwHeight       = dwHeight;
    ddsd.ddsCaps.dwCaps = DDSCAPS_3DDEVICE | DDSCAPS_OFFSCREENPLAIN |
                          dwDeviceMemType;
    hRes = lpdd->lpVtbl->CreateSurface(lpdd, &ddsd, &lpddDevice, NULL);
    if (FAILED(hRes))
        return hRes;

    // If we have created a palette, we have already determined that
    // the primary surface (and hence the device surface) is palettized.
    // Therefore, we should attach the palette to the device surface.
    // (The palette is already attached to the primary surface.)

    if (NULL != lpddPalette)
    {
        hRes = lpddDevice->lpVtbl->SetPalette(lpddDevice, lpddPalette);
        if (FAILED(hRes))
            return hRes;
    }

    // We now determine whether or not we need a z-buffer and, if
    // so, its bit depth.

    if (0 != lpd3dDeviceDesc->dwDeviceZBufferBitDepth)
    {
        // The device supports z-buffering. Determine the depth. We
        // select the lowest supported z-buffer depth to save memory.
        // (Accuracy is not too important for this sample.)

        dwZBufferBitDepth =
            FlagsToBitDepth(lpd3dDeviceDesc->dwDeviceZBufferBitDepth);

        // Create the z-buffer.

        ZeroMemory(&ddsd, sizeof(ddsd));
        ddsd.dwSize            = sizeof(ddsd);
        ddsd.dwFlags           = DDSD_CAPS   |
                                 DDSD_WIDTH  |
                                 DDSD_HEIGHT |
                                 DDSD_ZBUFFERBITDEPTH;
        ddsd.ddsCaps.dwCaps    = DDSCAPS_ZBUFFER | dwZBufferMemType;
        ddsd.dwWidth           = dwWidth;
        ddsd.dwHeight          = dwHeight;
        ddsd.dwZBufferBitDepth = dwZBufferBitDepth;
        hRes = lpdd->lpVtbl->CreateSurface(lpdd, &ddsd, &lpddZBuffer,
                                           NULL);
        if (FAILED(hRes))
            return hRes;

                // Attach it to the rendering target.

        hRes = lpddDevice->lpVtbl->AddAttachedSurface(lpddDevice,
                                                      lpddZBuffer);
        if (FAILED(hRes))
            return hRes;
    }

    // Now all the elements are in place: the device surface is in the
    // correct memory type; a z-buffer has been attached with the
    // correct depth and memory type; and a palette has been attached,
    // if necessary. Now we can query for the Direct3D device we chose
    // earlier.

    hRes = lpddDevice->lpVtbl->QueryInterface(lpddDevice,
                                   &guidDevice, &lpd3dDevice);
    if (FAILED(hRes))
        return hRes;

    return DD_OK;
}


Creating the Scene

The CreateScene function creates the elements making up the 3-D scene. In this sample, the scene consists of a single light, the viewport, the background and surface materials, the three transformation matrices, and the execute buffer holding the state changes and drawing primitives.

static HRESULT
CreateScene(void)
{
    HRESULT              hRes;
    D3DMATERIAL          d3dMaterial;
    D3DLIGHT             d3dLight;
    DWORD                dwVertexSize;
    DWORD                dwInstructionSize;
    DWORD                dwExecuteBufferSize;
    D3DEXECUTEBUFFERDESC d3dExecuteBufferDesc;
    D3DEXECUTEDATA       d3dExecuteData;

    ASSERT(NULL != lpd3d);
    ASSERT(NULL != lpd3dDevice);
    ASSERT(NULL == lpd3dViewport);
    ASSERT(NULL == lpd3dMaterial);
    ASSERT(NULL == lpd3dBackgroundMaterial);
    ASSERT(NULL == lpd3dExecuteBuffer);
    ASSERT(NULL == lpd3dLight);
    ASSERT(0  == hd3dWorldMatrix);
    ASSERT(0  == hd3dViewMatrix);
    ASSERT(0  == hd3dProjMatrix);

    // Create the light.

    hRes = lpd3d->lpVtbl->CreateLight(lpd3d, &lpd3dLight, NULL);
    if (FAILED(hRes))
        return hRes;

    ZeroMemory(&d3dLight, sizeof(d3dLight));
    d3dLight.dwSize = sizeof(d3dLight);
    d3dLight.dltType = D3DLIGHT_POINT;
    d3dLight.dcvColor.dvR    = D3DVAL( 1.0);
    d3dLight.dcvColor.dvG    = D3DVAL( 1.0);
    d3dLight.dcvColor.dvB    = D3DVAL( 1.0);
    d3dLight.dcvColor.dvA    = D3DVAL( 1.0);
    d3dLight.dvPosition.dvX  = D3DVAL( 1.0);
    d3dLight.dvPosition.dvY  = D3DVAL(-1.0);
    d3dLight.dvPosition.dvZ  = D3DVAL(-1.0);
    d3dLight.dvAttenuation0  = D3DVAL( 1.0);
    d3dLight.dvAttenuation1  = D3DVAL( 0.1);
    d3dLight.dvAttenuation2  = D3DVAL( 0.0);
    hRes = lpd3dLight->lpVtbl->SetLight(lpd3dLight, &d3dLight);
    if (FAILED(hRes))
        return hRes;

    // Create the background material.

    hRes = lpd3d->lpVtbl->CreateMaterial(lpd3d,
        &lpd3dBackgroundMaterial, NULL);
    if (FAILED(hRes))
        return hRes;

    ZeroMemory(&d3dMaterial, sizeof(d3dMaterial));
    d3dMaterial.dwSize = sizeof(d3dMaterial);
    d3dMaterial.dcvDiffuse.r  = D3DVAL(0.0);
    d3dMaterial.dcvDiffuse.g  = D3DVAL(0.0);
    d3dMaterial.dcvDiffuse.b  = D3DVAL(0.0);
    d3dMaterial.dcvAmbient.r  = D3DVAL(0.0);
    d3dMaterial.dcvAmbient.g  = D3DVAL(0.0);
    d3dMaterial.dcvAmbient.b  = D3DVAL(0.0);
    d3dMaterial.dcvSpecular.r = D3DVAL(0.0);
    d3dMaterial.dcvSpecular.g = D3DVAL(0.0);
    d3dMaterial.dcvSpecular.b = D3DVAL(0.0);
    d3dMaterial.dvPower       = D3DVAL(0.0);

    // Since this is the background material, we don't want a ramp to be
    // allocated. (We will not be smooth-shading the background.)

    d3dMaterial.dwRampSize    = 1;

    hRes = lpd3dBackgroundMaterial->lpVtbl->SetMaterial
        (lpd3dBackgroundMaterial, &d3dMaterial);
    if (FAILED(hRes))
        return hRes;
    hRes = lpd3dBackgroundMaterial->lpVtbl->GetHandle
        (lpd3dBackgroundMaterial, lpd3dDevice, &hd3dBackgroundMaterial);
    if (FAILED(hRes))
        return hRes;

    // Create the viewport.
    // The viewport parameters are set in the UpdateViewport function,
    // which is called in response to WM_SIZE.

    hRes = lpd3d->lpVtbl->CreateViewport(lpd3d, &lpd3dViewport, NULL);
    if (FAILED(hRes))
        return hRes;
    hRes = lpd3dDevice->lpVtbl->AddViewport(lpd3dDevice, lpd3dViewport);
    if (FAILED(hRes))
        return hRes;
    hRes = lpd3dViewport->lpVtbl->SetBackground(lpd3dViewport,
        hd3dBackgroundMaterial);
    if (FAILED(hRes))
        return hRes;
    hRes = lpd3dViewport->lpVtbl->AddLight(lpd3dViewport, lpd3dLight);
    if (FAILED(hRes))
        return hRes;

    // Create the matrices.

    hRes = lpd3dDevice->lpVtbl->CreateMatrix(lpd3dDevice,
        &hd3dWorldMatrix);
    if (FAILED(hRes))
        return hRes;
    hRes = lpd3dDevice->lpVtbl->SetMatrix(lpd3dDevice, hd3dWorldMatrix,
        &d3dWorldMatrix);
    if (FAILED(hRes))
        return hRes;
    hRes = lpd3dDevice->lpVtbl->CreateMatrix(lpd3dDevice,
        &hd3dViewMatrix);
    if (FAILED(hRes))
        return hRes;
    hRes = lpd3dDevice->lpVtbl->SetMatrix(lpd3dDevice, hd3dViewMatrix,
        &d3dViewMatrix);
    if (FAILED(hRes))
        return hRes;
    hRes = lpd3dDevice->lpVtbl->CreateMatrix(lpd3dDevice,
        &hd3dProjMatrix);
    if (FAILED(hRes))
        return hRes;
    SetPerspectiveProjection(&d3dProjMatrix, HALF_HEIGHT, FRONT_CLIP,
        BACK_CLIP);
    hRes = lpd3dDevice->lpVtbl->SetMatrix(lpd3dDevice, hd3dProjMatrix,
        &d3dProjMatrix);
    if (FAILED(hRes))
        return hRes;

    // Create the surface material.

    hRes = lpd3d->lpVtbl->CreateMaterial(lpd3d, &lpd3dMaterial, NULL);
    if (FAILED(hRes))
        return hRes;
    ZeroMemory(&d3dMaterial, sizeof(d3dMaterial));
    d3dMaterial.dwSize = sizeof(d3dMaterial);

    // Base green with white specular.

    d3dMaterial.dcvDiffuse.r  = D3DVAL(0.0);
    d3dMaterial.dcvDiffuse.g  = D3DVAL(1.0);
    d3dMaterial.dcvDiffuse.b  = D3DVAL(0.0);
    d3dMaterial.dcvAmbient.r  = D3DVAL(0.0);
    d3dMaterial.dcvAmbient.g  = D3DVAL(0.4);
    d3dMaterial.dcvAmbient.b  = D3DVAL(0.0);
    d3dMaterial.dcvSpecular.r = D3DVAL(1.0);
    d3dMaterial.dcvSpecular.g = D3DVAL(1.0);
    d3dMaterial.dcvSpecular.b = D3DVAL(1.0);
    d3dMaterial.dvPower       = D3DVAL(20.0);
    d3dMaterial.dwRampSize    = 16;

    hRes = lpd3dMaterial->lpVtbl->SetMaterial(lpd3dMaterial,
        &d3dMaterial);
    if (FAILED(hRes))
        return hRes;

    hRes = lpd3dMaterial->lpVtbl->GetHandle(lpd3dMaterial, lpd3dDevice,
        &hd3dSurfaceMaterial);
    if (FAILED(hRes))
        return hRes;

    // Build the execute buffer.

    dwVertexSize      = (NUM_VERTICES        * sizeof(D3DVERTEX));
    dwInstructionSize = (NUM_INSTRUCTIONS    * sizeof(D3DINSTRUCTION)) +
                        (NUM_STATES          * sizeof(D3DSTATE))       +
                        (NUM_PROCESSVERTICES *
                                        sizeof(D3DPROCESSVERTICES))    +
                        (NUM_TRIANGLES      * sizeof(D3DTRIANGLE));
    dwExecuteBufferSize = dwVertexSize + dwInstructionSize;
    ZeroMemory(&d3dExecuteBufferDesc, sizeof(d3dExecuteBufferDesc));
    d3dExecuteBufferDesc.dwSize       = sizeof(d3dExecuteBufferDesc);
    d3dExecuteBufferDesc.dwFlags      = D3DDEB_BUFSIZE;
    d3dExecuteBufferDesc.dwBufferSize = dwExecuteBufferSize;
    hRes = lpd3dDevice->lpVtbl->CreateExecuteBuffer(lpd3dDevice,
        &d3dExecuteBufferDesc, &lpd3dExecuteBuffer, NULL);
    if (FAILED(hRes))
        return hRes;

    // Fill the execute buffer with the required vertices, state
    // instructions and drawing primitives.

    hRes = FillExecuteBuffer();
    if (FAILED(hRes))
        return hRes;

    // Set the execute data so Direct3D knows how many vertices are in
    // the buffer and where the instructions start.

    ZeroMemory(&d3dExecuteData, sizeof(d3dExecuteData));
    d3dExecuteData.dwSize = sizeof(d3dExecuteData);
    d3dExecuteData.dwVertexCount       = NUM_VERTICES;
    d3dExecuteData.dwInstructionOffset = dwVertexSize;
    d3dExecuteData.dwInstructionLength = dwInstructionSize;
    hRes = lpd3dExecuteBuffer->lpVtbl->SetExecuteData
        (lpd3dExecuteBuffer, &d3dExecuteData);
    if (FAILED(hRes))
        return hRes;

    return DD_OK;
}


Filling the Execute Buffer

The FillExecuteBuffer sample function fills the single execute buffer used in this sample with all the vertices, transformations, light and render states, and drawing primitives necessary to draw our triangle.

The method shown here is not the most efficient way of organizing the execute buffer. For best performance you should minimize state changes. In this sample we submit the execute buffer for each frame in the animation loop and no state in the buffer is modified. The only thing we modify is the world matrix (its contents—not its handle). Therefore, it would be more efficient to extract all the static state instructions into a separate execute buffer which we would issue once only at startup and, from then on, simply execute a second execute buffer with vertices and triangles.

However, because this sample is more concerned with clarity than performance, it uses only one execute buffer and resubmits it in its entirety for each frame.

static HRESULT
FillExecuteBuffer(void)
{
    HRESULT              hRes;
    D3DEXECUTEBUFFERDESC d3dExeBufDesc;
    LPD3DVERTEX          lpVertex;
    LPD3DINSTRUCTION     lpInstruction;
    LPD3DPROCESSVERTICES lpProcessVertices;
    LPD3DTRIANGLE        lpTriangle;
    LPD3DSTATE           lpState;

    ASSERT(NULL != lpd3dExecuteBuffer);
    ASSERT(0  != hd3dSurfaceMaterial);
    ASSERT(0  != hd3dWorldMatrix);
    ASSERT(0  != hd3dViewMatrix);
    ASSERT(0  != hd3dProjMatrix);

    // Lock the execute buffer.

    ZeroMemory(&d3dExeBufDesc, sizeof(d3dExeBufDesc));
    d3dExeBufDesc.dwSize = sizeof(d3dExeBufDesc);
    hRes = lpd3dExecuteBuffer->lpVtbl->Lock(lpd3dExecuteBuffer,
        &d3dExeBufDesc);
    if (FAILED(hRes))
        return hRes;

    // For purposes of illustration, we fill the execute buffer by
    // casting a pointer to the execute buffer to the appropriate data
    // structures.

    lpVertex = (LPD3DVERTEX)d3dExeBufDesc.lpData;

    // First vertex.

    lpVertex->dvX  = D3DVAL( 0.0); // Position in model coordinates
    lpVertex->dvY  = D3DVAL( 1.0);
    lpVertex->dvZ  = D3DVAL( 0.0);
    lpVertex->dvNX = D3DVAL( 0.0); // Normalized illumination normal
    lpVertex->dvNY = D3DVAL( 0.0);
    lpVertex->dvNZ = D3DVAL(-1.0);
    lpVertex->dvTU = D3DVAL( 0.0); // Texture coordinates (not used)
    lpVertex->dvTV = D3DVAL( 1.0);
    lpVertex++;

    // Second vertex.

    lpVertex->dvX  = D3DVAL( 1.0); // Position in model coordinates
    lpVertex->dvY  = D3DVAL(-1.0);
    lpVertex->dvZ  = D3DVAL( 0.0);
    lpVertex->dvNX = D3DVAL( 0.0); // Normalized illumination normal
    lpVertex->dvNY = D3DVAL( 0.0);
    lpVertex->dvNZ = D3DVAL(-1.0);
    lpVertex->dvTU = D3DVAL( 1.0); // Texture coordinates (not used)
    lpVertex->dvTV = D3DVAL( 1.0);
    lpVertex++;

    // Third vertex.

    lpVertex->dvX  = D3DVAL(-1.0); // Position in model coordinates
    lpVertex->dvY  = D3DVAL(-1.0);
    lpVertex->dvZ  = D3DVAL( 0.0);
    lpVertex->dvNX = D3DVAL( 0.0); // Normalized illumination normal
    lpVertex->dvNY = D3DVAL( 0.0);
    lpVertex->dvNZ = D3DVAL(-1.0);
    lpVertex->dvTU = D3DVAL( 1.0); // Texture coordinates (not used)
    lpVertex->dvTV = D3DVAL( 0.0);
    lpVertex++;

    // Transform state - world, view and projection.

    lpInstruction = (LPD3DINSTRUCTION)lpVertex;
    lpInstruction->bOpcode = D3DOP_STATETRANSFORM;
    lpInstruction->bSize   = sizeof(D3DSTATE);
    lpInstruction->wCount  = 3U;
    lpInstruction++;
    lpState = (LPD3DSTATE)lpInstruction;
    lpState->dtstTransformStateType = D3DTRANSFORMSTATE_WORLD;
    lpState->dwArg[0] = hd3dWorldMatrix;
    lpState++;
    lpState->dtstTransformStateType = D3DTRANSFORMSTATE_VIEW;
    lpState->dwArg[0] = hd3dViewMatrix;
    lpState++;
    lpState->dtstTransformStateType = D3DTRANSFORMSTATE_PROJECTION;
    lpState->dwArg[0] = hd3dProjMatrix;
    lpState++;

    // Lighting state.

    lpInstruction = (LPD3DINSTRUCTION)lpState;
    lpInstruction->bOpcode = D3DOP_STATELIGHT;
    lpInstruction->bSize   = sizeof(D3DSTATE);
    lpInstruction->wCount  = 2U;
    lpInstruction++;
    lpState = (LPD3DSTATE)lpInstruction;
    lpState->dlstLightStateType = D3DLIGHTSTATE_MATERIAL;
    lpState->dwArg[0] = hd3dSurfaceMaterial;
    lpState++;
    lpState->dlstLightStateType = D3DLIGHTSTATE_AMBIENT;
    lpState->dwArg[0] = RGBA_MAKE(128, 128, 128, 128);
    lpState++;

    // Render state.

    lpInstruction = (LPD3DINSTRUCTION)lpState;
    lpInstruction->bOpcode = D3DOP_STATERENDER;
    lpInstruction->bSize = sizeof(D3DSTATE);
    lpInstruction->wCount = 3U;
    lpInstruction++;
    lpState = (LPD3DSTATE)lpInstruction;
    lpState->drstRenderStateType = D3DRENDERSTATE_FILLMODE;
    lpState->dwArg[0] = D3DFILL_SOLID;
    lpState++;
    lpState->drstRenderStateType = D3DRENDERSTATE_SHADEMODE;
    lpState->dwArg[0] = D3DSHADE_GOURAUD;
    lpState++;
    lpState->drstRenderStateType = D3DRENDERSTATE_DITHERENABLE;
    lpState->dwArg[0] = TRUE;
    lpState++;

    // The D3DOP_PROCESSVERTICES instruction tells the driver what to
    // do with the vertices in the buffer. In this sample we want
    // Direct3D to perform the entire pipeline on our behalf, so
    // the instruction is D3DPROCESSVERTICES_TRANSFORMLIGHT.

    lpInstruction = (LPD3DINSTRUCTION)lpState;
    lpInstruction->bOpcode = D3DOP_PROCESSVERTICES;
    lpInstruction->bSize   = sizeof(D3DPROCESSVERTICES);
    lpInstruction->wCount  = 1U;
    lpInstruction++;
    lpProcessVertices = (LPD3DPROCESSVERTICES)lpInstruction;
    lpProcessVertices->dwFlags    = D3DPROCESSVERTICES_TRANSFORMLIGHT;
    lpProcessVertices->wStart     = 0U;           // First source vertex
    lpProcessVertices->wDest      = 0U;
    lpProcessVertices->dwCount    = NUM_VERTICES; // Number of vertices
    lpProcessVertices->dwReserved = 0;
    lpProcessVertices++;

    // Draw the triangle.

    lpInstruction = (LPD3DINSTRUCTION)lpProcessVertices;
    lpInstruction->bOpcode = D3DOP_TRIANGLE;
    lpInstruction->bSize   = sizeof(D3DTRIANGLE);
    lpInstruction->wCount  = 1U;
    lpInstruction++;
    lpTriangle = (LPD3DTRIANGLE)lpInstruction;
    lpTriangle->wV1    = 0U;
    lpTriangle->wV2    = 1U;
    lpTriangle->wV3    = 2U;
    lpTriangle->wFlags = D3DTRIFLAG_EDGEENABLETRIANGLE;
    lpTriangle++;

    // Stop execution of the buffer.

    lpInstruction = (LPD3DINSTRUCTION)lpTriangle;
    lpInstruction->bOpcode = D3DOP_EXIT;
    lpInstruction->bSize   = 0;
    lpInstruction->wCount  = 0U;

    // Unlock the execute buffer.

    lpd3dExecuteBuffer->lpVtbl->Unlock(lpd3dExecuteBuffer);

    return DD_OK;
}


Animating the Scene

The animation in this sample is simply a rotation about the y-axis. All we need to do is build a rotation matrix and set the world matrix to that new rotation matrix.

We don't need to modify the execute buffer in any way to perform this rotation. We simply set the matrix and resubmit the execute buffer.

static HRESULT
AnimateScene(void)
{
    HRESULT hRes;

    ASSERT(NULL != lpd3dDevice);
    ASSERT(0  != hd3dWorldMatrix);

    // We rotate the triangle by setting the world transform to a
    // rotation matrix.

    SetRotationAboutY(&d3dWorldMatrix, dAngleOfRotation);
    dAngleOfRotation += ROTATE_ANGLE_DELTA;
    hRes = lpd3dDevice->lpVtbl->SetMatrix(lpd3dDevice,
        hd3dWorldMatrix, &d3dWorldMatrix);
    if (FAILED(hRes))
        return hRes;

    return DD_OK;
}


Rendering Using an Execute Buffer

This section contains functions that render the entire scene and render a single frame.

  • Rendering the Scene
  • Rendering a Single Frame


Rendering the Scene

The RenderScene function renders the 3-D scene, just as you might suspect. The fundamental task performed by this function is submitting the single execute buffer used by this sample. However, the function also clears the back and z-buffers and demarcates the start and end of the scene (which in this case is a single execute).

When you clear the back and z-buffers, it's safe to specify the z-buffer clear flag even if we don't have an attached z-buffer. Direct3D will simply discard the flag if no z-buffer is being used.

For maximum efficiency we only want to clear those regions of the device surface and z-buffer which we actually rendered to in the last frame. This is the purpose of the array of rectangles and count passed to this function. It is possible to query Direct3D for the regions of the device surface that were rendered to by that execute. The application can then accumulate those rectangles and clear only those regions. However this is a very simple sample and so, for simplicity, we will just clear the entire device surface and z-buffer. You should probably implement a more efficient clearing mechanism in your application.

The RenderScene function must be called once and once only for every frame of animation. If you have multiple execute buffers comprising a single frame you must have one call to the IDirect3DDevice::BeginScene method before submitting those execute buffers. If you have more than one device being rendered in a single frame, (for example, a rear-view mirror in a racing game), call the IDirect3DDevice::BeginScene and IDirect3DDevice::EndScene methods once for each device.

When the RenderScene function returns DD_OK, the scene will have been rendered and the device surface will hold the contents of the rendering.

static HRESULT
RenderScene(void)
{
    HRESULT hRes;
    D3DRECT d3dRect;

    ASSERT(NULL != lpd3dViewport);
    ASSERT(NULL != lpd3dDevice);
    ASSERT(NULL != lpd3dExecuteBuffer);

    // Clear both back and z-buffer.

    d3dRect.lX1 = rSrcRect.left;
    d3dRect.lX2 = rSrcRect.right;
    d3dRect.lY1 = rSrcRect.top;
    d3dRect.lY2 = rSrcRect.bottom;
    hRes = lpd3dViewport->lpVtbl->Clear(lpd3dViewport, 1, &d3dRect,
        D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER);
    if (FAILED(hRes))
        return hRes;

    // Start the scene.

    hRes = lpd3dDevice->lpVtbl->BeginScene(lpd3dDevice);
    if (FAILED(hRes))
        return hRes;

    // Submit the execute buffer.

    // We want Direct3D to clip the data on our behalf so we specify
    // D3DEXECUTE_CLIPPED.

    hRes = lpd3dDevice->lpVtbl->Execute(lpd3dDevice, lpd3dExecuteBuffer,
        lpd3dViewport, D3DEXECUTE_CLIPPED);
    if (FAILED(hRes))
    {
        lpd3dDevice->lpVtbl->EndScene(lpd3dDevice);
        return hRes;
    }

        // End the scene.

    hRes = lpd3dDevice->lpVtbl->EndScene(lpd3dDevice);
    if (FAILED(hRes))
        return hRes;

    return DD_OK;
}


Rendering a Single Frame

The DoFrame function renders and shows a single frame. This involves rendering the scene and blitting the result to the client area of the application window on the primary surface.

This function handles lost surfaces by attempting to restore the application's surfaces and then retrying the rendering. It is called by the OnMove function (discussed in Redrawing on Window Movement), the OnSize function (discussed in Redrawing on Window Resizing), and the OnPaint function (discussed in Repainting the Client Area).

static HRESULT
DoFrame(void)
{
    HRESULT hRes;

    // We keeping trying until we succeed or we fail for a reason
    // other than DDERR_SURFACELOST.

    while (TRUE)
    {
        hRes = RenderScene();
        if (SUCCEEDED(hRes))
        {
            hRes = lpddPrimary->lpVtbl->Blt(lpddPrimary, &rDstRect,
                lpddDevice, &rSrcRect, DDBLT_WAIT, NULL);
            if (SUCCEEDED(hRes))  // If it worked.
                return hRes;
        }
        while (DDERR_SURFACELOST == hRes)  // Restore lost surfaces
            hRes = RestoreSurfaces();
        if (FAILED(hRes))  // handle other failure cases
            return hRes;
    }
}


Working with Matrices

This section contains two functions that work with matrices: the SetPerspectiveProjection function, which sets a given matrix to the appropriate values for the front and back clipping plane, and the SetRotationAboutY function, which sets a matrix to a rotation about the y-axis.

  • Setting the Perspective Transformation
  • Setting a Rotation Transformation


Setting the Perspective Transformation

The SetPerspectiveProjection function sets the given matrix to a perspective transform for the given half-height and front- and back-clipping planes. This function is called as part of the CreateScene function, documented in Creating the Scene.

static void
SetPerspectiveProjection(LPD3DMATRIX lpd3dMatrix,
                         double      dHalfHeight,
                         double      dFrontClipping,
                         double      dBackClipping)
{
    double dTmp1;
    double dTmp2;

    ASSERT(NULL != lpd3dMatrix);

    dTmp1 = dHalfHeight / dFrontClipping;
    dTmp2 = dBackClipping / (dBackClipping - dFrontClipping);

    lpd3dMatrix->_11 =  D3DVAL(2.0);
    lpd3dMatrix->_12 =  D3DVAL(0.0);
    lpd3dMatrix->_13 =  D3DVAL(0.0);
    lpd3dMatrix->_14 =  D3DVAL(0.0);
    lpd3dMatrix->_21 =  D3DVAL(0.0);
    lpd3dMatrix->_22 =  D3DVAL(2.0);
    lpd3dMatrix->_23 =  D3DVAL(0.0);
    lpd3dMatrix->_24 =  D3DVAL(0.0);
    lpd3dMatrix->_31 =  D3DVAL(0.0);
    lpd3dMatrix->_32 =  D3DVAL(0.0);
    lpd3dMatrix->_33 =  D3DVAL(dTmp1 * dTmp2);
    lpd3dMatrix->_34 =  D3DVAL(dTmp1);
    lpd3dMatrix->_41 =  D3DVAL(0.0);
    lpd3dMatrix->_42 =  D3DVAL(0.0);
    lpd3dMatrix->_43 =  D3DVAL(-dHalfHeight * dTmp2);
    lpd3dMatrix->_44 =  D3DVAL(0.0);
}


Setting a Rotation Transformation

The SetRotationAboutY function sets the given matrix to a rotation about the y-axis, using the specified number of radians. This function is called as part of the AnimateScene function, documented in Animating the Scene.

static void
SetRotationAboutY(LPD3DMATRIX lpd3dMatrix, double dAngleOfRotation)
{
    D3DVALUE dvCos;
    D3DVALUE dvSin;

    ASSERT(NULL != lpd3dMatrix);

    dvCos = D3DVAL(cos(dAngleOfRotation));
    dvSin = D3DVAL(sin(dAngleOfRotation));

    lpd3dMatrix->_11 =  dvCos;
    lpd3dMatrix->_12 =  D3DVAL(0.0);
    lpd3dMatrix->_13 = -dvSin;
    lpd3dMatrix->_14 =  D3DVAL(0.0);
    lpd3dMatrix->_21 =  D3DVAL(0.0);
    lpd3dMatrix->_22 =  D3DVAL(1.0);
    lpd3dMatrix->_23 =  D3DVAL(0.0);
    lpd3dMatrix->_24 =  D3DVAL(0.0);
    lpd3dMatrix->_31 =  dvSin;
    lpd3dMatrix->_32 =  D3DVAL(0.0);
    lpd3dMatrix->_33 =  dvCos;
    lpd3dMatrix->_34 =  D3DVAL(0.0);
    lpd3dMatrix->_41 =  D3DVAL(0.0);
    lpd3dMatrix->_42 =  D3DVAL(0.0);
    lpd3dMatrix->_43 =  D3DVAL(0.0);
    lpd3dMatrix->_44 =  D3DVAL(1.0);
}


Restoring and Redrawing

This section contains functions that restore objects and surfaces that may have been lost while the application is running.

  • Restoring the Direct3D Device
  • Restoring the Primary Surface
  • Restoring All Surfaces
  • Redrawing on Window Movement
  • Redrawing on Window Resizing
  • Repainting the Client Area
  • Updating the Viewport


Restoring the Direct3D Device

The RestoreDevice function restores lost video memory for the device surface and z-buffer.

static HRESULT
RestoreDevice(void)
{
    HRESULT hRes;

    if (NULL != lpddZBuffer)
    {
        hRes = lpddZBuffer->lpVtbl->Restore(lpddZBuffer);
        if (FAILED(hRes))
            return hRes;
    }

    if (NULL != lpddDevice)
    {
        hRes = lpddDevice->lpVtbl->Restore(lpddDevice);
        if (FAILED(hRes))
            return hRes;
    }

    return DD_OK;
}


Restoring the Primary Surface

The RestorePrimary function attempts to restore the video memory allocated for the primary surface. This function will be invoked by a DirectX function returning DDERR_SURFACELOST due to a mode switch or full-screen DOS box invalidating video memory.

static HRESULT
RestorePrimary(void)
{
    ASSERT(NULL != lpddPrimary);

    return lpddPrimary->lpVtbl->Restore(lpddPrimary);
}


Restoring All Surfaces

The RestoreSurfaces function attempts to restore all the surfaces used by the application.

static LRESULT
RestoreSurfaces(void)
{
    HRESULT hRes;

    hRes = RestorePrimary();
    if (FAILED(hRes))
        return hRes;

    hRes = RestoreDevice();
    if (FAILED(hRes))
        return hRes;

    return DD_OK;
}


Redrawing on Window Movement
static LRESULT
OnMove(HWND hwnd, int x, int y)
{
    int     xDelta;
    int     yDelta;
    HRESULT hRes;

    // No action if the device has not yet been created or if we are
    // suspended.

    if ((NULL != lpd3dDevice) && !fSuspended)
    {
        // Update the destination rectangle for the new client position.

        xDelta = x - rDstRect.left;
        yDelta = y - rDstRect.top;

        rDstRect.left   += xDelta;
        rDstRect.top    += yDelta;
        rDstRect.right  += xDelta;
        rDstRect.bottom += yDelta;

        // Repaint the client area.

        hRes = DoFrame();
        if (FAILED(hRes))
        {
            FatalError(hwnd, IDS_ERRMSG_RENDERSCENE, hRes);
            return 0L;
        }
    }

    return 0L;
}


Redrawing on Window Resizing
static LRESULT
OnSize(HWND hwnd, int w, int h)
{
    HRESULT       hRes;
    DDSURFACEDESC ddsd;

        // Nothing to do if we are suspended.

    if (!fSuspended)
    {
        // Update the source and destination rectangles (used by the
        // blit that shows the rendering in the client area).

        rDstRect.right  = rDstRect.left + w;
        rDstRect.bottom = rDstRect.top  + h;
        rSrcRect.right  = w;
        rSrcRect.bottom = h;

        if (NULL != lpd3dDevice)
        {
            // Although we already have a device, we need to be sure it
            // is big enough for the new window client size.

            // Because the window in this sample has a fixed size, it
            // should never be necessary to handle this case. This code
            // will be useful when we make the application resizable.

            ZeroMemory(&ddsd, sizeof(ddsd));
            ddsd.dwSize = sizeof(ddsd);
            hRes = lpddDevice->lpVtbl->GetSurfaceDesc(lpddDevice,
                &ddsd);
            if (FAILED(hRes))
            {
                FatalError(hwnd, IDS_ERRMSG_DEVICESIZE, hRes);
                return 0L;
            }

            if ((w > (int)ddsd.dwWidth) || (h > (int)ddsd.dwHeight))
            {
                // The device is too small. We need to shut it down
                // and rebuild it.

                // Execute buffers are bound to devices, so when
                // we release the device we must release the execute
                // buffer.

                ReleaseScene();
                ReleaseDevice();
            }
        }

        if (NULL == lpd3dDevice)
        {
            // No Direct3D device yet. This is either because this is
            // the first time through the loop or because we discarded
            // the existing device because it was not big enough for the
            // new window client size.

            hRes = CreateDevice((DWORD)w, (DWORD)h);
            if (FAILED(hRes))
            {
                FatalError(hwnd, IDS_ERRMSG_CREATEDEVICE, hRes);
                return 0L;
            }
            hRes = CreateScene();
            if (FAILED(hRes))
            {
                FatalError(hwnd, IDS_ERRMSG_BUILDSCENE, hRes);
                return 0L;
            }
        }

        hRes = UpdateViewport();
        if (FAILED(hRes))
        {
            FatalError(hwnd, IDS_ERRMSG_UPDATEVIEWPORT, hRes);
            return 0L;
        }

        // Render at the new size and show the results in the window's
        // client area.

        hRes = DoFrame();
        if (FAILED(hRes))
        {
            FatalError(hwnd, IDS_ERRMSG_RENDERSCENE, hRes);
            return 0L;
        }
    }

    return 0L;
}


Repainting the Client Area

The OnPaint function repaints the client area, when required. Notice that it calls the DoFrame function to do much of the work, even though DoFrame re-renders the scene as well as blitting the result to the primary surface. Although the re-rendering is not necessary, for this simple sample this inefficiency does not matter. In your application, you should re-render only when the scene changes.

For more information about the DoFrame function, see Rendering a Single Frame.

static LRESULT
OnPaint(HWND hwnd, HDC hdc, LPPAINTSTRUCT lpps)
{
    HRESULT hRes;

    USE_PARAM(lpps);

    if (fActive && !fSuspended && (NULL != lpd3dDevice))
    {
        hRes = DoFrame();
        if (FAILED(hRes))
        {
            FatalError(hwnd, IDS_ERRMSG_RENDERSCENE, hRes);
            return 0L;
        }
    }
    else
    {
        // Show the suspended image if we are not active or suspended or
        // if we have not yet created the device.

        PaintSuspended(hwnd, hdc);
    }

    return 0L;
}


Updating the Viewport

The UpdateViewport function updates the viewport in response to a change in window size. This ensures that we render at a resolution that matches the client area of the target window.

static HRESULT
UpdateViewport(void)
{
    D3DVIEWPORT d3dViewport;

    ASSERT(NULL != lpd3dViewport);

    ZeroMemory(&d3dViewport, sizeof(d3dViewport));
    d3dViewport.dwSize   = sizeof(d3dViewport);
    d3dViewport.dwX      = 0;
    d3dViewport.dwY      = 0;
    d3dViewport.dwWidth  = (DWORD)rSrcRect.right;
    d3dViewport.dwHeight = (DWORD)rSrcRect.bottom;
    d3dViewport.dvScaleX = D3DVAL((float)d3dViewport.dwWidth / 2.0);
    d3dViewport.dvScaleY = D3DVAL((float)d3dViewport.dwHeight / 2.0);
    d3dViewport.dvMaxX   = D3DVAL(1.0);
    d3dViewport.dvMaxY   = D3DVAL(1.0);
    return lpd3dViewport->lpVtbl->SetViewport(lpd3dViewport,
        &d3dViewport);
}


Releasing Objects

This section contains functions that release objects when they are no longer needed.

  • Releasing the Direct3D Object
  • Releasing the Direct3D Device
  • Releasing the Primary Surface
  • Releasing the Objects in the Scene


Releasing the Direct3D Object

The ReleaseDirect3D function releases the DirectDraw (Direct3D) driver object.

static HRESULT
ReleaseDirect3D(void)
{
    if (NULL != lpd3d)
    {
        lpd3d->lpVtbl->Release(lpd3d);
        lpd3d = NULL;
    }
    if (NULL != lpdd)
    {
        lpdd->lpVtbl->Release(lpdd);
        lpdd = NULL;
    }

    return DD_OK;
}


Releasing the Direct3D Device

The ReleaseDevice function releases the Direct3D device and its associated surfaces.

static HRESULT
ReleaseDevice(void)
{
    if (NULL != lpd3dDevice)
    {
        lpd3dDevice->lpVtbl->Release(lpd3dDevice);
        lpd3dDevice = NULL;
    }
    if (NULL != lpddZBuffer)
    {
        lpddZBuffer->lpVtbl->Release(lpddZBuffer);
        lpddZBuffer = NULL;
    }
    if (NULL != lpddDevice)
    {
        lpddDevice->lpVtbl->Release(lpddDevice);
        lpddDevice = NULL;
    }

    return DD_OK;
}


Releasing the Primary Surface

The ReleasePrimary function releases the primary surface and its attached clipper and palette.

static HRESULT
ReleasePrimary(void)
{
    if (NULL != lpddPalette)
    {
        lpddPalette->lpVtbl->Release(lpddPalette);
        lpddPalette = NULL;
    }
    if (NULL != lpddPrimary)
    {
        lpddPrimary->lpVtbl->Release(lpddPrimary);
        lpddPrimary = NULL;
    }

    return DD_OK;
}


Releasing the Objects in the Scene

The ReleaseScene function releases all the objects making up the 3-D scene.

static HRESULT
ReleaseScene(void)
{
    if (NULL != lpd3dExecuteBuffer)
    {
        lpd3dExecuteBuffer->lpVtbl->Release(lpd3dExecuteBuffer);
        lpd3dExecuteBuffer = NULL;
    }
    if (NULL != lpd3dBackgroundMaterial)
    {
        lpd3dBackgroundMaterial->
            lpVtbl->Release(lpd3dBackgroundMaterial);
        lpd3dBackgroundMaterial = NULL;
    }
    if (NULL != lpd3dMaterial)
    {
        lpd3dMaterial->lpVtbl->Release(lpd3dMaterial);
        lpd3dMaterial = NULL;
    }
    if (0 != hd3dWorldMatrix)
    {
        lpd3dDevice->lpVtbl->DeleteMatrix(lpd3dDevice, hd3dWorldMatrix);
        hd3dWorldMatrix = 0;
    }
    if (0 != hd3dViewMatrix)
    {
        lpd3dDevice->lpVtbl->DeleteMatrix(lpd3dDevice, hd3dViewMatrix);
        hd3dViewMatrix = 0;
    }
    if (0 != hd3dProjMatrix)
    {
        lpd3dDevice->lpVtbl->DeleteMatrix(lpd3dDevice, hd3dProjMatrix);
        hd3dProjMatrix = 0;
    }
    if (NULL != lpd3dLight)
    {
        lpd3dLight->lpVtbl->Release(lpd3dLight);
        lpd3dLight = NULL;
    }
    if (NULL != lpd3dViewport)
    {
        lpd3dViewport->lpVtbl->Release(lpd3dViewport);
        lpd3dViewport = NULL;
    }

    return DD_OK;
}


Error Checking

This section contains functions that help you check for and report errors.

  • Checking for Active Status
  • Reporting Standard Errors
  • Reporting Fatal Errors
  • Displaying a Notification String


Checking for Active Status
static LRESULT
OnIdle(HWND hwnd)
{
    HRESULT hRes;

    // Only animate if we are the foreground app, we aren't suspended,
    // and we have completed initialization.

    if (fActive && !fSuspended && (NULL != lpd3dDevice))
    {
        hRes = AnimateScene();
        if (FAILED(hRes))
        {
            FatalError(hwnd, IDS_ERRMSG_ANIMATESCENE, hRes);
            return 0L;
        }

        hRes = DoFrame();
        if (FAILED(hRes))
        {
            FatalError(hwnd, IDS_ERRMSG_RENDERSCENE, hRes);
            return 0L;
        }
    }

    return 0L;
}


Reporting Standard Errors

The ReportError function displays a message box to report an error.

static void
ReportError(HWND hwnd, int nMessage, HRESULT hRes)
{
    HDC  hdc;
    char szBuffer[256];
    char szMessage[128];
    char szError[128];
    int  nStrID;

    // Turn the animation loop off.

    fSuspended = TRUE;

    // Get the high level error message.

    LoadString(hAppInstance, nMessage, szMessage, sizeof(szMessage));

    // We issue sensible error messages for common run time errors. For
    // errors which are internal or coding errors we simply issue an
    // error number (they should never occur).

    switch (hRes)
    {
        case DDERR_EXCEPTION:        nStrID = IDS_ERR_EXCEPTION;        break;
        case DDERR_GENERIC:          nStrID = IDS_ERR_GENERIC;          break;
        case DDERR_OUTOFMEMORY:      nStrID = IDS_ERR_OUTOFMEMORY;      break;
        case DDERR_OUTOFVIDEOMEMORY: nStrID = IDS_ERR_OUTOFVIDEOMEMORY; break;
        case DDERR_SURFACEBUSY:      nStrID = IDS_ERR_SURFACEBUSY;      break;
        case DDERR_SURFACELOST:      nStrID = IDS_ERR_SURFACELOST;      break;
        case DDERR_WRONGMODE:        nStrID = IDS_ERR_WRONGMODE;        break;
        default:                     nStrID = IDS_ERR_INTERNALERROR;    break;
    }
    LoadString(hAppInstance, nStrID, szError, sizeof(szError));

    // Show the "paused" display.

    hdc = GetDC(hwnd);
    PaintSuspended(hwnd, hdc);
    ReleaseDC(hwnd, hdc);

    // Convert the error code into a string.

    wsprintf(szBuffer, "%s\n%s (Error #%d)", szMessage, szError,
        CODEFROMHRESULT(hRes));
    MessageBox(hwnd, szBuffer, WINDOW_TITLE, MB_OK | MB_APPLMODAL);
    fSuspended = FALSE;
}


Reporting Fatal Errors

The FatalError function displays a message box to report an error message and then destroys the window. The function does not perform any clean-up; this is done when the application receives the WM_DESTROY message sent by the DestroyWindow function.

static void
FatalError(HWND hwnd, int nMessage, HRESULT hRes)
{
    ReportError(hwnd, nMessage, hRes);
    fSuspended = TRUE;

    DestroyWindow(hwnd);
}


Displaying a Notification String

The PaintSuspended function draws a notification string in the client area whenever the application is suspended—for example, when it is in the background or is handling an error.

static void
PaintSuspended(HWND hwnd, HDC hdc)
{
    HPEN     hOldPen;
    HBRUSH   hOldBrush;
    COLORREF crOldTextColor;
    int      oldMode;
    int      x;
    int      y;
    SIZE     size;
    RECT     rect;
    int      nStrLen;

    // Black background.

    hOldPen   = SelectObject(hdc, GetStockObject(NULL_PEN));
    hOldBrush = SelectObject(hdc, GetStockObject(BLACK_BRUSH));

    // White text.

    oldMode = SetBkMode(hdc, TRANSPARENT);
    crOldTextColor = SetTextColor(hdc, RGB(255, 255, 255));

    GetClientRect(hwnd, &rect);

    // Clear the client area.

    Rectangle(hdc, rect.left, rect.top, rect.right + 1, rect.bottom + 1);

    // Draw the string centered in the client area.

    nStrLen = strlen(PAUSED_STRING);
    GetTextExtentPoint32(hdc, PAUSED_STRING, nStrLen, &size);
    x = (rect.right  - size.cx) / 2;
    y = (rect.bottom - size.cy) / 2;
    TextOut(hdc, x, y, PAUSED_STRING, nStrLen);

    SetTextColor(hdc, crOldTextColor);
    SetBkMode(hdc, oldMode);

    SelectObject(hdc, hOldBrush);
    SelectObject(hdc, hOldPen);
}


Converting Bit Depths

This section contains functions that convert bit depths into flags and vice versa.

  • Converting a Bit Depth into a Flag
  • Converting a Flag into a Bit Depth


Converting a Bit Depth into a Flag

The BitDepthToFlags function is used by the ChooseDevice enumeration function to convert a bit depth into the appropriate DirectDraw bit depth flag. For more information, see Enumeration Function

static DWORD
BitDepthToFlags(DWORD dwBitDepth)
{
    switch (dwBitDepth)
    {
        case  1: return DDBD_1;
        case  2: return DDBD_2;
        case  4: return DDBD_4;
        case  8: return DDBD_8;
        case 16: return DDBD_16;
        case 24: return DDBD_24;
        case 32: return DDBD_32;
        default: return 0;
    }
}


Converting a Flag into a Bit Depth

The FlagsToBitDepth function is used by the CreateDevice function to convert bit-depth flags to an actual bit count. It selects the smallest bit count in the mask if more than one flag is present. For more information, see Creating the Direct3D Device.

static DWORD
FlagsToBitDepth(DWORD dwFlags)
{
    if (dwFlags & DDBD_1)
        return 1;
    else if (dwFlags & DDBD_2)
        return 2;
    else if (dwFlags & DDBD_4)
        return 4;
    else if (dwFlags & DDBD_8)
        return 8;
    else if (dwFlags & DDBD_16)
        return 16;
    else if (dwFlags & DDBD_24)
        return 24;
    else if (dwFlags & DDBD_32)
        return 32;
    else
        return 0;
}


Main Window Procedure
LRESULT CALLBACK
WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    HDC         hdc;
    PAINTSTRUCT ps;
    LRESULT     lResult;
    HRESULT     hRes;
    char        szBuffer[128];

    switch (msg)
    {
        case WM_CREATE:
            hRes = CreateDirect3D(hwnd);
            if (FAILED(hRes))
            {
                ReportError(hwnd, IDS_ERRMSG_CREATEDEVICE, hRes);
                ReleaseDirect3D();
                return -1L;
            }

            hRes = CreatePrimary(hwnd);
            if (FAILED(hRes))
            {
                ReportError(hwnd, IDS_ERRMSG_INITSCREEN, hRes);
                ReleasePrimary();
                ReleaseDirect3D();
                return -1L;
            }

            hRes = ChooseDevice();
            if (FAILED(hRes))
            {
                ReportError(hwnd, IDS_ERRMSG_NODEVICE, hRes);
                ReleasePrimary();
                ReleaseDirect3D();
                return -1L;
            }

            // Update the title to show the name of the chosen device.

            wsprintf(szBuffer, "%s: %s", WINDOW_TITLE, szDeviceName);
            SetWindowText(hwnd, szBuffer);

            return 0L;

        case WM_MOVE:
            return OnMove(hwnd, (int)LOWORD(lParam),
                (int)HIWORD(lParam));

        case WM_SIZE:
            return OnSize(hwnd, (int)LOWORD(lParam),
                (int)HIWORD(lParam));

        case WM_ERASEBKGND:
        // Our rendering fills the entire viewport so we won't bother
        // erasing the background.

            return 1L;

        case WM_PAINT:
            hdc = BeginPaint(hwnd, &ps);

            lResult = OnPaint(hwnd, hdc, &ps);

            EndPaint(hwnd, &ps);
            return lResult;

        case WM_ACTIVATEAPP:
            fActive = (BOOL)wParam;
            if (fActive && !fSuspended && (NULL != lpddPalette))
            {
                // Realizing the palette using DirectDraw is different
                // from GDI. To realize the palette we call SetPalette
                // each time our application is activated.

                // NOTE: DirectDraw recognizes that the new palette
                // is the same as the old one and so does not increase
                // the reference count of the palette.

                hRes = lpddPrimary->lpVtbl->SetPalette(lpddPrimary,
                    lpddPalette);
                if (FAILED(hRes))
                {
                    FatalError(hwnd, IDS_ERRMSG_REALIZEPALETTE, hRes);
                    return 0L;
                }

            }
            else
            {
                // If we have been deactived, invalidate to show
                // the suspended display.

                InvalidateRect(hwnd, NULL, FALSE);
            }
            return 0L;

        case WM_KEYUP:
            // We use the escape key as a quick way of
            // getting out of the application.

            if (VK_ESCAPE == (int)wParam)
            {
                DestroyWindow(hwnd);
                return 0L;
            }
            break;

        case WM_CLOSE:
            DestroyWindow(hwnd);
            return 0L;

        case WM_DESTROY:
            // All cleanup is done here when terminating normally or
            // shutting down due to an error.

            ReleaseScene();
            ReleaseDevice();
            ReleasePrimary();
            ReleaseDirect3D();

            PostQuitMessage(0);
            return 0L;
    }

    return DefWindowProc(hwnd, msg, wParam, lParam);
}


WinMain Function
int PASCAL
WinMain(HINSTANCE hInstance,
        HINSTANCE hPrevInstance,
        LPSTR     lpszCommandLine,
        int       cmdShow)
{
    WNDCLASS wndClass;
    HWND     hwnd;
    MSG      msg;

    USE_PARAM(hPrevInstance);

    // Record the instance handle.

    hAppInstance = hInstance;

    // Very simple command-line processing. We only have one
    // option - debug - so we will just assume that if anything was
    // specified on the command line the user wants debug mode.
    // (In debug mode there is no hardware and all surfaces are
    // explicitly in system memory.)

    if (0 != *lpszCommandLine)
        fDebug = TRUE;

    // Register the window class.

    wndClass.style         = 0;
    wndClass.lpfnWndProc   = WndProc;
    wndClass.cbClsExtra    = 0;
    wndClass.cbWndExtra    = 0;
    wndClass.hInstance     = hInstance;
    wndClass.hIcon         = LoadIcon(hAppInstance,
        MAKEINTRESOURCE(IDI_APPICON));
    wndClass.hCursor       = LoadCursor(NULL, IDC_ARROW);
    wndClass.hbrBackground = GetStockObject(WHITE_BRUSH);
    wndClass.lpszMenuName  = NULL;
    wndClass.lpszClassName = WINDOW_CLASSNAME;

    RegisterClass(&wndClass);

    // Create the main window of the instance.

    hwnd = CreateWindow(WINDOW_CLASSNAME,
                        WINDOW_TITLE,
                        WS_OVERLAPPED | WS_SYSMENU,
                        CW_USEDEFAULT, CW_USEDEFAULT,
                        WINDOW_WIDTH, WINDOW_HEIGHT,
                        NULL,
                        NULL,
                        hInstance,
                        NULL);

    ShowWindow(hwnd, cmdShow);
    UpdateWindow(hwnd);

    // The main message dispatch loop.

    // NOTE: For simplicity we handle the message loop with a
    // simple PeekMessage scheme. This might not be the best
    // mechanism for a real application (a separate render worker
    // thread might be better).

    while (TRUE)
    {
        if (PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
        {
            // Message pending. If it's QUIT then exit the message
            // loop. Otherwise, process the message.

            if (WM_QUIT == msg.message)
            {
                break;
            }
            else
            {
                TranslateMessage(&msg);
                DispatchMessage(&msg);
            }
        }
        else
        {
            // Animate the scene.

            OnIdle(hwnd);
        }
    }

    return msg.wParam;
}


The Geometry Pipeline

When you design a 3-D application, you define the world in any units you find convenient, from microns to parsecs. Your application passes a description of that world to Direct3D. This description includes the sizes and relative positions of all of the objects in your world and the position and orientation of the viewer. Direct3D transforms this description into a series of pixels on the screen. This process—the transformation of the geometry you supply into a two-dimensional image—is the geometry pipeline, sometimes called the transformation pipeline.

This section provides a Direct3D-centered approach to discussing the geometry pipeline. The following topics introduce key concepts and make parallels from those concepts to their counterparts in the Direct3D API:

  • Overview of the Pipeline
  • The World Transformation
  • The View Transformation
  • The Projection Transformation
  • Viewports and Clipping
  • The Rasterizer


Overview of the Pipeline

The part of Direct3D that pushes geometry through the geometry pipeline is the transformation engine. It locates the model and viewer in the world, projects vertices for display on the screen, and clips vertices to the viewport. (The transformation engine also performs lighting computations to determine diffuse and specular components at each vertex. For more information, see Lighting and Materials.)

The geometry pipeline takes vertices as input. The transformation engine applies three transformations to the vertices (the world, view, and projection transformations), clips the result, and passes everything on to the rasterizer. The sequence of steps looks like this:

At the head of the pipeline, no transformations have been applied, so all of a model's vertices are declared relative to a local coordinate system (this is a local origin and an orientation). This orientation of coordinates is often referred to as model space, and individual coordinates are called model coordinates.

The first stage of the geometry pipeline transforms a model's vertices from their local coordinate system to a coordinate system that is used by all the objects in a scene. The process of reorienting the vertices is called the world transformation. This new orientation is commonly referred to as world space, and each vertex in world space is declared using world coordinates. This transformation is discussed in The World Transformation.

In the next stage, the vertices that describe your 3-D world are oriented with respect to a camera. That is, your application chooses a point-of-view for the scene, and world space coordinates are relocated and rotated around the camera's view, turning world space into camera space. This is the view transformation. For more information, see The View Transformation.

The next stage is the projection transformation. In this part of the pipeline, objects are usually scaled with relation to their distance from the viewer in order to give the illusion of depth to a scene; close objects are made to appear larger than distant objects, and so on. This transformation is discussed in The Projection Transformation. For simplicity, this documentation refers to the space in which vertices exist after the projection transformation as projection space. (Some graphics books might refer to projection space as "post-perspective homogeneous space.") Note that not all projection transformations scale the size of objects in a scene. A projection such as this is sometimes called an affine or orthogonal projection.

In the final part of the pipeline, any vertices that will not be visible on the screen are removed, so that the rasterizer doesn't take the time to calculate the colors and shading for something that will never be seen. This process is called clipping, and is discussed in Viewports and Clipping. After clipping, the remaining vertices are scaled according to the viewport parameters and converted into screen coordinates. The resulting vertices—seen on the screen when the scene is rasterized—exist in screen space.


The World Transformation

The discussion of the world transformation introduces basic concepts and provides details on how to set up a world transformation matrix in a Direct3D application. This information is organized into the following topics:

  • What Is the World Transformation?
  • Setting Up a World Matrix


What Is the World Transformation?

The world transformation changes coordinates from model space, where vertices are defined relative to a model's local origin, to world space, where vertices are defined relative to an origin common to all of the objects in a scene. In essence, the world transformation places a model into the world; hence its name. The following illustration provides a graphical representation of the relationship between the world coordinate system and a model's local coordinate system:

The world transformation can include any combination of translations, rotations, and scalings. For a discussion of the mathematics of transformations, see 3-D Transformations.


Setting Up a World Matrix

Like any other transformation, you create the world transformation by concatenating a series of transformation matrices into a single matrix that contains the sum total of their effects. In the simplest case, when a model is at the world origin and its local coordinate axes are oriented the same as world space, the world matrix is the identity matrix. More commonly, the world matrix is a combination of a translation into world space, and possibly one or more rotations to "turn" the model as needed.

The following example, from a fictitious 3-D model class, uses the helper functions in the D3dutil.cpp and D3dmath.cpp files (included with the DirectX SDK) to create a world matrix that includes three rotations to orient a model and a translation to relocate it relative to its position in world space.

/*
 * For the purposes of this example, the following variables
 * assumed to be valid and initialized.
 *
 * The m_vPos variable is a D3DVECTOR that contains the model's
 * location in world coordinates.
 *
 * The m_fPitch, m_fYaw, and m_fRoll variables are D3DVALUEs that
 * contain the model's orientation in terms of pitch, yaw, and roll
 * angles (in radians).
 */

D3DMATRIX C3DModel::MakeWorldMatrix(void)
{
    D3DMATRIX matWorld, // World matrix being constructed.
              matTemp,  // Temp matrix for rotations.
              matRot;   // Final rotation matrix (applied to matWorld).

    // Using the right-to-left order of matrix concatenation,
    // apply the translation to the object's world position
    // before applying the rotations.
    D3DUtil_SetTranslateMatrix(matWorld, m_vPos);
    D3DUtil_SetIdentityMatrix(matRot);

    //
    // Now, apply the orientation variables into the
    // world matrix
    //
    if(m_fPitch || m_fYaw || m_fRoll)
    {
        // Produce and combine the rotation matrices.
        D3DUtil_SetRotateXMatrix(matTemp, m_fPitch);    // pitch
        D3DMath_MatrixMultiply(matRot,matRot,matTemp);
        D3DUtil_SetRotateYMatrix(matTemp, m_fYaw);      // yaw
        D3DMath_MatrixMultiply(matRot,matRot,matTemp);
        D3DUtil_SetRotateZMatrix(matTemp, m_fRoll);     // roll
        D3DMath_MatrixMultiply(matRot,matRot,matTemp);

        // Apply the rotation matrices to complete the world matrix.
        D3DMath_MatrixMultiply(matWorld, matWorld, matRot);
    }
    return (matWorld);
}

After you prepare the world transformation matrix, call the IDirect3DDevice3::SetTransform method to set it, specifying the D3DTRANSFORMSTATE_WORLD flag in the first parameter. For more information, see Setting Transformations.

Performance Optimization Direct3D uses the world and view matrices that you set through IDirect3DDevice3::SetTransform to configure several of its internal data structures. Each time you set a new world or view matrix, the system recalculates the associated internal structures. Setting these matrices frequently—for example, thousands of times per frame—is computationally expensive. You can minimize the number of required calculations by concatenating your world and view matrices into a proverbial "world-view" matrix that you set as the world matrix, then set the view matrix to the identity. Keep cached copies of individual world and view matrices that you can modify, concatenate, and reset the world matrix as needed. (For clarity, Direct3D samples rarely employ this optimization.)


The View Transformation

This section introduces the basic concepts of the view transformation and provides details on how you can set up a view transformation matrix in a Direct3D application. This information is organized into the following topics:

  • What Is the View Transformation?
  • Setting Up a View Matrix


What Is the View Transformation?

The view transformation locates the viewer in world space, transforming vertices into camera space. In camera space, the camera (or "viewer") is at the origin, looking in the positive z-direction. (Recall that Direct3D uses a left-handed coordinate system, so z is positive into a scene.) The view matrix relocates the objects in the world around a camera's position (the origin of camera space) and orientation.

There are many ways to create a view matrix. In all cases, the camera has some logical position and orientation in world space that is used as a starting point to create a view matrix that will be applied to the models in a scene. The view matrix translates and rotates objects to place them in camera space, where the camera is at the origin. One way to create a view matrix is to combine a translation matrix with rotation matrices for each axis. In this approach, the following general matrix formula applies:

In this formula, V is the view matrix being created, T is a translation matrix that repositions objects in the world, and Rx through Rz are rotation matrices that rotate objects along the x-, y-, and z-axis. The translation and rotation matrices are based on the camera's logical position and orientation in world space. So, if the camera's logical position in the world <10,20,100>, the aim of the translation matrix is to move objects -10 units along the x-axis, -20 units along the y-axis, and -100 along the z-axis. The rotation matrices in the formula are based on the camera's orientation, in terms of how the much the axes of camera space are rotated out of alignment with world space. For example, if the camera mentioned earlier is pointing straight down, its z-axis is 90 degrees (pi/2 radians) out of alignment with the z-axis of world space, as shown in the following illustration.

The rotation matrices apply rotations of equal, but opposite, magnitude to the models in the scene. The view matrix for this camera would include a rotation of -90 degrees around the x-axis. The rotation matrix is combined with the translation matrix to create a view matrix that adjusts the position and orientation of the objects in the scene so that their top is facing toward the camera, giving the appearance that the camera is above the model.

Another approach involves creating the composite view matrix directly. (The D3DUTIL_SetViewMatrix helper function in the D3dutil.cpp source file uses this technique). This approach uses the camera's world space position and a "look-at point" within the scene to derive vectors that describe the orientation of the camera space coordinate axes. The camera position is subtracted from the look-at point to produce a vector for the camera's direction vector (vector n). Then the cross product of the vector n and the y-axis of world space is taken and normalized to produce a "right" vector (vector u). Next, the cross product of the vectors u and n is taken to determine an "up" vector (vector v). The right (u), up (v), and view-direction (n) vectors describe the orientation of the coordinate axes for camera space in terms of world space. The x, y, and z translation factors are computed by taking the negative of the dot product between the camera position and the u, v, and n vectors.

These values are put into the following matrix to produce the view matrix:

In this matrix, u, v, and n are the up, right and view-direction vectors, and c is the camera's world space position. This matrix contains all the elements needed to translate and rotate vertices from world space to camera space. After creating this matrix, you can also apply a matrix for rotation around the z-axis to allow the camera to roll.

For information on implementing this technique, see Setting Up a View Matrix.


Setting Up a View Matrix

The D3DUtil_SetViewMatrix helper function, from the D3dutil.cpp source file that is included with this SDK, creates a view matrix based on the camera location and a look-at point passed to it. It uses the Magnitude, CrossProduct, and DotProduct D3D_OVERLOADS helper functions.

HRESULT D3DUtil_SetViewMatrix( D3DMATRIX& mat, D3DVECTOR& vFrom,
                               D3DVECTOR& vAt, D3DVECTOR& vWorldUp )
{
    // Get the z basis vector, which points straight ahead. This is the
    // difference from the eyepoint to the lookat point.
    D3DVECTOR vView = vAt - vFrom;

    FLOAT fLength = Magnitude( vView );
    if( fLength < 1e-6f )
        return E_INVALIDARG;

    // Normalize the z basis vector
    vView /= fLength;

    // Get the dot product, and calculate the projection of the z basis
    // vector onto the up vector. The projection is the y basis vector.
    FLOAT fDotProduct = DotProduct( vWorldUp, vView );

    D3DVECTOR vUp = vWorldUp - fDotProduct * vView;

    // If this vector has near-zero length because the input specified a
    // bogus up vector, let's try a default up vector
    if( 1e-6f > ( fLength = Magnitude( vUp ) ) )
    {
        vUp = D3DVECTOR( 0.0f, 1.0f, 0.0f ) - vView.y * vView;

        // If we still have near-zero length, resort to a different axis.
        if( 1e-6f > ( fLength = Magnitude( vUp ) ) )
        {
            vUp = D3DVECTOR( 0.0f, 0.0f, 1.0f ) - vView.z * vView;

            if( 1e-6f > ( fLength = Magnitude( vUp ) ) )
                return E_INVALIDARG;
        }
    }

    // Normalize the y basis vector
    vUp /= fLength;

    // The x basis vector is found simply with the cross product of the y
    // and z basis vectors
    D3DVECTOR vRight = CrossProduct( vUp, vView );

    // Start building the matrix. The first three rows contains the basis
    // vectors used to rotate the view to point at the lookat point
    D3DUtil_SetIdentityMatrix( mat );
    mat._11 = vRight.x;    mat._12 = vUp.x;    mat._13 = vView.x;
    mat._21 = vRight.y;    mat._22 = vUp.y;    mat._23 = vView.y;
    mat._31 = vRight.z;    mat._32 = vUp.z;    mat._33 = vView.z;

    // Do the translation values (rotations are still about the eyepoint)
    mat._41 = - DotProduct( vFrom, vRight );
    mat._42 = - DotProduct( vFrom, vUp );
    mat._43 = - DotProduct( vFrom, vView );

    return S_OK;
}

As with the world transformation, you call the IDirect3DDevice3::SetTransform method to set the view transformation, specifying the D3DTRANSFORMSTATE_VIEW flag in the first parameter. See Setting Transformations, for more information.

Performance Optimization Direct3D uses the world and view matrices that you set through IDirect3DDevice3::SetTransform to configure several of its internal data structures. Each time you set a new world or view matrix, the system recalculates the associated internal structures. Setting these matrices frequently—for example, 20000 times per frame—is computationally expensive. You can minimize the number of required calculations by concatenating your world and view matrices into a proverbial "world-view" matrix that you set as the world matrix, then set the view matrix to the identity. Keep cached copies of individual world and view matrices that you can modify, concatenate, and reset the world matrix as needed. (For clarity, Direct3D samples rarely employ this optimization.)


The Projection Transformation

You can think of the projection transformation as controlling the camera's internals; it is analogous to choosing a lens for the camera. This is the most complicated of the three transformation types. This discussion of the projection transformation is organized into the following topics:

  • The Viewing Frustum
  • What Is the Projection Transformation?
  • Setting Up a Projection Matrix
  • A "W-Friendly" Projection Matrix


The Viewing Frustum

A viewing frustum is 3-D volume in a scene positioned relative to the viewport's camera. The shape of the volume affects how models are projected from camera space onto the screen. The most common type of projection, a perspective projection, is responsible for making objects near the camera appear bigger than objects in the distance. For perspective viewing, the viewing frustum can be visualized as a pyramid, with the camera positioned at the tip. This pyramid is intersected by a front and back clipping plane. The volume within the pyramid between the front and back clipping planes is the viewing frustum. Objects are visible only when they are in this volume.

If you imagine that you are standing in a dark room and looking out through a square window, you are visualizing a viewing frustum. In this analogy, the near-clipping plane is the window, and the back clipping plane is whatever finally interrupts your view—the skyscraper across the street, the mountains in the distance, or nothing at all. You can see everything inside the truncated pyramid that starts at the window and ends with whatever interrupts your view, and you can see nothing else.

The viewing frustum is defined by fov (field of view) and by the distances of the front and back clipping planes, specified in z-coordinates.

In this illustration, the variable D is the distance from the camera to the origin of the space that was defined in the last part of the geometry pipeline—the viewing transformation. This is the space around which you arrange the limits of your viewing frustum. For information about how this D variable is used to build the projection matrix, see What Is the Projection Transformation?


What Is the Projection Transformation?

The projection matrix is typically a scale and perspective projection. The projection transformation converts the viewing frustum into a cuboid shape. Because the near end of the viewing frustum is smaller than the far end, this has the effect of expanding objects that are near to the camera; this is how perspective is applied to the scene.

In The Viewing Frustum, the distance between the camera required by the projection transformation and the origin of the space defined by the viewing transformation is defined as D. A beginning for a matrix defining the perspective projection might use this D variable like this:

The viewing matrix puts the camera at the origin of the scene. Since the projection matrix needs to have the camera at (0, 0, -D), it translates the vector by -D in the z-direction, by using the following matrix:

Multiplying these two matrices gives the following composite matrix:

The following illustration shows how the perspective transformation converts a viewing frustum into a new coordinate space. Notice that the frustum becomes cuboid and also that the origin moves from the upper-right corner of the scene to the center.

In the perspective transformation, the limits of the x- and y-directions are -1 and 1. The limits of the z-direction are 0 for the front plane and 1 for the back plane.

This matrix translates and scales objects based on a specified distance from the camera to the near clipping plane, but it doesn't consider the field-of-view (fov), and the z-values that it produces for objects in the distance can be nearly identical, making depth comparisons difficult. The following matrix addresses these issues, and adjusts vertices to account for the aspect ratio of the viewport, making it a good choice for the perspective projection:

In this matrix, Zn is the z-value of the near clipping plane. The variables w, h, and Q have the following meanings (noting that fovw and fovh represent the viewport's horizontal and vertical fields-of-view, in radians):

For your application, using field-of-view angles to define the x and y scaling coefficients might not be as convenient as using the viewport's horizontal and vertical dimensions (in camera space). As the math works-out, the following two formulas for w and h use the viewport's dimensions, and are equivalent to the preceding formulas:

In these formulas, Zn represents the position of the near clipping plane, and the Vw and Vh variables represent the width and height of the viewport, in camera space. The two dimensions correspond directly to the dwWidth and dwHeight members of the D3DVIEWPORT2 structure.

Whatever formula you decide to use, it's important that you set Zn to as large a value as you can, as z-values extremely close to the camera don't vary by much, making depth comparisons using 16-bit z-buffers tricky. In Direct3D, the (3,4) element of the projection matrix cannot be a negative number.

As with the world and view transformations, you call the IDirect3DDevice3::SetTransform method to set the projection transformation; for more information, see Setting Transformations.


Setting Up a Projection Matrix

The following ProjectionMatrix sample function takes four input parameters that set the front and back clipping planes, as well as the horizontal and vertical field of view angles. (This code parallels the approach discussed in What Is the Projection Transformation?.) The fields-of-view should be less than pi radians.

D3DMATRIX
ProjectionMatrix(const float near_plane,
                             // distance to near clipping plane
                 const float far_plane,
                             // distance to far clipping plane
                 const float fov_horiz,
                             // horizontal field of view angle, in radians
                 const float fov_vert)
                             // vertical field of view angle, in radians
{
    float    h, w, Q;

    w = (float)cot(fov_horiz*0.5);
    h = (float)cot(fov_vert*0.5);
    Q = far_plane/(far_plane - near_plane);

    D3DMATRIX ret = ZeroMatrix();
    ret(0, 0) = w;
    ret(1, 1) = h;
    ret(2, 2) = Q;
    ret(3, 2) = -Q*near_plane;
    ret(2, 3) = 1;
    return ret;
}   // end of ProjectionMatrix()

When you have created the matrix, you need set it in a call to the IDirect3DDevice3::SetTransform method, specifying D3DTRANSFORMSTATE_PROJECTION in the first parameter. For details, see Setting Transformations.


A W-Friendly Projection Matrix

Direct3D Immediate Mode can utilize the W component of a vertex that has been transformed by the world, view, and projection matrices to perform depth-based calculations in depth-buffer or fog effects. Computations such as these require that your projection matrix normalize W to be equivalent to world-space Z. In short, if your projection matrix includes a (3,4) coefficient that is not 1, you must scale all the coefficients by the inverse of the (3,4) coefficient to make a proper matrix. If you don't provide a compliant matrix, fog effects and depth buffering will not be applied correctly. (The projection matrix recommended in What Is the Projection Transformation? is compliant with w-based calculations.)

The following illustration shows a non-compliant projection matrix, and the same matrix scaled so that eye-relative fog will be enabled.

In the preceding matrices, all variables are assumed to be nonzero. For more information about eye-relative fog, see Eye-Relative vs. Z-based Depth. For information about w-based depth buffering, see What Are Depth Buffers?

Note: Direct3D uses the currently set projection matrix in its w-based depth calculations. As a result, applications must set a compliant projection matrix to receive the desired w-based features, even if they do not use the Direct3D transformation pipeline.


Viewports and Clipping

This section discusses the last stage of the geometry pipeline: clipping. The discussion is organized into the following topics:

  • What Is a Viewport?
  • Clipping Volumes
  • Viewport Scaling
  • Using Viewports

Direct3D implements clipping by way of a COM object representing a viewport's functionality and exposing interfaces to allow you to manipulate the object. The IDirect3DViewport3 interface is the newest interface to the viewport object.


What Is a Viewport?

Conceptually, a viewport is a 2-D rectangle into which a three dimensional scene is projected. (In Direct3D, the rectangle exists as coordinates within a DirectDraw surface that the system uses as a rendering target.) The projection transformation converts vertices into the coordinate system used for the viewport.

You use a viewport in Direct3D to specify the following features in your application:

  • The screen-space viewport to which the rendering will be confined.
  • The background material. The viewport can be cleared to this material color.
  • The background depth buffer used to initialize the z-buffer before rendering the scene.
  • The post-transformation clip volume, the contents of which will be mapped into the viewport. (This is also known as the "window" in a "window-to-viewport transformation," in standard computer-graphics terminology.)

The clipping volume is the area that defines the part of your scene that will appear on the render target surface. If the viewport you choose is small enough so that parts of your scene will not be visible, you should clip the parts that will be off of the screen so that the system will avoid the overhead of rendering those parts of the scene. For more information, see Clipping Volumes.


Clipping Volumes

The following topics discuss the role and effects of the viewport clipping volume, as well as some considerations that might apply to you, depending on the type of vertices your application uses:

  • About Clipping Volumes
  • Considerations for Various Vertex Types


About Clipping Volumes

You define a clipping volume inside the coordinate system of the viewport. The best way to define a clipping volume in Direct3D is by using the D3DVIEWPORT2 structure—the structure that is specified by the methods in IDirect3DViewport3. (Another way is by using the D3DVIEWPORT structure. The D3DVIEWPORT2 structure enables a better clip-volume definition than D3DVIEWPORT and is recommended for all DirectX 5.0 and newer applications.)

The dvClipX, dvClipY, dvClipWidth, and dvClipHeight members of the D3DVIEWPORT2 structure specify the region inside of which vertices will be visible. This region corresponds to the destination rectangle, specified by the dwX, dwY, dwWidth, and dwHeight members of D3DVIEWPORT2.

Direct3D uses the values you set in the D3DVIEWPORT2 structure to construct a matrix that it internally applies to all vertices before performing clipping tests. The matrix looks like this:

In the preceding matrix all variables are taken directly from the D3DVIEWPORT2 structure: Cx and Cy are the values in the dvClipX and dvClipY members, Cw and Ch are values in dvClipWidth and dvClipHeight, and the Zmin and Zmax variables are values taken from the dvMinZ and dvMaxZ members. The matrix effectively scales vertices according to the proportions of the clipping volume you define and translates them to position them around the volume's origin.

The values produced by the clipping matrix are tested by using the following formulas, and any vertices that fail the tests are clipped:

In the preceding formulas, Xc, Yc, Zc, and Wc represent the vertex coordinates after the clipping matrix is applied.

In most cases, you will define a clipping volume that extends from -1.0 to 1.0 in the x- and y-directions, and 0.0 to 1.0 in the z-direction, and doesn't scale vertices. The significant D3DVIEWPORT2 structure settings for such a volume are as follows:

dvClipX      = -1.0;
dvClipY      =  1.0;
dvClipWidth  =  2.0;
dvClipHeight =  2.0;
dvMinZ       =  0.0;
dvMaxZ       =  1.0;

It is important that neither dvClipWidth nor dvClipHeight be zero. Also, dvMinZ cannot equal dvMaxZ.

This clipping volume corresponds to the destination rectangle, as shown in the following illustration.

The values you specify for the dwX, dwY, dwWidth, and dwHeight members of the D3DVIEWPORT2 structure are screen coordinates relative to the upper-left corner of the render target surface.


Considerations for Various Vertex Types

If you are using D3DVERTEX or D3DLVERTEX vertices—that is, if Direct3D is performing the transformations—you might want to set the last six members of this structure as follows:

    dvClipX = -1.0f;
    dvClipY =  1.0f;
    dvClipWidth = 2.0f;
    dvClipHeight = 2.0f;
    dvMinZ = 0.0f;
    dvMaxZ = 1.0f;

Note that setting the viewport values as shown in the preceding example doesn't account for the viewport aspect ratio. Although it's not uncommon to use viewport parameters for aspect ratio scaling, the projection matrix is a more accurate, more flexible, and cleaner platform for the task. For more information about accounting for the viewport aspect ratio in the projection matrix, see What Is the Projection Transformation?

If you are using D3DTLVERTEX vertices—that is, if your application is calculating the transformations and lighting—you can set up the clip space however is best for your application. If the x- and y-coordinates in your data already match pixels, you could set the last six members of D3DVIEWPORT2 as follows:

    dvClipX = 0;
    dvClipY = 0;
    dvClipWidth = dwWidth;
    dvClipHeight = dwHeight;
    dvMinZ = 0.0f;
    dvMaxZ = 1.0f;

You can use the rectangle defined by the dwX, dwY, dwWidth, and dwHeight members of the D3DVIEWPORT2 structure to clip your geometry. Although the clipping members (their names begin with "dvClip") in D3DVIEWPORT2 are ignored when you use D3DTLVERTEX vertices, the system still validates them, so you must provide reasonable values for them. If you don't need this clipping, you can specify D3DDP_DONOTCLIP in your calls to IDirect3DDevice3::DrawPrimitive or IDirect3DDevice3::DrawIndexedPrimitive.


Viewport Scaling

The dimensions used in the dwX, dwY, dwWidth, and dwHeight members of the D3DVIEWPORT2 structure for a viewport define the location and dimensions of the viewport on the render target surface. These values are in screen coordinates, relative to the upper-left corner of the surface.

Direct3D uses the viewport location and dimensions to scale the vertices to fit a rendered scene into the appropriate location on the target surface. Internally, Direct3D inserts these values into a matrix that is applied to each vertex:

This matrix simply scales vertices according to the viewport dimensions and translates them to the appropriate location on the render target surface. (The matrix also "flips" the y-coordinate to reflect a screen origin at the top-left corner with y increasing downward.) After this matrix is applied, vertices are still homogeneous—that is, they still exist as [x,y,z,w] vertices—and they must be converted to non-homogeneous coordinates before being sent to the rasterizer. This is performed by way of simple division, as discussed in The Rasterizer.


Using Viewports

This section provides details about creating, working with, and deleting viewports. Information is divided into the following topics:

  • Preparing to Use a Viewport
  • Creating a Viewport
  • Adding a Viewport to a Device
  • Setting the Viewport Clipping Volume
  • Deleting a Viewport
  • Clearing a Viewport
  • Manually Transforming Vertices


Preparing to Use a Viewport

To set up a viewport in Direct3D

  1. Create a viewport object.

    Creating the viewport causes Direct3D to allocate internal data structures that contain the viewport's properties. For more information, see Creating a Viewport.

  2. Add the viewport to a device.

    This creates an association between a viewport and a device; the device adds the viewport to an internal list of viewports. You can switch the current viewport by calling the IDirect3DDevice3::NextViewport method for that device. For more information about this step, see Adding a Viewport to a Device.

  3. Set the viewport properties.

    After adding the viewport to a device, you can set its properties. The viewport properties control how Direct3D clips objects from a scene and determine the aspect ratio of the scene rendered to the target surface.

When you're finished working with the viewport, you can delete it from the device's viewport list. For more information, see Deleting a Viewport.


Creating a Viewport

Call the IDirect3D3::CreateViewport method to create the viewport object. For this you need a valid LPDIRECT3D3 pointer, shown in the following example as lpD3D2:

    HRESULT hr;

    hr = lpD3D3->CreateViewport(&lpD3DViewport3, NULL);

    if(FAILED(hr))
        return hr;
    else
    {
      // Add the viewport to a device.
    }

After creating a viewport, you can add it to an existing device. For more information, see Adding a Viewport to a Device.


Adding a Viewport to a Device

After creating a viewport, you can call the IDirect3DDevice3::AddViewport method to add it to the device's viewport list. The following example shows what this call might look like:

    HRESULT hr;

    // lpD3DDevice3 is a valid pointer to a Direct3D
    // device object.
    hr = lpD3DDevice3->AddViewport(lpD3DViewport3);

    if(FAILED(hr))
        return hr;
    else
    {
      // Set the viewport properties.
    }

Once you've added the viewport to the device, you can set the viewport clipping volume. For more information, see Setting the Viewport Clipping Volume.


Setting the Viewport Clipping Volume

After you add a viewport to a device, you can set the viewport's clipping volume. To do this, you initialize and set clipping values for the clipping volume and for the render target surface. Viewports are commonly set up to render to the full surface and to compensate for the aspect ratio. You could use the following settings for the members of the D3DVIEWPORT2 structure to achieve this:

    memset(&viewData, 0, sizeof(D3DVIEWPORT2));
    viewData.dwSize = sizeof(D3DVIEWPORT2);
    viewData.dwX = 0;
    viewData.dwY = 0;
    viewData.dwWidth  = width;
    viewData.dwHeight = height;
    viewData.dvClipX  = -1.0f;
    viewData.dvClipY  =  1.0;
    viewData.dvClipWidth  = 2.0f;
    viewData.dvClipHeight = 2.0f;
    viewData.dvMinZ = 0.0f;
    viewData.dvMaxZ = 1.0f;

After setting values in the D3DVIEWPORT2 structure, you apply the structure to the viewport object by calling its IDirect3DViewport3::SetViewport2 method. The following examples shows what this call might look like:

    HRESULT hr;

    hr = lpD3DViewport3->SetViewport2(&viewData);
    if(FAILED(hr))
        return hr;

If the call succeeds, you have a working viewport. If you need to make changes to the viewport values, simply update the values in the D3DVIEWPORT2 structure and call SetViewport2 again.

The IDirect3DViewport3 interface has two ways of specifying a viewport clipping volume. For more information, see Clipping Volumes.


Deleting a Viewport

When you no longer need to use a viewport with a given device, first delete any lights and materials associated with it and then remove it from the device's viewport list by calling the IDirect3DDevice3::DeleteViewport method. DeleteViewport accepts the address of an IDirect3DViewport3 interface as its only parameter. (If you're using execute buffers, you will be calling the IDirect3DDevice::DeleteViewport method, which accepts the address of an IDirect3DViewport interface.)

Deleting a viewport only removes it from a device's viewport list; it doesn't free the resources allocated for the viewport object itself. To completely get rid of a viewport, you must release it by calling its IUnknown::Release method.


Clearing a Viewport

Clearing a viewport resets the contents of the viewport rectangle on the render target surface as well as the rectangle in the depth and stencil buffer surfaces (if specified). Typically, you will clear the viewport before rendering a new frame to ensure that graphics and other data is ready to accept new rendered objects without displaying artifacts.

The IDirect3DViewport3 interface offers the IDirect3DViewport3::Clear and IDirect3DViewport3::Clear2 methods that provide various ways to clear the viewport. Both of the clearing methods accept one or more rectangles that define the area or areas on the surfaces being cleared. In cases where the scene being rendered includes motion throughout the entire viewport rectangle—in a first-person perspective game, perhaps—you might want to clear the entire viewport each frame. In this situation, you would set the dwCount parameter to 1, and the lpRects parameter to the address of a single rectangle that covers the entire viewport area.

Note DirectX 5.0 allowed background materials to have associated textures, making it possible to clear the viewport to a texture, rather than a simple color. This feature was little used, and not particularly efficient. Interfaces added for DirectX 6.0 do not accept texture handles, meaning that you can no longer clear the viewport to a texture. Rather, applications must now draw backgrounds manually. As a result, there is rarely a need to clear the viewport on the render target surface. So long as your application clears the depth buffer, all pixels on the render target surface will be overwritten anyway.

In some situations, you might only be rendering to small portions of the render target and depth buffer surfaces. The clear methods also allow you to clear multiple areas of your surfaces in a single call. Do this by setting the dwCount parameter to the number of rectangles you want cleared, and specify the address of the first rectangle in an array of rectangles in the lpRects parameter.

The clearing methods have differing features and behavior. The IDirect3DViewport3::Clear method can clear the viewport using the color of the background material if you specify the D3DCLEAR_TARGET flag in the dwFlags parameter, and it can clear the z-buffer to the "deepest" value (1.0) if you include the D3DCLEAR_ZBUFFER flag. The method requires that you set a background material by calling the IDirect3DViewport3::SetBackground method. The Clear method is incapable of clearing stencil buffers.

The IDirect3DViewport3::Clear2 method was introduced to provide more flexibility and ease-of-use than the Clear method, and to provide support for clearing stencil bits within a depth buffer. Clear2 accepts the same two flags in the dwFlags parameter as its ancestor, but with slightly different results, and it adds one new flag to support stencils. If you include the D3DCLEAR_TARGET flag, the method clears the viewport using an arbitrary RGBA color that you provide in the dwColor parameter (not the material color). If you include the D3DCLEAR_ZBUFFER flag, the method clears the depth buffer to an arbitrary depth you specify in dvZ: 0.0 is the closest distance, and 1.0 is the farthest. Including the new D3DCLEAR_STENCIL flag causes the method to reset the stencil bits to the value you provide in the dwStencil parameter. You can use integers that range from 0 to 2n-1, where n is the stencil buffer bit depth.


Manually Transforming Vertices

You can use three different kinds of vertices in your Direct3D application. Read Vertex Formats for more details on the vertex formats:

Untransformed, unlit vertices
Vertices that your application doesn't light or transform. Applications that neither transform nor light vertices before rendering a scene can use D3DVERTEX vertices (or an equivalent flexible vertex format). Although you specify lighting parameters and transformation matrices, Direct3D does the math.
Untransformed, lit vertices
Vertices that your application lights but does not transform. Applications that use customized lighting effects might use D3DLVERTEX vertices (or an equivalent flexible vertex format).
Transformed, lit, vertices
Vertices that your application both lights and transforms. Applications that transform and light vertices on their own might use D3DTLVERTEX vertices (or an equivalent flexible vertex format). These vertices skip the transformations in the geometry pipeline altogether but they can be clipped by the system if needed. If your application clips vertices itself, you can get the best performance by specifying the D3DDP_DONOTCLIP flag when calling a rendering method. If you want Direct3D to clip vertices, omit the D3DDP_DONOTCLIP flag. Note that if you request Direct3D clipping on transformed and lit vertices, the system back-transforms them to camera space for clipping, then transforms them back to screen space, incurring processing overhead.

Direct3D includes two ways to change from simple to complex vertex types: the TransformVertices method that has been available since Direct3D was created, and vertex buffers, introduced in DirectX 6.0. The latter is the most efficient method, as vertex buffers are optimized to exploit processor specific features.

Using TransformVertices

You can use the IDirect3DViewport3::TransformVertices method to transform either the D3DVERTEX and D3DLVERTEX vertex types into screen coordinates, which are represented by D3DTLVERTEX vertices.

TransformVertices uses the current matrix (that you set with a call to the IDirect3DDevice3::SetTransform method) to perform the transformation. You might call TransformVertices if you want to transform but not necessarily render a set of vertices; for example, you might provide two vertices that define the opposite corners of a bounding box. If both vertices are clipped, you could forgo any further processing for that model.

The TransformVertices does not perform lighting. If you pass D3DVERTEX vertices, the resulting D3DTLVERTEX vertices will not have valid diffuse and specular components. Likewise, if you pass D3DLVERTEX vertices, the diffuse and specular components you provide with each vertex will be unchanged after TransformVertices returns.

Although managing the transformations yourself can be faster than calling the IDirect3DViewport3::TransformVertices method, implementing your own transformation engine can be time consuming, and TransformVertices is reasonably fast. If you need more control over the geometry pipeline than you get when using D3DVERTEX or D3DLVERTEX vertices, but you don't want to develop your own transformation engine, calling TransformVertices is a good compromise.

Note: Applications often use TransformVertices to perform visibility checking, because the call returns clipping information in the associated D3DTRANSFORMDATA structure. Although accurate, visibility checking is best performed by calling the IDirect3DDevice3::ComputeSphereVisibility method, which was specially designed and optimized for this purpose.

Using Vertex Buffers

Vertex buffers are objects used to efficiently contain and process batches of vertices for rapid rendering. Vertex buffers offer the IDirect3DVertexBuffer::ProcessVertices method to perform vertex transformations for you; this is usually much faster than the TransformVertices method. The ProcessVertices method accepts only untransformed vertices, and can optionally light and clip vertices as well. Lighting is performed at the time you call ProcessVertices, but clipping is actually performed at render time.

After processing the vertices, you can use special rendering methods to render the vertices, or you can access them directly by locking the vertex buffer memory. For more information about using vertex buffers, see Vertex Buffers.


The Rasterizer

After passing through the Direct3D geometry pipeline, vertices have been transformed, clipped, and scaled to fit in the viewport render-target surface, making them almost ready to be sent to the rasterizer to be painted on the screen. However, the vertices are still homogeneous, and the rasterizer expects to receive vertices in terms of their x-, y-, and z-locations, as well as the reciprocal-of-homogeneous-w (RHW). Direct3D converts the homogeneous vertices to non-homogeneous vertices by dividing the x-, y-, and z-coordinates by the w-coordinate, and produces an RHW value by inverting the w-coordinate, as in the following formulas:

The resulting values are passed to the rasterizer for display. The rasterizer uses the x- and y-coordinates as the screen coordinates for the vertex, and uses the z-coordinate for depth comparisons in the depth buffer, when z-buffering is enabled. The RHW value is used in multiple ways: for calculating fog, for performing perspective-correct texture mapping, and for w-buffering (an alternate form of depth buffering).


Lighting and Materials

This section describes illumination in Direct3D Immediate Mode scenes, using ambient light, light objects, and materials. The following topics are discussed:

  • Introduction to Lighting and Materials

    Describes, in general terms, the roles of lights and materials in a Direct3D Immediate Mode scene.

  • The Direct3D Light Model vs. Nature

    Describes the Direct3D illumination model in more detail, and contrasts it from the behavior of light in the natural world.

  • Color Values for Lights and Materials

    Describes the RGBA color values used with both lights and materials in Direct3D Immediate Mode.

  • Direct Light vs. Ambient Light

    Compares and contrasts the roles of true light sources and ambient light levels.

  • Enabling and Disabling the Lighting Engine

    Describes how to enable or disable the Direct3D lighting engine.

  • Lights

    Describes Direct3D light objects and provides information on how to use them in a scene.

  • Materials

    Describes materials in Direct3D Immediate Mode and provides information about how to use them in a scene.

  • The Mathematics of Direct3D Lighting

    Provides details about the math behind the Direct3D light model.


Introduction to Lighting and Materials

When lighting is enabled, as Direct3D rasterizes a scene in the final stage of rendering, it determines the color of each rendered pixel based on a combination of the current material color (and the texels in an associated texture map), the diffuse and specular colors at the vertex, if specified, as well as the color and intensity of light produced by light objects in the scene or the scene's ambient light level. When you use Direct3D lighting and materials, you are allowing Direct3D to handle the details of illumination for you, but advanced users can perform lighting on their own if necessary.

How you work with lighting and materials makes a huge difference in the appearance of the rendered scene. Materials define how light reflects off of a surface. Direct light and ambient light levels define the light that is being reflected. You must use materials to render a scene if you are letting Direct3D handle lighting. Lights are not actually required to render a scene, but you'll be hard pressed to see much in a scene rendered without light. At best, rendering an unlit scene will result in a silhouette of the objects in the scene—not enough detail for most purposes.


The Direct3D Light Model vs. Nature

In nature, when light is emitted from a source, it reflects off hundreds (if not thousands or millions) of objects before reaching the viewer's eye. Each time it reflects, parts of the light are absorbed by a surface, parts are scattered in random directions, and the rest goes on to another surface or to the viewer. This process continues until the light attenuates to nothing or a viewer perceives the light—but, who knows how many times the light will bounce? It could be once, a hundred times, or millions of times.

Obviously, the calculations required to perfectly simulate the natural behavior of light are, by far, too time consuming to be used for real-time 3-D graphics. Therefore, with the interest of speed in mind, the Direct3D light model approximates the way light works in the natural world. Direct3D describes light in terms of red, green, and blue components that combine to create a final color. For more information, see Color Values for Lights and Materials. In Direct3D, when light reflects off a surface, the light color interacts mathematically with the surface itself to create the color eventually drawn to the screen. For specific information about the algorithms Direct3D uses, see The Mathematics of Direct3D Lighting.

The Direct3D Immediate Mode light model generalizes light into two types: ambient light and direct light. Each has different attributes, and each interacts with the material of a surface in different ways. Ambient light is light that has been scattered so much that its direction and source are indeterminate: it maintains a low-level of intensity everywhere. The indirect lighting used by photographers is a good example of ambient light. Ambient light in Direct3D, as in nature, has no real direction or source, only a color and intensity. In fact, the ambient light level is completely independent of any objects in a scene that generate light. Ambient light does not contribute to specular reflection.

Direct light is the light generated by an object in a scene; it always has color and intensity, and travels in a specified direction. Direct light interacts with the material of a surface to create specular highlights, and its direction is used as a factor in shading algorithms, including Gouraud shading. When direct light is reflected, it does not contribute to the ambient light level in a scene. The objects in a scene that generate direct light (referred to as "lights" or "light objects") have different characteristics that affect how they illuminate a scene. For more information, see Lights.

Additionally, a polygon's material has properties that affect how that polygon reflects the light it receives. You set a single reflectance trait that describes how the material reflects ambient light, and you set individual traits to determine the material's specular and diffuse reflectance. For more information, see Materials.


Color Values for Lights and Materials

Direct3D Immediate Mode describes color in terms the four components (red, green, blue, and alpha) that combine to make a final color. The D3DCOLORVALUE structure is defined to contain values for each component. Each member is a floating point value that typically ranges from 0.0 to 1.0, inclusive. Although both lights and materials use the same structure to describe color, the values within the structure are used a little differently by each.

Color values for light objects represent the amount of a particular light component it emits. Lights don't use an alpha component, so you only need to think about the red, green, and blue components of the color. You can visualize the three components as the red, green, and blue lenses on a projection television. Each lens might be off (a 0.0 value in the appropriate D3DCOLORVALUE structure member), it might be as bright as possible (a 1.0 value), or some level in between. The colors coming from each lens combine to make the light's final color. A combination like R: 1.0, G: 1.0, B: 1.0 creates a white light, where R: 0.0, G: 0.0, B: 0.0 results in a light that doesn't emit light at all. You can make a light that emits only one component, resulting in a purely red, green, or blue light, or, the light could use combinations to emit colors like yellow or purple. You can even set negative values color component values to create a "dark light" that actually removes light from a scene. Or, you might set the components to some value larger than 1.0 to create an extremely bright light.

With materials, on the other hand, color values represent how much of a given light component is reflected by a surface that uses that material. A material whose color components are R: 1.0, G: 1.0, B: 1.0, A: 1.0 will reflect all the light that comes its way. Likewise, a material with R: 0.0, G: 1.0, B: 0.0, A: 1.0 will reflect all of the green light that is directed at it. Materials have multiple reflectance values to create various types of effects; for more information, see Material Properties.

Color values for ambient light are different than those used for light objects and materials. For more information, see Direct Light vs. Ambient Light.


Direct Light vs. Ambient Light

Although both direct and ambient light illuminate objects in a scene, they are independent of one another, they have very different effects, and they require that you work with them in completely different ways.

Direct light is just that: direct. Direct light always has direction and color, it is always emitted by an object within a scene, and it is a factor for shading algorithms, such as Gouraud shading. Different types of light objects emit direct light in different ways, creating special attenuation effects. You create lights by calling the IDirect3D3::CreateLight method, set their properties with the IDirect3DLight::SetLight method, and add them to a scene by calling the IDirect3DViewport3::AddLight method.

Ambient light is effectively everywhere in a scene. You can think of it as a general level of light that fills an entire scene, regardless of the objects and their locations within that scene. Ambient light, being everywhere, has no position or direction, only color and intensity. Additionally, ambient light is not factored-in for shading algorithms. If you're using the DrawPrimitive architecture to do your rendering, you set the ambient light level with a single call to the IDirect3DDevice3::SetLightState method, specifying D3DLIGHTSTATE_AMBIENT as the dwLightStateType parameter, and the desired RGBA color as the dwLightState parameter. If you're using execute buffers, you must include the D3DOP_STATELIGHT opcode in the execute buffer, as well as the D3DLIGHTSTATE_AMBIENT flag and color value in the accompanying D3DSTATE structure.

Color values for ambient light are interpreted the same way for both the DrawPrimitive and execute buffer architectures. Ambient light color takes the form of an RGBA value, where each component is an integer value from 0 to 255. (This is unlike most color values in Direct3D Immediate Mode. For more information, see Color Values for Lights and Materials.) You can use the RGBA_MAKE macro to generate RGBA values from integers. The red, green, and blue components combine to make the final color of the ambient light. The alpha component controls the transparency of the color. In ramp emulation, ambient light doesn't have color, so the alpha component is used for brightness. When using hardware acceleration or RGB emulation, the alpha component is ignored.


Enabling and Disabling the Lighting Engine

Direct3D normally performs lighting calculations on any vertices that contain a vertex normal. However, you can disable lighting for vertices that include normals by using the D3DDP_DONOTLIGHT flag when you call DrawPrimitive-based rendering methods.

If your application uses vertex buffers, include or omit the D3DVOP_LIGHT flag when calling the IDirect3DVertexBuffer::ProcessVertices method to enable or disable lighting for that vertex buffer.

If the rendering device does not have a material assigned to it, the Direct3D lighting engine is disabled.


Lights

Lights are used to illuminate objects in a scene. This section describes lights and how they are used in Direct3D Immediate Mode. The following topics are discussed:

  • Introduction to Light Objects
  • Light Properties
  • Using Lights


Introduction to Light Objects

Direct3D employs four types of lights: point lights, spotlights, directional lights, and parallel-point lights. You choose the type of light you want when you set the light properties after creating a light object. The illumination properties and the resulting computational overhead varies with each type of light. The following light types, supported in Direct3D, are discussed:

  • Point lights
  • Spotlights
  • Directional lights
  • Parallel-point lights

Do not confuse light objects with the concept of an ambient light level. For more information, see Direct Light vs. Ambient Light, Light Properties and Using Lights.


Point Lights

Point lights have color and position within a scene, but no single direction. They give off light equally in all directions, as shown in the following illustration.

A light bulb would be a good example of a point light. Point lights are affected by attenuation and range, and illuminate a mesh on a vertex-by-vertex basis. During lighting, Direct3D uses the point light's position in world space and the coordinates of the vertex being lit to derive a vector for the direction of the light, and the distance that the light has traveled. Both of these are used (along with the vertex normal) to calculate the contribution of the light to the illumination of the surface.


Spotlights

Spotlights have color, position, and direction in which they emit light. Light emitted from a spotlight is made up of a bright inner cone, and a larger outer cone, with the light intensity diminishing between the two, as shown in the following illustration, along with the related members from the D3DLIGHT2 structure.

Spotlights are affected by falloff, attenuation, and range. These factors, as well as the distance light travels to each vertex, are figured in while computing lighting effects for objects in a scene. Computing all these effects for each vertex makes spotlights the most computationally expensive of all lights in Direct3D Immediate Mode.


Directional Lights

Directional lights have only color and direction, not position. They give off parallel light, meaning that all light generated by it travels through scene in the same direction. You can imagine a directional light as a light source at near infinite distance, such as the sun. Directional lights are not affected by attenuation or range, so the direction and color you specify are the only factors considered when Direct3D calculates vertex colors. Because of the small number of illumination factors, these are the least computationally intensive lights to use.


Parallel-Point lights

Parallel-point lights have only color and position. They create lighting effects similar to point lights but with less overhead, at the cost of some accuracy. As a result, parallel-point lights are often a good choice when extremely accurate specular highlights are not critical. Direct3D illuminates a mesh with a parallel-point light in a manner similar to a point light, but uses a shortcut to increase performance. The shortcut taken is in establishing a single direction for the light hitting all vertices in a mesh, rather than calculating a new direction for each vertex like a point light. (The direction that is used is the vector from the light's position to the origin of the mesh.) Because the light has the same direction for all vertices, it is considered parallel, hence the name. Like directional lights, parallel-point lights are not affected by range or attenuation.


Light Properties

Light properties describe a light object's type and color. Depending on the type of light being used, a light can have properties for attenuation and range, or for spotlight effects. But, not all types of lights will use all properties. Direct3D Immediate Mode uses the D3DLIGHT2 structure to carry information about light properties for all types of lights. This section contains information for all light properties. Information is divided into the following groups:

  • Light Type
  • Light Color
  • Light Position, Range and Attenuation
  • Light Direction
  • Spotlight Properties

Light properties affect how a light object illuminates objects in a scene. For more information, see Using Lights, Setting Light Properties, and The Mathematics of Direct3D Lighting.


Light Type

The light type property defines which type of Direct3D light object you're using. The light type is set by using a value from the D3DLIGHTTYPE enumeration in the dltType member of the light's D3DLIGHT2 structure. There are four types of lights in Direct3D Immediate Mode—point lights, spot lights, directional lights, and parallel-point lights. Each type illuminates objects in a scene differently, with varying levels of computational overhead. For general information about how each type of light works, see Introduction to Light Objects.


Light Color

The color property in the dcvColor member of the D3DLIGHT2 structure is an RGBA color that defines the color of light that a light object emits. The most common color is white (R:1.0 G:1.0 B:1.0), but you can create colors as needed to achieve the desired effect. For example, you could use red light for a fireplace, or you could use green light for a traffic signal set to "Go."

Generally, you set the light color components to values between 0.0 and 1.0, inclusive, but this isn't a requirement. For example, you might set all the components to 2.0, creating a light that was "brighter than white." This type of setting can be especially useful when you use attenuation settings other than constant.

Note that although Direct3D uses RGBA values for lights, the alpha color component is not used. For more information, see Color Values for Lights and Materials.


Light Position, Range and Attenuation

The position, range, and attenuation properties are used to define a light's location in world space, and how the light it emits behaves over distance. Like all light properties, these are carried within a light's D3DLIGHT2 structure.

Position

Light position is described using a D3DVECTOR structure in the dvPosition member of the D3DLIGHT2 structure. The x-, y-, and z-coordinates are assumed to be in world space. Directional lights are the only type of light that don't use the position property.

Range

A light's range property determines the distance, in world space, at which meshes in a scene no longer receive light emitted by that object. The dvRange member contains a floating-point value that represents the light's maximum range, in world space. Most applications set the range to the maximum possible value, D3DLIGHT_RANGE_MAX, which is defined in D3d.h. Directional and parallel-point lights don't use the range property.

Attenuation

Attenuation controls how a light's intensity decreases toward the maximum distance specified by the range property. Light attenuation is represented by three D3DLIGHT2 structure members: dvAttenuation0, dvAttenuation1, and dvAttenuation2. These members contain floating point values typically ranging from 0.0 to 1.0, controlling a light's constant, linear, and quadratic attenuation. Many applications set the dvAttenuation1 member to 1.0 and the others to 0.0, resulting in light intensity that attenuates evenly over distance—from maximum intensity at the source, to zero intensity at the light's range. You can combine attenuation values to get more complex attenuation effects. Or, you might set them to values outside of the normal range to create even stranger attenuation effects; negative attenuation values make a light that gets brighter over distance. For more information about the mathematical model that Direct3D uses to calculate attenuation, see Light Attenuation Over Distance. Like the range property, directional and parallel-point lights don't use the attenuation property.


Light Direction

A light's direction property determines the direction that the light emitted by the object travels, in world space. Direction is only used by directional and spotlights, and is described with a D3DVECTOR structure in the dvDirection member of the light's D3DLIGHT2 structure. Direction vectors are described as distances from a logical origin, regardless of the light's position within a scene. Therefore, a spotlight that points straight into a scene (along the positive z-axis) would have a direction vector of <0,0,1> no matter where its position is defined to be. Similarly, you could simulate sunlight shining directly down on a scene by using a directional light whose direction is <0,-1,0>. Obviously, you don't have to create lights that shine along the coordinate axes; you can mix and match values to create lights that shine at more interesting angles.

Note Although you don't need to normalize a light's direction vector, always be sure that it has magnitude. In other words, don't use a <0,0,0> direction vector.


Spotlight Properties

The D3DLIGHT2 structure contains three members that are used only by spotlights. These members (dvFalloff, dvTheta, and dvPhi) control how large or small a spotlight object's inner and outer cones are, and how light decreases between them. For general information about these characteristics, see Spotlights.

The dvTheta value is the radian angle of the spotlight's inner cone and the dvPhi value is the angle for the outer cone of light. The dvFalloff value controls how light intensity decreases between the outer edge of the inner cone and in the inner edge of the outer cone. Most applications will set dvFalloff to 1.0 to create falloff that occurs evenly between the two cones, but you can set other values as needed. For more information about the mathematical model used by Direct3D for calculating falloff, see Spotlight Falloff Model.

The following illustration shows the relationship between the values for these members, and how they can affect a spotlight's inner and outer cones of light.


Using Lights

This section provides information about using Lights in a Direct3D Immediate Mode application. Information is divided into the following topics.

  • Preparing to Use a Light
  • Creating a Light
  • Setting Light Properties
  • Adding a Light to a Viewport
  • Deleting a Light
  • Retrieving Light Properties


Preparing to Use a Light

The following steps are required, in order, to create and prepare a light for use in a scene. Note that these steps assume that you have already initialized the Direct3D sub-system and created a viewport.

To prepare a light for use in a scene

  1. Create a light object.

    Creating a light causes Direct3D to allocate internal data structures that will contain information about the light. For more information, see Creating a Light.

  2. Set the light properties.

    By setting the light properties, you are choosing the type of light you will use, and how Direct3D will calculate lighting effects generated by that object. For more information, see Setting Light Properties.

  3. Add the light to a viewport.

    The final step in preparing a light is to add it to the light list for a rendering viewport. For more information, see Adding a Light to a Viewport.


Creating a Light

The following illustration shows a common creation path of a light in Direct3D.

You create a light object by calling the IDirect3D3::CreateLight method. The first parameter is the address of a variable that will contain a valid IDirect3DLight interface pointer if the call succeeds. The method's second parameter is intended to be used in COM aggregation — because aggregation is not implemented, this parameter must be set to NULL. The following example shows what the code to make this call might look like:

    /*
     * For the purposes of this example, the g_lpD3D3 variable is the
     * address of an IDirect3D3 interface exposed by a Direct3D
     * object.
     */
    LPDIRECT3DLIGHT g_lpD3DLight;
    HRESULT   hr;

    hr = g_lpD3D3->CreateLight (&g_lpD3DLight, NULL);
    if (SUCCEEDED(hr))
    {
        // Set the light properties.
    }
    else
        return hr;

Before you can use the light object, you must set its properties. For more information, see Setting Light Properties.


Setting Light Properties

After you create a light object, you must set the light's properties by preparing a D3DLIGHT2 structure and then calling the IDirect3DLight::SetLight method. The SetLight method accepts the address of a prepared D3DLIGHT2 structure as its only parameter. You can call SetLight with new information as needed to update the light's illumination properties.

The following code sets up properties for a white point light that doesn't attenuate over distance, then calls the SetLight method to put the properties into effect:

    /*
     * For the purposes of this example, the g_lpD3DLight variable
     * is a valid pointer to an IDirect3D3 interface.
     */
    D3DLIGHT2 g_light;
    HRESULT   hr;

    // Initialize the structure.
    ZeroMemory(&g_light, sizeof(D3DLIGHT2));
    g_light.dwSize = sizeof(D3DLIGHT2);  // MUST set the size!

    // Set up for a white point light.
    g_light.dltType = D3DLIGHT_POINT;
    g_light.dcvColor.r = 1.0f;
    g_light.dcvColor.g = 1.0f;
    g_light.dcvColor.b = 1.0f;

    // Position it high in the scene, and behind the viewer.
    // (Remember, these coordinates are in world space, so
    //  the "viewer" could be anywhere in world space, too.
    //  For the purposes of this example, assume the viewer
    //  is at the origin of world space.)
    g_light.dvPosition.x = 0.0f;
    g_light.dvPosition.y = 1000.0f;
    g_light.dvPosition.z = -100.0f;

    // Don't attenuate.
    g_light.dvAttenuation0 = 1.0f;
    g_light.dvRange = D3DLIGHT_RANGE_MAX;

    // Make the light active light.
    g_light.dwFlags = D3DLIGHT_ACTIVE;

    // Set the property info for this light.
    // We have to cast the LPD3DLIGHT2 to be
    // an LPD3DLIGHT in order to compile.
    //
    // (See the following note for details.)
    hr = g_lpD3DLight->SetLight((LPD3DLIGHT)&g_light);
    if (SUCCEEDED(hr))
    {
        // Add the light to the viewport.
    }
    else
        return hr;

Note The IDirect3DLight::SetLight method checks the dwSize member of the structure specified in the lpLight parameter to determine whether you are using a D3DLIGHT2 or D3DLIGHT structure. The two structures are interpreted differently. The D3DLIGHT2 structure supersedes the D3DLIGHT structure, using the newer structure will provide the most reliable lighting. For backward compatibility, the SetLight method's parameter list is unchanged. As a result, you must cast the address of the D3DLIGHT2 structure you provide to the LPD3DLIGHT data type to avoid compiler errors.

(You can update a light's properties by a subsequent call to SetLight at any time, you need not add the light to the viewport each time.)

After choosing the light type by setting its properties, you can add the light to a viewport to complete the process of preparing a light for rendering. For more information, see Adding a Light to a Viewport.


Adding a Light to a Viewport

After you've created a light and set its properties, you can add it to a viewport by calling the viewport's IDirect3DViewport3::AddLight method. The AddLight method causes the viewport to add the light to a list of light objects it considers when rendering a scene. When you call AddLight, you specify the IDirect3DLight interface pointer that was returned when you initially created the light object by calling IDirect3D3::CreateLight, as shown in the following code fragment:

    /*
     * For this example, the g_lpD3DLight variable is a pointer to
     * the IDirect3DLight interface of a light object whose
     * illumination properties have been set, and the lpViewport3
     * variable is a valid IDirect3DViewport3 interface.
     */
    HRESULT hr;

    hr = lpViewport3->AddLight (g_lpD3DLight);
    if (FAILED (hr))
        return hr;


Deleting a Light

When you no longer need to use a light, you can delete it from a viewport by calling the viewport's IDirect3DViewport3::DeleteLight method. The method accepts a pointer to the IDirect3DLight interface of the light you want to remove.

The DeleteLight method only removes the light object from the list that the viewport uses when rendering a scene, it does not deallocate the light object. If you want to deallocate the light object, you must call the light object's IUnknown::Release method.


Retrieving Light Properties

You can retrieve the properties of an existing light object by calling its IDirect3DLight::GetLight method. When calling the GetLight method, you should pass the address of a D3DLIGHT2 structure cast as the LPD3DLIGHT data type, rather than the address of a D3DLIGHT structure. By passing the address of a D3DLIGHT2 structure, you ensure that there is enough memory available to accept the property information that the method copies to the provided structure from its internal data members. As with all structures in DirectX, always make sure to initialize the structure's dwSize member to the size of the structure, in bytes, before using it.


Materials

This section describes materials and how they are used in Direct3D Immediate Mode applications. The following topics are discussed:

  • What are Materials?
  • Material Properties
  • Using Materials


What are Materials?

Materials describe how polygons reflect light or appear to emit light in a 3-D scene. Essentially, a material is a set of properties that tell Direct3D the following things about the polygons it is rendering:

  • How they reflect ambient and diffuse light
  • What their specular highlights look like
  • Whether or not the polygons appear to emit light

Direct3D Immediate Mode uses the D3DMATERIAL structure to describe material properties. For more information, see Material Properties.


Material Properties

Material properties detail a material's diffuse reflection, ambient reflection, light emission, and specular highlighting characteristics. Direct3D uses the D3DMATERIAL structure to carry all material property information, as well as information used only for ramp emulation (an associated texture handle and the ramp palette size). Material properties affect the colors Direct3D uses to rasterize polygons that use the material. With the exception of the specular property, each of the properties is described as an RGBA color that represents how much of the red, green, and blue parts of a given type of light it reflects, and an alpha blending factor (the alpha component of the RGBA color). The material's specular property is described in two parts: color and power. For more information, see Color Values for Lights and Materials.

Diffuse and Ambient Reflection

The dcvDiffuse and dcvAmbient members of the D3DMATERIAL structure describe how a material reflects the ambient and diffuse light in a scene. Because most scenes contain much more diffuse light than ambient light, diffuse reflection plays the largest part in determining color. Additionally, because diffuse light is directional, the angle of incidence for diffuse light affects the overall intensity of the reflection. Diffuse reflection is greatest when the light strikes a vertex parallel to the vertex normal. As the angle increases, the effect of diffuse reflection diminishes. The amount of light reflected is the cosine of the angle between the incoming light and the vertex normal, as shown here.

Ambient reflection, like ambient light, is nondirectional. Ambient reflection has a lesser impact on the apparent color of a rendered object, but it does affect the overall color, and is most noticeable when little or no diffuse light reflects off the material. A material's ambient reflection is affected by the ambient light set for a scene by calling the IDirect3DDevice3::SetLightState method with the D3DLIGHTSTATE_AMBIENT flag.

Diffuse and ambient reflection work together to determine the perceived color of an object, and are usually identical values. For example, to render a blue crystalline object, you would create a material that reflected only the blue component of diffuse and ambient light. When placed in a room with a white light, the crystal appears to be blue. However, in a room that has only red light, the same crystal would appear to be black, because its material doesn't reflect red light.

Emission

Materials can be used to make a rendered object appear to be self-luminous. The dcvEmissive member of the D3DMATERIAL structure is used to describe the color and transparency of the emitted light. Emission affects an object's color and can, for example, make a dark material brighter and take on part of the emitted color.

You can use a material's emissive property to add the illusion that an object is emitting light, without incurring the computational overhead of adding a light to the scene. In the case of the blue crystal, the emissive property could be handy if you wanted to make the crystal appear to light up, but not actually cast light on other objects in the scene. Remember, materials with emissive properties don't actually emit light that can be reflected by other objects in a scene. To achieve this effect, you would need to place an additional light within the scene.

Specular Reflection

Specular reflection creates highlights on objects, making them appear shiny. The D3DMATERIAL structure contains two members that describe the specular highlight color as well as the material's overall shininess. You establish the color of the specular highlights by setting the dcvSpecular member to the desired RGBA color — the most common colors are white or light gray. The values you set in the dvPower member control how sharp the specular effects are.

Specular highlights can create dramatic effects. Drawing again on the blue crystal analogy: a larger dvPower value will create sharper specular highlights, making the crystal appear to be quite shiny. Smaller values increase the area of the effect, creating a dull reflection that might make the crystal look frosty. To make an object truly matte, set the dvPower member to zero, and the color in dcvSpecular to black. Experiment with different levels of reflection to produce a realistic appearance for your needs. The following illustration shows two identical models, the one on the left uses a specular reflection power of 10; the model on the right has no specular reflection:

Associated Textures

When using ramp emulation, textures are assigned to materials by setting the texture's handle to the hTexture member in the D3DMATERIAL structure. You can set this member to NULL if you won't be using ramp emulation, or if no texture is associated with the material.

You can retrieve the texture handle by calling the IDirect3DTexture2::GetHandle method. For more information, see Textures.

Ramp Emulation Properties

The dwRampSize member provides information about how the material should be drawn when Direct3D uses the ramp emulation shade model for shading (as opposed to RGB emulation, or hardware acceleration). Specifically, this member is an integer value that tells Direct3D how many palette entries it should create when it renders shaded polygons. For most materials, you should set this value to a reasonable number of shades; 16 is a common value. Direct3D automatically determines the shades it uses based on the material color and number of shades you specify.

It is recommended that you use the same ramp size for all of your materials. If Direct3D runs out of palette entries when adding a new material it tries to pick the closest material already in the palette. In order to get a match, the materials must have the same ramp size. By using the same size for all materials you have a better chance of getting a good color match, providing more attractive results.

Note A material that you will use solely as a background in a viewport should have a dwRampSize value of 1. This is because backgrounds are never shaded, regardless of the shade mode you set. Providing additional ramp shades for a background material doesn't provide any advantages, and effectively wastes memory.


Using Materials

‹Materials are required for rendering in Direct3D Immediate Mode. › This section contains information about using Materials in a Direct3D application. Information is divided into the following topics:

  • Preparing to Use a Material
  • Creating a Material
  • Setting Material Properties
  • Retrieving Material Handles
  • Selecting a Material for Rendering
  • Retrieving Material Properties


Preparing to Use a Material

The following steps are required, in order, to create and prepare a material for rendering.

To prepare a material for rendering

  1. Create a material object.

    When you create a material object, Direct3D allocates internal data structures that will contain information about the material. For more information, see Creating a Material.

  2. Set the material properties.

    By setting material properties, you define how the material will reflect light in a scene, and how material colors will be used when Direct3D is using ramp emulation. For more information, see Setting Material Properties.

  3. Retrieve the material handle.

    Retrieving the material object's handle creates an association between the material and a Direct3D device. For more information, see Retrieving Material Handles.

  4. Select the material.

    Selecting the material causes Direct3D to rasterize polygons with that material's reflection properties, and is the final step you must take to prepare the material for rendering. For more information, see Selecting a Material for Rendering.


Creating a Material

The following illustration shows a common creation path of a material in Direct3D.

You create a material by calling the IDirect3D3::CreateMaterial method. The first parameter is the address of the variable that will contain a valid IDirect3DMaterial3 interface pointer if the call succeeds. The method's second parameter is unused and should be set to NULL. The following example shows how this call can be made:

    //
    // The g_lpD3D variable is a global variable that
    // contains a pointer to an IDirect3D3 interface.
    //

    LPDIRECT3DMATERIAL3 lpMat3;
    HRESULT     hr;

    hr = g_lpD3D->CreateMaterial(&lpMat3, NULL);
    if(SUCCEEDED(hr))
    {
        // Set the material properties.
    }

Before using the material, you must set its properties. For more information, see Setting Material Properties.


Setting Material Properties

After creating a material object, you must set its properties before you can use it during rendering. Setting the material's properties involves preparing a D3DMATERIAL structure and then calling the IDirect3DMaterial3::SetMaterial method.

To prepare the D3DMATERIAL structure for use, set the property information in the structure to create the desired effect during rendering. The following code fragment sets up the D3DMATERIAL structure for a purple material, with sharp white specular highlights, and a 16 color ramp (which Direct3D only uses for ramp emulation):

    D3DMATERIAL mat;

    // Initialize the structure for use.
    ZeroMemory(&mat, sizeof(D3DMATERIAL));
    mat.dwSize   = sizeof(D3DMATERIAL);  // This is REQUIRED.

    // Set the RGBA for diffuse reflection.
    mat.dcvDiffuse.r = (D3DVALUE)0.5;
    mat.dcvDiffuse.g = (D3DVALUE)0.0;
    mat.dcvDiffuse.b = (D3DVALUE)0.5;
    mat.dcvDiffuse.a = (D3DVALUE)1.0;

    // Set the RGBA for ambient reflection.
    mat.dcvAmbient.r = (D3DVALUE)0.5;
    mat.dcvAmbient.g = (D3DVALUE)0.0;
    mat.dcvAmbient.b = (D3DVALUE)0.5;
    mat.dcvAmbient.a = (D3DVALUE)1.0;

    // Set the color and sharpness of specular highlights.
    mat.dcvSpecular.r = (D3DVALUE)1.0;
    mat.dcvSpecular.g = (D3DVALUE)1.0;
    mat.dcvSpecular.b = (D3DVALUE)1.0;
    mat.dcvSpecular.a = (D3DVALUE)1.0;
    mat.dvPower = (float)50.0;

    // Use a 16 entry color ramp, in case
    // we're using ramp emulation.
    mat.dwRampSize = 16;

After preparing the D3DMATERIAL structure, complete setting material properties by calling the IDirect3DMaterial3::SetMaterial method of the desired material object. This method accepts the address of a prepared D3DMATERIAL structure as its only parameter. You can call SetMaterial with new information as needed to update the material's illumination properties.

Once you successfully set a material's properties, you can retrieve its material handle, which you need to select the material during rendering. For more information, see Retrieving Material Handles.


Retrieving Material Handles

After setting a material object's properties, you can retrieve its material handle by calling the IDirect3DMaterial3::GetHandle method. Direct3D Immediate Mode uses the D3DMATERIALHANDLE data type to declare material handle variables.

By retrieving the material handle, you are effectively creating an association between the material and a particular Direct3D device. The material handle represents that association — the handle you retrieve can only be used with that device. To use the material with another device, you must retrieve another handle specific to that device.

The GetHandle method accepts two parameters: the address of an IDirect3DDevice3 interface, and the address of a variable that will contain the resulting material handle after the call returns. Upon retrieving the material's handle, you can use it during rendering as often as you need. For more information, see Selecting a Material for Rendering.


Selecting a Material for Rendering

After you've created a material object, set its properties, and retrieved its handle, you're ready to render. You select the material into a Direct3D device by calling the device's IDirect3DDevice3::SetLightState method with the appropriate flags. The SetLightState method is a multi-purpose method; when calling the method to select the rendering material, set the first parameter to D3DLIGHTSTATE_MATERIAL, and set the second parameter to the handle of the material you want to use. The following code shows what this call commonly looks like

    //
    // For this example, hMat is a variable of type D3DMATERIALHANDLE that has
    // been set to a valid material handle.  The lpDev3 variable is a pointer
    // to the IDirect3DDevice3 interface of the device that will use the material.
    //
    HRESULT hr;

    // Set the current material.
    hr = lpDev3->SetLightState(D3DLIGHTSTATE_MATERIAL, hMat);
    if(FAILED(hr))
    {
        REPORTERR(hr);
        return hr;
    }

Note A Direct3D device can render with only one material at a time. After setting the current material, Direct3D will use that material for all polygons until another material is selected. You can change the currently used material at any time.


Retrieving Material Properties

You retrieve a material object's properties by calling the object's IDirect3DMaterial3::GetMaterial method. Unlike using the IDirect3DMaterial3::SetMaterial method, GetMaterial doesn't require much preparation. Before the call, initialize a D3DMATERIAL structure's members to zero and set the dwSize member to the size of the structure, in bytes. The GetMaterial method accepts the address of an initialized D3DMATERIAL structure, and fills the provided structure with information describing the current material properties before returning.


The Mathematics of Direct3D Lighting

Direct3D models illumination by estimating how light behaves in nature. The Direct3D light model keeps track of light color, the direction and distance that light travels, the position of the viewer, and the characteristics of materials to compute two color components for each vertex in a face.

Note All computations are made in model space by transforming the light's position and direction, along with the camera position to model space using the inverse of the world matrix, then backtransformed. Direct3D uses these color components to compute the color it draws while rasterizing the pixels of a face. As a result, if the world or view matrices introduce non-uniform scaling, the resultant lighting could be inaccurate.

This section presents a technical look at the formulas that Direct3D uses to come up with diffuse and specular components. By understanding Direct3D's approach, you will be better equipped to decide if the Direct3D light model suits your needs. The Direct3D light model was designed to be accurate, efficient, and easy to use. However, if the formulas used by Direct3D don't suit your needs, you can implement your own light model, bypassing the Direct3D lighting module altogether.

  • Light Attenuation Over Distance
  • Reflectance Model
  • Spotlight Falloff Model


Light Attenuation Over Distance

Direct3D uses the following formula to normalize the distance from a light source to a vertex into a value from 0.0 to 1.0, inclusive:

In the preceding formula, Dn is the normalized distance, R is the light's range, and D is the distance, in world space, from the light source to the vertex being lit. (When D is greater than R, the system assumes that no light reaches the vertex, and it moves to the next vertex to be lit.) A normalized distance is 1.0 at the light's source, and 0.0 at the light's range.

With the normalized distance in hand, Direct3D then applies the following formula to calculate light attenuation over distance for point lights and spotlights (directional and parallel point lights don't attenuate over distance):

In this attenuation formula, A is the calculated total attenuation and Dn is the normalized distance from the light source to the vertex. The dvAttenuation0, dvAttenuation1, and dvAttenuation2 values are the light's constant, linear, and quadratic attenuation factors as specified by the members of a light object's D3DLIGHT2 structure. (Not surprisingly, the corresponding structure members are dvAttenuation0, dvAttenuation1, and dvAttenuation2. In most cases, these attenuation factors are between 0.0 and 1.0, inclusive.)

The constant, linear and quadratic attenuation factors act as coefficients in the formula—you can produce a wide variety of attenuation curves by making simple adjustments to them. Most applications will set the linear attenuation factor to 1.0 and set the remaining factors to 0.0 to produce a light that steadily falls off over distance. Similarly, you could apply a constant attenuation factor of 1.0 by itself to make a light that doesn't attenuate (but will still be limited by range). The following illustration shows the three most common attenuation curves.

Note that using only quadratic attenuation often results in harsh transition between light and dark over distance. Each of the curves uses only one of the attenuation factors, but you are free to mix these values to create different attenuation effects.

The attenuation formula used by Direct3D computes an attenuation value that typically ranges from 1.0 at the light source to 0.0 at the maximum range of the light. (The result of the formula isn't normalized to fit between 0.0 and 1.0; attenuation outside that range is still considered valid, but will result in harsh or unpredictable lighting). The attenuation value is multiplied into the red, green and blue components of the light's color to scale the light's intensity as a factor of the distance light travels to a vertex. After computing the light attenuation, Direct3D also considers spotlight effects (if applicable), the angle that the light reflects from a surface, as well as the reflectance of the material that the vertex uses to come up with the diffuse and specular components for that vertex. For more information, see Spotlight Falloff Model and Reflectance Model.


Reflectance Model

After adjusting the light intensity for any attenuation effects, Direct3D computes how much of the remaining light reflects from a vertex given the angle of the vertex normal and the direction of the incident light. (Direct3D skips to this step for directional and parallel point lights, because they don't attenuate over distance.)

The system considers two reflection types, diffuse and specular, and uses a different formula to determine how much light is reflected for each. After figuring out the amounts of light reflected, Direct3D applies these new values to the diffuse and specular reflectance properties of the material for the vertex being lit. The resulting color values are the diffuse and specular components that the rasterizer uses to produce Gouraud shading and specular highlighting.

This section provides information on the methods that the system uses for calculating reflectance. Information is divided according to the type of reflectance being calculated:

  • Diffuse Reflection Model
  • Specular Reflection Model


Diffuse Reflection Model

Direct3D uses the following formula to compute diffuse reflection factors:

In this formula, Rd is the diffuse reflectance factor, D is the direction that the light travels to the vertex, and N is the vertex normal. Vectors D and N are normalized vectors. The light's direction vector is reversed by multiplying it by -1 to create the proper association between the direction vector and the vertex normal. This formula produces values that range from -1.0 to 1.0, which are clamped to the range of 0.0 to 1.0 and used to scale the intensity of the light reflecting from the vertex.

After the diffuse reflection formula is applied, the light has been scaled appropriately for attenuation over distance, spotlight effects, and diffuse reflection. The scaled light is then applied to the diffuse reflectance property of the material that the vertex uses and ambient reflection is considered to determine the diffuse component at that vertex. The formula that combines ambient and diffuse reflection to create the diffuse component for the vertex looks like this:

In the preceding formula, Dv is the diffuse component being calculated for the vertex, Ia is the ambient light level in the scene, Ma is the material's ambient reflection property, and the Me variable is the emissive property for the material. The A variable is the attenuated light at the vertex (see Light Attenuation Over Distance) and Rd is the diffuse reflectance factor. The Cd variable can be one of two possible colors, the one used depends on the state of the system and the format of the vertex at the time. If the D3DLIGHTSTATE_COLORVERTEX light state is enabled (and diffuse color is present in the vertex), the system uses the diffuse vertex color in Cd. Otherwise, the system uses the diffuse material color for Cd. If a diffuse vertex color is present, the output alpha is equal to the diffuse alpha for the vertex. Otherwise, output alpha is equal to the alpha component of diffuse material, clamped to the range [0, 255].

After applying this formula, Dv is the diffuse color component for the vertex being lit.

For more information, see Specular Reflection Model, Spotlight Falloff Model.


Specular Reflection Model

Modeling specular reflection requires that the system not only know the direction that light is traveling, but also the direction to the viewer's eye. Direct3D uses the inverses of the view- and world-transformation matrices to get this information. The system uses a simplified version of the Phong specular-reflection model, which employs a "halfway vector" that exists midway between the vector to the light source and the vector to the eye to approximate the intensity of specular reflection.

Following the simplified Phong model, Direct3D determines the halfway vector by subtracting the vector to the light source from the vector to the eye. Once it has found the halfway vector, the system uses the following formula to compute specular reflection:

In the preceding formula, Rs is the specular reflectance, N in the vertex normal, H is the halfway vector, and p is the specular reflection power of the material that the vertex uses (as specified by the dvPower member of the material's D3DMATERIAL structure). The N and H vectors are normalized.

Like the diffuse reflectance formula, this formula produces values that range from -1.0 to 1.0, which are clamped to the range of 0.0 to 1.0 and used to scale the light reflecting from the vertex. Also similar to the diffuse reflection model, the remaining light is applied to the specular reflectance property of the vertex's material to derive the specular component at that vertex, as shown in the following formula:

In the preceding formula, Sv is the specular color being computed, A is the attenuated light at the vertex, and the Rs variable is the previously calculated specular reflectance. The Cs variable can be one of two possible colors, the one used depends on the state of the system and the format of the vertex at the time. If the D3DLIGHTSTATE_COLORVERTEX light state is enabled (and specular color is present in the vertex), the system uses the specular vertex color in Cs. Otherwise, the system uses the diffuse material color for Cs.

For more information, see Diffuse Reflection Model.


Spotlight Falloff Model

Spotlights emit a cone of light that has two parts: a bright inner cone and an outer cone. Light is brightest within the inner cone and isn't present outside the outer cone, with light intensity attenuating between the two areas. This type of attenuation is commonly referred to as falloff.

How much the light a vertex receives is based on the vertex's location within the inner or outer cones. Direct3D computes the dot product of the spotlight's direction vector (L) and the vector from the vertex to the light (D). This value is equal to the cosine of the angle between the two vectors, and serves as a indicator of the vertex's position that can be compared to the light's cone angles to determine where the vertex might lie in the inner or outer cones. The following illustration provides a graphical representation of the association between these two vectors:

Next, the system compares this value to the cosine of the spot light's inner and outer cone angles. In the light's D3DLIGHT2 structure, the dvTheta and dvPhi members represent the total cone angles for the inner and outer cones. Because the attenuation occurs as the vertex becomes more distant from the center of illumination, rather than across the total cone angle, Direct3D halves these cone angles before calculating their cosines.

If the dot product of vectors L and D is less than or equal to the cosine of the outer cone angle, the vertex lies beyond the outer cone, and receives no light. If the dot product of L and D is greater than the cosine of the inner cone angle, then the vertex is within the inner cone, and receives the maximum amount of light (still considering attenuation over distance). If the vertex is somewhere between the two regions, Direct3D calculates falloff for the vertex by using the following formula:

In the formula, If is light intensity (after falloff) for the vertex being lit, α is the angle between vectors L and D, φ is half of the outer cone angle, θ is half of the inner cone angle, and p is the spot light's falloff property (dvFalloff in the D3DLIGHT2 structure). This formula generates a value between 0.0 and 1.0 that scales the light's intensity at the vertex to account for falloff. Attenuation as a factor of the vertex's distance from the light is also applied. The p value corresponds to the dvFalloff member of the D3DLIGHT2 structure and controls the shape of the falloff curve. The following illustration shows how different dvFalloff values can affect the falloff curve:

The effect of various dvFalloff values on the actual lighting is subtle, and a small performance penalty is incurred by shaping the falloff curve with dvFalloff values other than 1.0. For these reasons, most people will set this value to 1.0.

For more information, see Light Attenuation Over Distance.


Vertex Formats

This section describes the concepts you need to understand to specify vertices in Direct3D, and provides information about the various formats your application can use to declare vertices. The following topics are discussed:

  • About Vertex Formats
  • Untransformed and Unlit Vertices
  • Untransformed and Lit Vertices
  • Transformed and Lit Vertices
  • Strided Vertex Format

Note Prior to DirectX 6.0, applications were required to use one of three vertex types — D3DVERTEX, D3DLVERTEX, and D3DTLVERTEX — depending on which parts of the Direct3D geometry pipeline were being used. With the introduction of more flexible vertex formats in DirectX 6.0, you can declare vertices in many more ways than before, but you can still use the predefined structures to describe untransformed and unlit vertices, untransformed but lit vertices, and vertices that are both transformed and lit. For more information, read the topics for each type of vertex in this section thoroughly.


About Vertex Formats

Direct3D Immediate Mode applications can define model vertices in several different ways. Support for flexible vertex definitions (also known as "flexible vertex formats") makes it possible for your application to use only the vertex components it needs, eliminating those components that aren't used. By using only the needed vertex components, your application can conserve memory and minimize the processing bandwidth required to render models.

You describe how your vertices are formatted by using a combination of flexible vertex format flags. Each of the rendering methods of IDirect3DDevice3 accepts a combination of these flags, and uses them to determine how to render primitives. Basically, these flags tell the system which vertex components—position, normal, colors, and the number of texture coordinates–your application uses and, indirectly, which parts of the rendering pipeline you want Direct3D to apply to them. In addition, the presence or absence of a particular vertex format flag communicates to the system which vertex component fields are present in memory, and which you've omitted.

Note The behavior is slightly different if your application uses the IDirect3DDevice3::DrawPrimitiveStrided or IDirect3DDevice3::DrawIndexedPrimitiveStrided methods. For more information, see Strided Vertex Format.

One significant requirement that the system places on how you format your vertices is on the order in which the data appears. The following illustration depicts the required order for all possible vertex components in memory, and their associated data types.

No real application will use every single component—the RHW (reciprocal homogenous W) and vertex normal fields are mutually exclusive–nor will most applications try to use all eight sets of texture coordinates, but the flexibility is there. There are several restrictions on which flags you can use with other flags. These are mostly common-sense. For example, you can't use the D3DFVF_XYZ and D3DFVF_XYZRHW flags together, as this would indicate that your application is describing a vertex's position with both untransformed and transformed vertices. For more information, take a look at the description for each of the flags in Flexible Vertex Format Flags.


Untransformed and Unlit Vertices

The presence of the D3DFVF_XYZ and D3DFVF_NORMAL flags in the vertex description that you pass to rendering methods identifies the untransformed and unlit vertex type. By using untransformed and unlit vertices, your application effectively requests that Direct3D perform all transformation and lighting operations using its internal algorithms. (If you want, you can pass D3DDP_DONOTLIGHT to the rendering methods to disable Direct3D's lighting engine for the primitives being rendered.)

Most applications use this vertex type, as it frees them from implementing their own transformation and lighting engines. However, because the system is making calculations for you, it requires that you provide a certain amount of information with each vertex:

  • You are required to specify vertices in untransformed model coordinates (a model coordinate vertex is positioned relative to a local origin for the model, not for the world). The system then applies world, view, and projection transformations to the model coordinates to position them within your scene, and determine their final locations on the screen.
  • You should include a vertex normal. Omitting the vertex normal is like telling Direct3D that you've lit the vertices already (see Untransformed and Lit Vertices). The system uses the vertex normal, along with the current material, in its lighting calculations. For details, see Face and Vertex Normal Vectors, and Lighting and Materials.

Other than these requirements, you have the flexibility to use (or disregard) the other vertex components. For example, if you want to include a diffuse or specular color with your untransformed vertices, you can. (This wasn't possible before DirectX 6.0). These color components can "tint" the material color at each vertex, making it possible to achieve shading effects that are much more subtle and flexible than lighting calculations that use only the material color. Untransformed, unlit vertices can also include up to eight sets of texture coordinates.

Applications can still use the legacy D3DVERTEX structure for vertices. In fact, the d3dtypes.h header file defines a shortcut macro to identify this vertex format:

#define D3DFVF_VERTEX ( D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1 )

If the D3DVERTEX structure doesn't suit your application's needs, feel free to define your own. Remember which vertex components your application needs, and make sure they appear in the required order by declaring a properly ordered structure. The following code declares a valid vertex format structure that includes a position, a vertex normal, a diffuse color, and two sets of texture coordinates:

//
// The vertex format description for this vertex
// would be: (D3DFVF_XYZ | D3DFVF_NORMAL |
//            D3DFVF_DIFFUSE | D3DFVF_TEX2)
//
typedef struct _UNLITVERTEX {
    float x, y, z;        // position

    float nx, ny, nz;     // normal

    DWORD dwDiffuseRGBA;  // diffuse color

    float tu1,    // texture coordinates
          tv1;

    float tu2,
          tv2;
} UNLITVERTEX, *LPUNLITVERTEX;

The vertex description for the preceding structure would be a combination of the D3DFVF_XYZ, D3DFVF_NORMAL, D3DFVF_DIFFUSE, and D3DFVF_TEX2 flexible vertex format flags. The rendering methods, such as IDirect3DDevice3::DrawPrimitive, accept the address of a vertex array as a void pointer, so remember to cast your vertex array pointer to the LPVOID data type when you call the rendering methods.

For more information, see About Vertex Formats.


Untransformed and Lit Vertices

If you include the D3DFVF_XYZ flag, but not the D3DFVF_NORMAL flag, in the vertex format description you use with the Direct3D rendering methods, you are identifying your vertices as untransformed, but already lit. (For information about other dependencies and exclusions, see Flexible Vertex Format Flags.)

By using untransformed and lit vertices, your application requests that Direct3D not perform any lighting calculations on your vertices, but it should still transform them using the previously set world, view, and projection matrices. Because the system isn't doing lighting calculations, it doesn't need a vertex normal. The system uses the diffuse and specular components at each vertex for shading. These colors might be arbitrary, or they might be computed using your own lighting formulas. If you don't include a diffuse or specular component, the system uses the default colors. The default diffuse color is 0xFFFFFFFF, and the default specular color is 0x00000000.

Like the other vertex types, other than including a position and some amount of color information, you are free to include or disregard the texture coordinate sets in the unlit vertex format.

Applications can still use the legacy D3DLVERTEX structure for vertices. The d3dtypes.h header file defines the following helper macro that you can use to describe the D3DLVERTEX structure's format:

#define D3DFVF_LVERTEX ( D3DFVF_XYZ | D3DFVF_RESERVED1 | D3DFVF_DIFFUSE | \
                         D3DFVF_SPECULAR | D3DFVF_TEX1 )

Note that the helper macro includes the D3DFVF_RESERVED1 flag, indicating to the system that you're using the D3DLVERTEX structure, which includes the dwReserved member. This is required when using D3DLVERTEX because vertex formats don't usually include reserved fields; the D3DFVF_RESERVED1 flag informs the system that there is an unused DWORD between the vertex's position and diffuse color vertex components.

If the D3DLVERTEX structure doesn't include all the fields your application needs, you can define another structure. Make sure that your vertex components appear in the required order, declaring a new structure accordingly. The following code declares a valid untransformed and lit vertex, with diffuse and specular vertex colors, and three sets of texture coordinates:

//
// The vertex format description for this vertex
// would be: (D3DFVF_XYZ | D3DFVF_DIFFUSE |
//            D3DFVF_SPECULAR | D3DFVF_TEX3)
//
typedef struct _LITVERTEX {
    float x, y, z;        // position

    DWORD dwDiffuseRGBA;  // diffuse color

    DWORD dwSpecularRGBA; // specular color

    float tu1,    // texture coordinates
          tv1;

    float tu2,
          tv2;

    float tu3,
          tv3;
} LITVERTEX, *LPLITVERTEX;

The vertex description for the preceding structure would be a combination of the D3DFVF_XYZ, D3DFVF_DIFFUSE, D3DFVF_SPECULAR, and D3DFVF_TEX3 flexible vertex format flags. The rendering methods, such as IDirect3DDevice3::DrawPrimitive, accept the address of a vertex array as a void pointer, so remember to cast your vertex array pointer to the LPVOID data type when you call the rendering methods.

For more information, see About Vertex Formats.


Transformed and Lit Vertices

If you include the D3DFVF_XYZRHW flag in your vertex format description, you are telling the system that your application uses transformed and lit vertices. This means that Direct3D doesn't transform your vertices with the world, view, or projection matrices, nor does it perform any lighting calculations; it assumes that your application has already taken care of these steps. (This fact makes transformed and lit vertices common when porting existing 3-D applications to Direct3D Immediate Mode.) In short, Direct3D does not modify transformed and lit vertices at all; it passes them directly to the driver to be rasterized.

The vertex format flags associated with untransformed vertices and lighting (D3DFVF_XYZ and D3DFVF_NORMAL) are not allowed if D3DFVF_XYZRHW is present. For more about flag dependencies and exclusions, see Flexible Vertex Format Flags.

The system requires that the vertex position you specify be already transformed. The x and y values must be in screen coordinates, and z must be the depth value of the pixel to be used in the z-buffer. Z values can range from 0.0 to 1.0, where 0.0 is the closest possible position to the viewer, and 1.0 is the farthest position still visible within the viewing area. Immediately following the position, transformed and lit vertices must include an RHW value (reciprocal of homogeneous W) value. RHW is the reciprocal of the W coordinate from the homogeneous point (x,y,z,w) at which the vertex exists in projection space. (This value often works out to be the distance from the eyepoint to the vertex, taken along the z-axis.)

Other than the position and RHW requirements, this vertex format is similar to an untransformed and lit vertex. To recap:

  • The system doesn't do any lighting calculations with this format, so it doesn't need a vertex normal.
  • You can specify a diffuse or specular color. If you don't, the system uses 0xFFFFFFFF and 0x00000000 for these components, respectively.
  • You can use up to eight sets of texture coordinates, or none at all.

Applications can still use the legacy D3DTLVERTEX structure for transformed and lit vertices. The d3dtypes.h header file defines the following helper macro that you can use to describe the vertex format declared by the D3DTLVERTEX structure:

#define D3DFVF_TLVERTEX ( D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR | \
                          D3DFVF_TEX1 )

It's possible that the D3DTLVERTEX structure doesn't include the fields you need. If this is the case, define another structure that does, but make sure that the vertex components are ordered properly. The following code declares a valid transformed and lit vertex, with diffuse and specular vertex colors, and one set of texture coordinates:

//
// The vertex format description for this vertex
// would be: (D3DFVF_XYZRHW | D3DFVF_DIFFUSE |
//            D3DFVF_SPECULAR | D3DFVF_TEX1)
//
typedef struct _TRANSLITVERTEX {
    float x, y;           // screen position

    float z;              // Z-buffer depth

    float rhw;            // reciprocal homogeneous W

    DWORD dwDiffuseRGBA;  // diffuse color

    DWORD dwSpecularRGBA; // specular color

    float tu1,    // texture coordinates
          tv1;
} TRANSLITVERTEX, *LPTRANSLITVERTEX;

The vertex description for the preceding structure would be a combination of the D3DFVF_XYZRHW, D3DFVF_DIFFUSE, D3DFVF_SPECULAR, and D3DFVF_TEX1 flexible vertex format flags. The rendering methods, such as IDirect3DDevice3::DrawPrimitive, accept the address of a vertex array as a void pointer, so remember to cast your vertex array pointer to the LPVOID data type when you call the rendering methods.

For more information, see About Vertex Formats.


Strided Vertex Format

The strided vertex format contains fields to represent untransformed vertices, lit or unlit, for the IDirect3DDevice3::DrawPrimitiveStrided and IDirect3DDevice3::DrawIndexedPrimitiveStrided methods. You cannot use the strided vertex format for transformed vertices. Unlike a "normal" vertex, which is a structure that physically contains all the necessary vertex components, a "strided" vertex is a structure that contains pointers to the vertex components rather than the components themselves.

This indirection is accomplished through the D3DDRAWPRIMITIVESTRIDEDDATA structure that is accepted by the DrawPrimitiveStrided and DrawIndexedPrimitiveStrided methods. You describe strided vertices using the same combinations of flexible vertex format flags as a non-strided vertex. However, unlike non-strided vertices, the flags you use do not indicate the presence of a given field in memory (D3DDRAWPRIMITIVESTRIDEDDATA includes them all), they indicate which the structure members that your application uses. The restrictions for these flags are identical to non-strided vertices, for details, see Flexible Vertex Format Flags.

The D3DDRAWPRIMITIVESTRIDEDDATA structure contains 12 D3DDP_PTRSTRIDE structures, one structure each for the position, normal, diffuse color, specular color, and texture coordinate sets for the vertices. Each D3DDP_PTRSTRIDE structure contains a pointer to an array of data, and the stride of that array. These 12 structures provide the indirection that allows your application to arrange vertex components however it needs. For instance, you might use distinct arrays for every vertex component, as shown in the following illustration.

The lpvData member of the corresponding D3DDP_PTRSTRIDE structures contains the address of a buffer that contains an array of vertex components. Each element in each array represents a component for one vertex, which is made up of some number of floats (for position, normal, and texture coordinates) or an RGBA value (for diffuse and specular colors). There is one entry within each array for every vertex to be rendered. The dwStride member of D3DDP_PTRSTRIDE should be set to the memory stride, in bytes, from one entry in the array to the next. The following table describes the components and the corresponding strides for each.

Component | Stride
untransformed position | 3 floats (x,y,z)
vertex normal | 3 floats (nx,ny,nz)
diffuse color | 1 DWORD (RGBA)
specular color | 1 DWORD (RGBA)
texture coordinate set | 2 floats (u,v)

Some developers might choose to include some or all vertex components in an interleaved array. The strided vertex format makes doing this very simple. If your application interleaves the vertex position and normal components, for example, you could visualize the memory layout and corresponding settings in D3DDP_PTRSTRIDE structures as follows:

In this case, the lpvData members of the D3DDP_PTRSTRIDE structures point to two locations within the same buffer, and the strides are set to the combined width of the interleaved components. Of course, you aren't limited to any particular interleaving scheme. So long as you set the data pointers and their strides correctly, any interleaving scheme will work.


Textures

Textures are a powerful tool in the quest for realism in computer-generated 3-D images. Direct3D supports an extensive texturing feature set, providing developers with easy access to advanced texturing techniques. This section discusses the purposes and uses of textures in Direct3D. The information is presented in the following topics:

  • Basic Texturing Concepts
  • Texture Handles
  • Texture Interfaces
  • Texture Filtering
  • Texture Wrapping
  • Texture Blending
  • Texture Compression
  • Automatic Texture Management
  • Hardware Considerations for Texturing

If you are familiar with what textures are and how they are used, you may want to skip the Basic Texturing Concepts section. It is important to note, however, that Direct3D now uses texture interfaces to access many of its most powerful texturing features. Therefore, you may want to look over the section entitled Texture Interfaces.


Basic Texturing Concepts

This section presents the most fundamental concepts required for an understanding of texturing in Direct3D. The information in this section is presented in the following topics:

  • What Is a Texture?
  • Texture Coordinates
  • Texture Addressing Modes
  • Texture Handles and Texture Interfaces
  • Palettized Textures


What Is a Texture?

Early computer-generated 3-D images, although generally advanced for their time, tended to have a shiny plastic look. They lacked the types of markings that give 3-D objects realistic visual complexity such as scuffs, cracks, fingerprints, and smudges. In recent years, textures have gained popularity among developers as a tool for enhancing the realism of computer-generated 3-D images.

At its most basic, a texture is simply a bitmap of pixel colors. In this sense, the word texture has a specific definition when used in the context of computer graphics. In the normal semantics associated with the word texture, we refer both to the patterns of color on an object and its roughness or smoothness. Direct3D textures don't add "bumpiness" to an object. Rather, the textures, or patterns of colors, just give it the appearance of bumpiness.

Because Direct3D textures are simply bitmaps, any bitmap can be applied to a Direct3D primitive. For instance, applications can create and manipulate objects that appear to have a wood grain pattern in them. Grass, dirt, and rocks can be applied to a set of 3-D primitives that form a hill. The result is a very realistic-looking hillside. Texturing can also be used to create effects such as signs along a roadside, rock strata in a cliff, or the appearance of marble on a floor.

In addition, Direct3D supports more advanced texturing techniques such as texture blending (with or without transparency) and light mapping. Information on these techniques is presented in Texture Blending and Light Mapping With Textures.

If your application creates a HAL device, an MMX device, or an RGB device (see Direct3D Device Types), it can use 8-, 16-, 24-, or 32-bit textures. Legacy applications that use the monochromatic (or ramp) device must use 8-bit textures.


Texture Coordinates

Textures, like most bitmaps, are a two dimensional array of color values. The individual color values are called texture elements, or texels. Each texel has a unique address in the texture. The address can be thought of as a column and row number, which are labeled U and V respectively.

Texture coordinates are in texture space. That is, they are relative to the location (0,0) in the texture. When a texture is applied to a primitive in 3-D space, its texel addresses must be mapped into object coordinates. They must then be translated into screen coordinates, or pixel locations.

Direct3D maps texels in texture space directly to pixels in screen space, skipping the intermediate step for greater efficiency. This mapping process is actually an inverse mapping. That is, for each pixel in screen space, the corresponding texel position in texture space is calculated. The texture color at or around that point is sampled. The sampling process is called texture filtering. For more information, see Texture Filtering.

Each texel in a texture can be specified by its texel coordinate. However, in order to map texels onto primitives, Direct3D requires a uniform address range for all texels in all textures. Therefore, it uses a generic addressing scheme in which all texel addresses are in the range of 0.0 to 1.0 inclusive. Direct3D programs specify texture coordinates in terms of U,V values, much like 2-D Cartesian coordinates are specified in terms of x,y coordinates.

A result of this is that identical texture addresses can map to different texel coordinates in different textures. In the following illustration, the texture address being used is (0.0,0.5). However, because the textures are different sizes, the texture address maps to different texels. Texture 1, on the left, is 5x5. The texture address (0.0,0.5) maps to texel (0,2). Texture 2, on the right, is 7x7. The texture address (0.0,0.5) maps to texel (0,3).

A simplified version of the texel mapping process is shown in the following diagram.

For this example, we are idealizing a pixel, shown at the left of the illustration, into a square of color. The addresses of the four corners of the pixel are mapped onto the 3-D primitive in object space. The shape of the pixel is often distorted because of the shape of the primitive in 3-D space and because of the viewing angle. The corners of the surface area on the primitive that correspond the corners of the pixel are then mapped into texture space. The mapping process distorts the pixel's shape again, which is common. The final color value of the pixel is computed from the texels in the region to which the pixel maps. You determine the method that Direct3D uses to arrive at the pixel color when you set the texture filtering method. For more information, see Texture Filtering.

Your application can assign texture coordinates directly to vertices. For details, see D3DVERTEX. This capability gives you control over which portion of a texture is mapped onto a primitive. For instance, suppose you create a rectangular primitive that is exactly the same size as the texture in the following illustration. In this example, you want your application to map the whole texture onto the whole wall. The texture coordinates your application would assign to the vertices of the primitive are (0.0,0.0), (1.0,0.0), (1.0,1.0), and (0.0,1.0).

Let's say you decide to decrease the height of the wall by one-half. You can either distort the texture to fit onto the smaller wall, or you can assign texture coordinates that will cause Direct3D to use the bottom half of the texture.

If you decide to distort or scale the texture to fit the smaller wall, the texture filtering method that you use will influence the quality of the image. For more information, see Texture Filtering.

If, instead, you decide to assign texture coordinates to make Direct3D use the bottom half of the texture for the smaller wall, the texture coordinates your application would assign to the vertices of the primitive in this example are (0.0,0.0), (1.0,0.0), (1.0,0.5), and (0.0,0.5). Direct3D will apply the bottom half of the texture to the wall.

It is possible for texture coordinates of a vertex to be greater than 1.0. When you assign texture coordinates to a vertex that are not in the range of 0.0 to 1.0 inclusive, you should also set the texture addressing mode. For further information, see Texture Addressing Modes.


Texture Addressing Modes

This section describes the purpose and use of Direct3D texture addressing modes. It is organized into the following topics:

  • What Are Texture Addressing Modes?
  • About the Wrap Texture Address Mode
  • About the Mirror Texture Address Mode
  • About the Clamp Texture Address Mode
  • About the Border Color Texture Address Mode
  • Setting and Retrieving Texture Addressing Modes
  • Texture Addressing Modes and Texture Wrapping


What Are Texture Addressing Modes?

Your Direct3D application can assign texture coordinates to any vertex of any primitive. For details, see Texture Coordinates. Typically, the U and V texture coordinates that you assign to a vertex will be in the range of 0.0 to 1.0 inclusive. However, by assigning texture coordinates outside that range, you can create certain special texturing effects.

You control what Direct3D does with texture coordinates that are outside the [0.0, 1.0] range by setting the texture addressing mode. For instance, you can have your application set the texture addressing mode such that a texture is tiled across a primitive. The following topics contain additional details:

  • About the Wrap Texture Address Mode
  • About the Mirror Texture Address Mode
  • About the Clamp Texture Address Mode
  • About the Border Color Texture Address Mode


About the Wrap Texture Address Mode

The "wrap" texture address mode, identified by the D3DTADDRESS_WRAP member of the D3DTEXTUREADDRESS enumerated type, makes Direct3D repeat the texture on every integer junction. Suppose, for example, your program creates a square primitive and specifies texture coordinates of (0.0,0.0), (0.0,3.0), (3.0,3.0), and (3.0,0.0). Setting the texture addressing mode to D3DTADDRESS_WRAP will result in the texture being applied three times in both the U and V directions. This is illustrated in the following figure.

The effects of this texture address mode are similar to, but distinct from, those of the "mirror" mode. For more information, see About the Mirror Texture Address Mode.


About the Mirror Texture Address Mode

The "mirror" texture address mode, identified by the D3DTADDRESS_MIRROR member of the D3DTEXTUREADDRESS enumerated type, causes Direct3D will mirror the texture at every integer boundary. Suppose, for example, your program creates a square primitive and specifies texture coordinates of (0.0,0.0), (0.0,3.0), (3.0,3.0), and (3.0,0.0). Setting the texture addressing mode to D3DTADDRESS_MIRROR will result in the texture being applied three times in both the U and V directions. Every other row and column that it is applied to will be a mirror image of the preceding row or column. This is illustrated in the following figure.

The effects of this texture address mode are similar to, but distinct from, those of the "wrap" mode. For more information, see About the Wrap Texture Address Mode.


About the Clamp Texture Address Mode

The "clamp" texture address mode, identified by the D3DTADDRESS_CLAMP member of the D3DTEXTUREADDRESS enumerated type, causes Direct3D to clamp your texture coordinates to the [0.0, 1.0] range. That is, it will apply the texture once, then "smear" the color of edge pixels. For instance, suppose that your program creates a square primitive and assigns texture coordinates of (0.0,0.0), (0.0,3.0), (3.0,3.0), and (3.0,0.0) to the primitive's vertices. Setting the texture addressing mode to D3DTADDRESS_CLAMP will result in the texture being applied once. The pixel colors at the top of the columns and the end of the rows are extended to the top and right of the primitive respectively. This is illustrated in the following figure:


About the Border Color Texture Address Mode

The "border color" texture address mode, identified by the D3DTADDRESS_BORDER member of the D3DTEXTUREADDRESS enumerated type, causes Direct3D to use an arbitrary color, known as the border color, for any texture coordinates outside the range of 0.0 through 1.0, inclusive.

This is shown in the next illustration in which the application specified that the texture be applied to the primitive using a red border.

How your application sets the border color depends on what version of the Direct3D device interface it uses. If your application uses the IDirect3DDevice3 interface, set the border color by calling IDirect3DDevice3::SetTextureStageState. Set the first parameter for the call to the desired texture stage identifier, the second parameter to the D3DTSS_BORDERCOLOR stage state value, and the third parameter to the new RGBA border color.

If your application stills uses the legacy IDirect3DDevice2 interface, you can set the border color by calling IDirect3DDevice2::SetRenderState method, specifying the D3DRENDERSTATE_BORDERCOLOR render state value and the new RGBA border color as parameters.

Note The IDirect3DDevice3::SetRenderState method (as opposed to the IDirect3DDevice2 version) still recognizes the D3DRENDERSTATE_BORDERCOLOR render state, even though it has been superseded. Instead of failing this legacy render state, the IDirect3DDevice3 implementation maps the effect of this render state to the first texture stage (stage 0). Applications should not mix the legacy render states with their corresponding texture stage states, as unpredictable results can occur.


Setting and Retrieving Texture Addressing Modes

How your application sets and retrieves texture addressing modes depends largely on which version of the Direct3D device interface it uses. When performing multiple texture blending by way of the IDirect3DDevice3 interface, you can set texture addressing modes for individual texture stages by calling the IDirect3DDevice3::SetTextureStageState method. Specify the desired texture stage identifier in the first parameter. Set the second parameter to D3DTSS_ADDRESS to change both the U and V texture addressing modes simultaneously, or use the D3DTSS_ADDRESSU or D3DTSS_ADDRESSV values to update the U or V addressing modes individually. The third parameter you pass to SetTextureStageState determines which mode is being set; this can be any one of the members of the D3DTEXTUREADDRESS enumerated type. To retrieve the current texture address mode for a given texture stage, call IDirect3DDevice3::GetTextureStageState, using the D3DTSS_ADDRESS, D3DTSS_ADDRESSU, or D3DTSS_ADDRESSV members of the D3DTEXTURESTAGESTATETYPE enumeration to identify about which address mode you want information.

If your application uses the IDirect3DDevice2 interface, you set texture addressing modes by calling the IDirect3DDevice2::SetRenderState method, using the D3DRENDERSTATE_TEXTUREADDRESS render state to simultaneously set U and V texture addressing. You can set U and V addressing individually with the D3DRENDERSTATE_TEXTUREADDRESSU or D3DRENDERSTATE_TEXTUREADDRESSV render states. Like their newer SetTextureStageState counterparts, these render states also use the values from D3DTEXTUREADDRESS enumerated type.

Note The IDirect3DDevice3::SetRenderState method (as opposed to the IDirect3DDevice2 version) still recognizes the D3DRENDERSTATE_TEXTUREADDRESS, D3DRENDERSTATE_TEXTUREADDRESSU, D3DRENDERSTATE_TEXTUREADDRESSV render states, even though they have been superseded. Instead of failing these legacy render states, the IDirect3DDevice3 implementation maps their effects to the first texture stage (stage 0). Applications should not mix the legacy render states with their corresponding texture stage states, as unpredictable results can occur.


Texture Addressing Modes and Texture Wrapping

Direct3D enables applications to perform texture wrapping. It is important to note that setting the texture addressing mode to D3DTADDRESS_WRAP is not the same as performing texture wrapping. Setting the texture addressing mode to D3DTADDRESS_WRAP results in multiple copies of the source texture being applied to the current primitive, and enabling texture wrapping changes how the system rasterizes textured polygons. For details, see Texture Wrapping.

Enabling texture wrapping effectively makes texture coordinates outside the [0.0, 1.0] range invalid, and the behavior for rasterizing such "delinquent" texture coordinates is undefined in this case. When texture wrapping is enabled, texture addressing modes are not used. Take care that your application does not specify texture coordinates lower than 0.0 or higher than 1.0 when texture wrapping is enabled.


Texture Handles and Texture Interfaces

Direct3D provides two methods of manipulating and controlling textures, texture handles and texture interfaces. Texture handles are obsolete. They were used in applications that utilized the IDirect3D and IDirect3D2 interfaces. For details, see Texture Handles.

With the introduction of the IDirect3D3 interface, you now create and use textures through texture interface pointers. Obtain a texture interface pointer by querying the DirectDrawSurface object for the IDirect3DTexture2 interface by calling the surface's IUnknown::QueryInterface method (use the IID_IDirect3DTexture2 reference identifier).

With the advent of texture interfaces in Direct3D, powerful new texturing features are also realized. Texture interfaces support the blending of up to eight textures onto a primitive at once. New texture blending operations have been also added. For details, see Texture Interfaces.


Palettized Textures

Direct3D devices can support texturing from texture surfaces that use attached palettes. These types of textures are sometimes called "palettized textures." A palettized texture is a DirectDrawSurface object, created with the DDSCAPS_TEXTURE capability, that uses one of the DDPF_PALETTEINDEXEDn pixel formats (where n is 1, 2, 4, or 8). These capabilities are included in the DDSURFACEDESC2 structure that you use to create a texture (and the DDPIXELFORMAT structure that the description contains). Like all palettized surfaces, instead of a color, each pixel is an index into a table of values held within an attached DirectDrawPalette object. For more information about creating and using palettized surfaces, see Surfaces and Palettes in the DirectDraw documentation. As you should always do when checking texture-related device capabilities, be sure to verify the supported texture pixel formats by calling the IDirect3DDevice3::EnumTextureFormats method.

To prepare a palettized texture

  1. Check DirectDraw and Direct3D capabilities as described in this section.
  2. Create a surface of the desired dimensions that includes the DDSCAPS_TEXTURE capability and uses one of the DDPF_PALETTEINDEXEDn pixel formats.
  3. Create and initialize a DirectDrawPalette object. For more information, see Palettes in the DirectDraw documentation. (To use an alpha-only palettized texture, include the DDPCAPS_ALPHA capability when you create the palette. See the reference for IDirectDraw4::CreatePalette for more information.)
  4. Attach the palette to the surface by calling the IDirectDrawSurface4::SetPalette method for the texture surface.

Note If you create a palettized texture surface, but neglect to attach a palette, your application will cause an access violation within Direct3D Immediate Mode during rendering.

The palettes you use with palettized textures need not be limited to color data. In some cases, devices support texture palettes that also contain alpha information. If so, DirectDraw will expose the DDPCAPS_ALPHA palette capability flag when you call the IDirectDraw4::GetCaps method—the flag is found in the dwPalCaps member of the associated DDCAPS structure. If the rendering device can perform texturing from alpha-capable palettized textures, it will expose the D3DPTEXTURECAPS_ALPHAPALETTE capability when you call IDirect3DDevice3::GetCaps. (The D3DPTEXTURECAPS_ALPHAPALETTE flag can be found in the two D3DPRIMCAPS structures contained by the D3DDEVICEDESC structure you pass with the call.)


Texture Handles

Texture handles are primarily provided for backward compatibility. New applications should use texture interface pointers. See Texture Interfaces.

The IDirect3D and IDirect3D2 interfaces are used when programming with Direct3D texture handles. A Direct3D texture is a DirectDraw surface. You can use a DirectDraw surface as a texture map by calling the IDirectDrawSurface4::QueryInterface method to retrieve an IDirect3DTexture2 interface. Use the IDirect3DTexture2 interface to load textures, retrieve handles, and track changes to palettes.

A texture map created with the IDirect3DTexture2 interface must be associated with a 3-D device. A texture handle identifies the coupling of a texture map and a device. A given texture can be associated with more than one device. When your application calls the IDirect3DTexture2::GetHandle method to associate a texture with a device, Direct3D validates it to ensure that the device supports the specified type of texture format and dimensions. The GetHandle method returns the texture handle if this validation succeeds. Your application can then use texture handles as parameters to render states. For details, see Render States.

Applications can use handles obtained using IDirect3DTexture or IDirect3DTexture2 for a given device interface interchangeably.

The IDirect3DTexture2 interface eliminates some unimplemented methods from the IDirect3DTexture interface.

This section presents information on creating and rendering with texture handles in the topics listed hereafter:

  • Creating a Texture Handle
  • Rendering with Texture Handles


Creating a Texture Handle

The following example demonstrates how to create an IDirect3DTexture2 interface. It also illustrates the process of obtaining a texture handle by calling the IDirect3DTexture2::GetHandle method. It then loads the texture using the IDirect3DTexture2::Load method. (Explicitly loading the texture in this way, however, is only required if you created the texture with the DDCAPS_ALLOCONLOAD surface capability.) Note that the DirectDraw surface you query must have the DDSCAPS_TEXTURE capability to support a Direct3D texture. See Creating Surfaces and DDSCAPS.

// This code fragment assumes that lpDDS is a valid pointer to
// a DirectDraw surface, and that lpD3DDevice is a valid pointer to
// an IDirect3DDevice3 interface.

LPDIRECT3DTEXTURE2 lpD3DTexture2;
D3DTEXTUREHANDLE d3dhTextureHandle;

// Get the texture interface pointer.
lpDDS->QueryInterface( IID_IDirect3DTexture2,
                       &lpD3DTexture2);

// Associate the texture with a device.
lpD3DTexture2->GetHandle( lpD3DDevice,
                          d3dhTextureHandle);

// Load the texture.
lpD3DTexture2->Load(lpD3DTexture2);

Note Loading a texture with the IDirect3DTexture2::Load method allocates the memory for the texture. Once this is done, your application may load a bitmap onto the surface associated with the texture from a resource or a file. Direct3D uses device-independent bitmaps (DIBs) as texture bitmaps. For details, see the documentation for DIB in the Platform SDK.


Rendering with Texture Handles

After your program creates a texture handle and loads a bitmap onto the texture's surface, it may use the texture for rendering. Texture handles can be used to set the texture-related rendering states whether your application utilizes the DrawPrimitive methods or execute buffers. If it uses the DrawPrimitive methods, all rendering states are set by invoking the IDirect3DDevice3::SetRenderState method. Pass the texture-related rendering state as the first parameter. The second parameter must be the texture's handle.

When an application sets a texture as the current texture, Direct3D applies it to all primitives that it renders with the DrawPrimitive methods. For further information, see Current Texture.

Your application controls the mapping of texture coordinates to screen coordinates by setting the texture-addressing rendering state. See Texture Addressing State.

On some 3-D hardware, applications can also enable or disable perspective correction. Many 3-D cards apply texture perspective correction unconditionally. Direct3D perspective correction is enabled by default. See Texture Perspective State.

Direct3D sports a powerful set of texture filtering capabilities. For further information, see Texture Filtering and Texture Filtering State.

When it applies a texture to a primitive's surface, your application can blend the texture's texel colors with the current color of a primitive. It can only blend one texture at a time if it uses texture handles. See Texture Blending State.

Applications that render with execute buffers use texture handles. Invoke the IDirect3DDevice3::SetRenderState method and pass the D3DRENDERSTATE_TEXTUREHANDLE render state (part of the D3DRENDERSTATETYPE enumerated type) as the value of the first parameter. Set the texture handle as the second parameter.


Texture Interfaces

Applications that create an IDirect3D3 interface can take advantage of the new texturing features in Direct3D. Using IDirect3DTexture2 interface pointers, rather than texture handles, Direct3D can now perform multiple texturing if the user's hardware supports it. For more information, see Multiple Texture Blending.

This section presents information on creating and rendering with texture interface pointers in the following topics:

  • Obtaining a Texture Interface Pointer
  • Rendering with Texture Interface Pointers


Obtaining a Texture Interface Pointer

Textures under the IDirect3D3 interface are DirectDraw surfaces, just as textures are when programming with texture handles. Therefore, the first step in obtaining a texture interface pointer is to create a DirectDraw surface with the DDSCAPS_TEXTURE capability set. See Creating Surfaces , DDSCAPS, and DDSCAPS2.

Once the surface is created, your application can retrieve a pointer to its texture interface. To do so, simply query the surface for its IDirect3DTexture2 interface. (If you created the texture with the DDSCAPS_ALLOCONLOAD flag, your application must also load the texture by invoking the IDirect3DTexture2::Load method before you can place any images in the texture.)

The following code fragment illustrates the process of creating a texture from an existing DirectDrawSurface object's interface. It also demonstrates how to load a texture.

// This code fragment assumes that lpDDS is a valid pointer to
// a DirectDraw surface that was created with the DDSCAPS_TEXTURE
// surface capability, and that lpD3D3 is a valid pointer to
// an IDirect3D3 interface.

LPDIRECT3DTEXTURE2 lpD3DTexture2;

// Get the texture interface.
lpDDS->QueryInterface(IID_IDirect3DTexture2, (void**)&lpD3DTexture2);

// Load the texture.
// (This only applies to textures that were
// created with the DDSCAPS_ALLOCONLOAD flag.
lpD3DTexture2->Load(lpD3DTexture2);

Note Loading a texture with the IDirect3DTexture2::Load method allocates the memory for the texture. Once this is done, a bitmap may be loaded from a resource or a file onto the surface associated with the texture by using DirectDraw blitting methods. (In the event that blitting isn't supported, you can access the surface memory directly by using the DirectDraw IDirectDrawSurface4::Lock and IDirectDrawSurface4::Unlock methods.)


Rendering with Texture Interface Pointers

As part of the multitexturing functionality of that was introduced in the IDirect3DDevice3 interface, Direct3D supports texture stages. Each texture stage contains a texture and operations that can be performed on the texture. The textures in the texture stages form the set of current textures. For more information, see Multiple Texture Blending. The state of each texture is encapsulated in its texture stage. Therefore, the state of each texture must be set with the IDirect3DDevice3::SetTextureStageState method. Pass the stage number (0-7) as the value of the first parameter. Set the value of the second parameter to a member of the member of the D3DTEXTURESTAGESTATETYPE enumerated type. The final parameter is the state value for the particular texture state.

Using texture interface pointers, your application can render a blend of up to eight textures. Set the current textures by invoking the IDirect3DDevice3::SetTexture method. Direct3D will blend all current textures onto the primitives that it renders.

Your application can set the texture wrapping state for the current textures by calling the IDirect3DDevice3::SetRenderState method. Pass a value from D3DRENDERSTATE_WRAP0 through D3DRENDERSTATE_WRAP7 as the value of the first parameter, and use a combination of the D3DWRAP_U or D3DWRAP_V flags to enable wrapping in the u or v directions.

Your application can also set the texture perspective and texture filtering states. See Texture Perspective State, Texture Filtering, and Texture Filtering State.


Texture Filtering

When Direct3D renders a primitive, it maps the 3-D primitive onto a 2-D screen. If the primitive has a texture, Direct3D must use that texture to produce a color for each pixel in the primitive's 2-D rendered image. For every pixel in the primitive's on-screen image, it must obtain a color value from the texture. This process is called texture filtering.

When a texture filter operation is performed, the texture being used is typically also being magnified or minified. In other words, it is being mapped onto a primitive image that is larger or smaller than itself. Magnification of a texture can result in many pixels being mapped to one texel. The result can be a chunky appearance. Minification of a texture often means that a single pixel is mapped to many texels. The resulting image can be blurry or aliased. To resolve these problems, some blending of the texel colors must be performed to arrive at a color for the pixel.

Direct3D simplifies the complex process of texture filtering. It provides developers with three types of texture filtering—linear filtering, anisotropic filtering, and mipmap filtering. If you select no texture filtering, Direct3D utilizes a technique called nearest point sampling.

Each type of texture filtering has advantages and disadvantages. For instance, linear texture filtering can produce jagged edges or a chunky appearance in the final image. However, it is a computationally low-overhead method of texture filtering. On the other hand, filtering with mipmaps usually produces the best results, especially when combined with anisotropic filtering. However it requires the most memory of the techniques that Direct3D supports.

If your application uses texture handles, it should set the current texture filtering method by invoking the IDirect3DDevice3::SetRenderState method. The first parameter must be either D3DRENDERSTATE_TEXTUREMAG or D3DRENDERSTATE_TEXTUREMIN. It must pass a member of the D3DTEXTUREFILTER enumerated type as the value of the second parameter. See Texture Filtering State.

Applications that use texture interface pointers should set the current texture filtering method by calling the IDirect3DDevice3::SetTextureStageState method. Set the value of the first parameter to the integer index number (0-7) of the texture for which you are selecting a texture filtering method. Pass either D3DTSS_MAGFILTER, D3DTSS_MINFILTER, or D3DTSS_MIPFILTER as the value of the second parameter. Set the third parameter to a member of the D3DTEXTUREMAGFILTER, D3DTEXTUREMINFILTER, or D3DTEXTUREMIPFILTER enumerated types respectively.

This section presents the texture filtering methods that Direct3D supports. It is organized into the following topics:

  • Nearest Point Sampling
  • Linear Texture Filtering
  • Anisotropic Texture Filtering
  • Texture Filtering With Mipmaps


Nearest Point Sampling

Applications are not required to use texture filtering. Direct3D can be set so that it computes the texel address, which often does not evaluate to integers, and simply copies the color of the texel with the closest integer address. This process is called nearest point sampling. This can be a fast and efficient way to process textures if the size of the texture is similar to the size of the primitive's image on the screen. If not, the texture will need to be magnified or minified. The result can be a chunky, aliased, or blurred image.

Your application can select nearest point sampling by calling the IDirect3DDevice3::SetTextureStageState method. Set the value of the first parameter to the integer index number (0-7) of the texture for which you are selecting a texture filtering method. Pass D3DTEXTUREMAGFILTER as the value of the second parameter if you are setting the magnification filter. Pass D3DTEXTUREMIPFILTER as the value of the second parameter if you are setting the minification filter. Pass D3DTEXTUREMIPFILTER as the value of the second parameter if you are setting the mipmapping filter. Set the third parameter to D3DTFG_POINT if you are setting the magnification filter, D3DTFN_POINT if you are setting the minification filter, or D3DTFP_POINT if you are setting the mipmap filter. For more information, see Texture Filtering State.

You should use nearest point sampling carefully, as it can sometimes cause graphic artifacts when the texture is sampled at the boundary between two texels. This boundary is the position along the texture (u or v) at which the sampled texel transitions from one texel to the next. When point sampling is used, the system chooses one sample texel or the other, and the result can change abruptly from one texel to the next texel as the boundary is crossed. This effect can appear as undesired graphic artifacts in the displayed texture. (When linear filtering is used, the resulting texel is computed from both adjacent texels and smoothly blends between them as the texture index moves through the boundary.)

This effect can be seen when mapping a very small texture onto a very large polygon: an operation often called "magnification." For example, when using a texture that looks like a checkerboard, nearest point sampling results in a larger checkerboard that shows distinct edges. By contrast, linear texture filtering results in an image where the checkerboard colors vary smoothly across the polygon.

In most cases, applications can receive the best results by avoiding nearest point sample wherever possible. The majority of hardware today is optimized for linear filtering, so your application should not suffer degraded performance. If the effect you desire absolutely requires the use of the nearest point sampling—such as when using textures to display readable text characters—then your application should be extremely careful to avoid sampling at the texel boundaries, which might result in undesired effects. The following screen capture shows what these artifacts can look like:

Notice that the two squares in the top-right of the group appear different that their neighbors. To avoid graphic artifacts like these, you should start by understanding Direct3D texture sampling rules for nearest-point filtering. Direct3D maps a floating-point texture coordinate ranging from [0.0, 1.0] (0.0 to 1.0, inclusive) to an integer texel space value ranging from [–0.5, n – 0.5], where n is the number of texels in a given dimension on the texture. The resulting texture index is rounded to the nearest integer. This mapping can introduce sampling inaccuracies at texel boundaries.

For a simple example, imagine an application that renders polygons with the D3DTADDRESS_WRAP texture addressing mode. Using the mapping employed by Direct3D, the u texture index maps as follows for a texture with a width of 4 texels:

Notice that the texture coordinates—0.0 and 1.0—for this illustration are exactly at the boundary between texels. Using the method by which Direct3D maps values, the texture coordinates range from [–0.5, 4 – 0.5], where 4 is the width of the texture. For this case, the sampled texel will be the 0th texel for a texture index of 1.0. However, if the texture coordinate was only slightly less than 1.0, the sampled texel would be the nth texel instead of the 0th texel.

The implication of this is that magnifying a small texture using texture coordinates of exactly 0.0 and 1.0 with nearest-point filtering on a screen-space aligned triangle will result in pixels for which the texture map is sampled at the boundary between texels. Any inaccuracies in the computation of texture coordinates, however small, will result in artifacts along the areas in the rendered image which correspond to the texel edges of the texture map.

Performing this mapping of floating point texture coordinates to integer texels with perfect accuracy is difficult, computationally expensive, and generally not necessary. Most hardware implementations use an iterative approach for computing texture coordinates at each pixel location within a triangle. Iterative approaches tend to hide these inaccuracies somewhat because the errors are accumulated evenly during iteration.

The Direct3D reference rasterizer uses a direct-evaluation approach for computing texture indices at each pixel location. Direct evaluation differs from the iterative approach in that any inaccuracy in the operation exhibits a more random error distribution. The result of this is that the sampling errors occurring at the boundaries can be more noticeable since the reference rasterizer does not perform this operation with perfect accuracy (which is, again, difficult and very expensive with floating point texture coordinates).

The best approach is to use nearest-point filtering only when necessary. When you must use it, it is recommended that you offset texture coordinates slightly from the boundary positions to avoid artifacts.


Linear Texture Filtering

Direct3D uses a form of linear texture filtering called bilinear filtering. Like nearest point sampling, bilinear texture filtering first computes a texel address, which is usually not an integer address. Just as in nearest point sampling, if then finds the texel whose integer address is closest the computed address. In addition, the Direct3D rendering module will compute a weighted average of the texels that are immediately above, below, to the left of, and to the right of the nearest sample point.

Select bilinear texture filtering by invoking the IDirect3DDevice3::SetTextureStageState method. Set the value of the first parameter to the integer index number (0-7) of the texture for which you are selecting a texture filtering method. Pass D3DTEXTUREMAGFILTER as the value of the second parameter if you are setting the magnification filter. Pass D3DTEXTUREMIPFILTER as the value of the second parameter if you are setting the minification filter. Pass D3DTEXTUREMIPFILTER as the value of the second parameter if you are setting the mipmapping filter. Set the third parameter to D3DTFG_LINEAR if you are setting the magnification filter, D3DTFN_LINEAR if you are setting the minification filter, or D3DTFP_LINEAR if you are setting the mipmap filter. For more information, see Texture Filtering State.


Anisotropic Texture Filtering

Anisotropy is the distortion visible in the texels of a 3-D object whose surface is oriented at an angle with respect to the plane of the screen. When a pixel from an anisotropic primitive is mapped into texels, its shape is distorted. Direct3D measures the anisotropy of a pixel as the elongation (length divided by width) of a screen pixel that is inverse-mapped into texture space.

Anisotropic texture filtering can be used in conjunction with linear texture filtering or mipmap texture filtering to improve rendering results. Your application enables anisotropic texture filtering by calling the IDirect3DDevice3::SetTextureStageState method. Set the value of the first parameter to the integer index number (0-7) of the texture for which you are selecting a texture filtering method. Pass D3DTEXTUREMAGFILTER as the value of the second parameter if you are setting the magnification filter. Pass D3DTEXTUREMINFILTER as the value of the second parameter if you are setting the minification filter. Set the third parameter to D3DTFG_ANISOTROPIC if you are setting the magnification filter, or D3DTFN_ANISOTROPIC if you are setting the minification filter. For more information, see Texture Filtering State.

Your program must also set the degree of anisotropy to a value greater than zero and less than one. Do this by calling the IDirect3DDevice3::SetTextureStageState method. Set the value of the first parameter to the integer index number (0-7) of the texture for which you are setting the degree of isotropy. Pass D3DTSS_MAXANISOTROPY as the value of the second parameter. The final parameter should be the degree of isotropy.

Disable isotropic filtering by setting the degree of isotropy to one (any value larger than one enables it). Check the D3DPRASTERCAPS_ANISOTROPY flag in the D3DPRIMCAPS structure to determine the possible range of values for the degree of anisotropy.


Texture Filtering With Mipmaps

Mipmap textures are used in 3-D scenes to decrease the time required for rendering a scene. They also improve the scene's realism. However, they often require large amounts of memory.

This section presents the fundamentals of using mipmap textures in 3-D scenes in the following topics:

  • What Is a Mipmap?
  • Creating a Set of Mipmaps
  • Selecting and Displaying a Mipmap


What Is a Mipmap?

A mipmap is a sequence of textures, each of which is a progressively lower resolution representation of the same image. The height and width of each image, or level, in the mipmap is a power of two smaller than the previous level. Mipmaps do not have to be square.

A high-resolution mipmap image is used for objects that are close to the viewer. Lower-resolution images are used as the object moves farther away. Mipmapping improves the quality of rendered textures at the expense of using more memory.

Direct3D represents mipmaps 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. That level has, in turn, an attachment that is the next level in the mipmap, and so on down to the lowest resolution level of the mipmap.

The following set of illustrations shows an example. The set of bitmap textures represents a sign on the side of a container in a 3-D, first-person game. When created as a mipmap, the highest-resolution texture is first in the set. Each succeeding texture in the mipmap set is a power of 2 smaller in height and width. In this case, the maximum-resolution mipmap is 256 pixels by 256 pixels. The next, texture is 128x128. The last texture in the chain is 64x64.

This sign would have a maximum distance from which it is visible. If the player begins far away from the sign, the game would display the smallest texture in the mipmap chain, which in this case the 64x64 texture.

As the player moves the point of view closer to the sign, progressively higher-resolution textures in the mipmap chain are used.

The highest-resolution texture is used when the user's point of view is at the minimum allowable distance from the sign.

This is a computationally lower-overhead way of simulating perspective effects for textures. Rather than render a single texture to many resolutions, it is faster to use multiple textures at varying resolutions.

Direct3D is able to assess which texture in a mipmap set is the closest resolution to the desired output and map pixels into its texel space. If the resolution of the final image is between the resolutions of the textures in the mipmap set, Direct3D can examine texels in both of the mipmaps and blend their color values together.

If you want your application to use mipmaps, it must build a set of mipmaps. For details, see Creating a Set of Mipmaps. If your program uses texture handles, it must then select the mipmap set as the current texture. For more information, see Current Texture. If it uses texture interface pointers, it must select the mipmap set as the first texture in the set of current textures. For more information, see Multiple Texture Blending.

Next, your program must set the filtering method that Direct3D uses to sample texels. The fastest method of mipmap filtering is to have Direct3D select the nearest texel. Use the D3DTFP_POINT enumerated value to select this. Direct3D can produce better filtering results if your application uses the D3DTFP_LINEAR enumerated value. This will select the nearest mipmap, then compute a weighted average of the texels surrounding the location in the texture to which the current pixel maps.


Creating a Set of Mipmaps

To create a surface representing a single level of a mipmap, specify the DDSCAPS_MIPMAP and DDSCAPS_COMPLEX flags in the DDSURFACEDESC structure passed to the IDirectDraw4::CreateSurface method. Because all mipmaps are also textures, the DDSCAPS_TEXTURE flag must also be specified.

It is possible to create each level manually and build the chain by using the IDirectDrawSurface4::AddAttachedSurface method. However, this is not recommended. Many 3-D hardware vendors optimize their drivers for the IDirectDraw4::CreateSurface method. Applications that build mipmap chains with calls to IDirectDrawSurface4::AddAttachedSurface may find that mipmapping is not as fast.

The following example demonstrates how your application can use the IDirectDraw4::CreateSurface method to build a chain of five mipmap levels of sizes 256×256, 128×128, 64×64, 32×32, and 16×16:

// This code fragment assumes that the variable lpDD is a
// valid pointer to a DirectDraw interface.

DDSURFACEDESC       ddsd;
LPDIRECTDRAWSURFACE4 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))
.
.
.

You can omit the number of mipmap levels, in which case the IDirectDraw4::CreateSurface method 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 IDirectDraw4::CreateSurface will create the number of levels you specify, with a minimum level size of 1×1.

Note: Each surface in a mipmap chain has dimensions that are one-half that of the previous surface in the chain. If the top-level mipmap has dimensions of 256×128, the dimensions of the second-level mipmap are 128×64, the third-level is 64×32, and so on down to 2×1. If you explicitly specify dimensions in the dwWidth and dwHeight members, you should be aware of some restrictions. Namely, you cannot request a number of mipmap levels in dwMipMapCount that would cause either the width or height of any mipmap in the chain to be smaller than 1. Take the very simple case of a 4×2 top-level mipmap surface: the maximum value allowed for dwMipMapCount here is 2: the top-level dimensions are 4×2, and the dimensions for the second level 2×1. A value larger than 2 in dwMipMapCount would result in a fractional value in the height of the second-level mipmap, and is therefore disallowed.

After your application creates the mipmap surfaces, it needs to associate the surface with a texture. If you are using texture handles, use the procedures outlined in Creating a Texture Handle. If you are using texture interface pointers, see Obtaining a Texture Interface Pointer.


Selecting and Displaying a Mipmap

If your program uses texture handles, it must assign the handle of the mipmap texture as the current texture. For details, see Current Texture.

If your application uses texture interface pointers, it must set the mipmap texture set as the first texture in the list of current textures. For more information, see Multiple Texture Blending.

After your application selects the mipmap texture set, it must assign values from the D3DTEXTUREFILTER enumerated type to the D3DRENDERSTATE_TEXTUREMAG and D3DRENDERSTATE_TEXTUREMIN render states. Direct3D will then automatically perform mipmap texture filtering.

Your application can also manually traverse a chain of mipmap surfaces by using the IDirectDrawSurface4::GetAttachedSurface method and specifying the DDSCAPS_MIPMAP and DDSCAPS_TEXTURE flags in the DDSCAPS structure. The following example traverses a mipmap chain from highest to lowest resolutions:

LPDIRECTDRAWSURFACE lpDDLevel, lpDDNextLevel;
DDSCAPS ddsCaps;
HRESULT ddres;

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))
{
    // Code to handle the error goes here
}
.
.
.

Applications need to manually traverse a mipmap chain to load bitmap data into each surface in the chain. This is typically the only reason to traverse the chain.

Direct3D explicitly stores the number of levels in a mipmap chain. When an application obtains the surface description of a mipmap (by calling the IDirectDrawSurface4::Lock or IDirectDrawSurface4::GetSurfaceDesc method), the dwMipMapCount member of the DDSURFACEDESC structure contains the number of levels in the mipmap, including the top level. For levels other than the top level in the mipmap, the dwMipMapCount member specifies the number of levels from that mipmap to the smallest mipmap in the chain.


Texture Wrapping

This section presents information on wrapping textures around 3-D primitives. The discussion is divided into the following topics:

  • What is Texture Wrapping?
  • Using Texture Wrapping

Note Texture wrapping should not be confused with the similarly named texture addressing modes. For more information, see Texture Addressing Modes and Texture Wrapping and Texture Addressing Modes.


What is Texture Wrapping?

Texture wrapping, in short, changes the basic way in which Direct3D rasterizes textured polygons using the texture coordinates specified for each vertex. (Don't confuse texture wrapping with the "wrap" texture addressing mode. For more information, see Texture Addressing Modes and Texture Wrapping.) While rasterizing a polygon, the system interpolates between the texture coordinates at each of the polygon's vertices to determine the texels that should be used for every pixel of the polygon. Normally, the system treats the texture as a 2-D plane, interpolating new texels by taking the shortest route from point A within a texture to point B. If point A represents the U, V position (0.8, 0.3), and point B is at (0.1,.9), the line of interpolation would look like:

Note that the shortest distance between A and B in the preceding illustration goes through the middle of the texture. Enabling U or V texture coordinate wrapping changes how Direct3D perceives the shortest route between texture coordinates in the U and V directions. By definition, texture wrapping causes the rasterizer to take the shortest route between texture coordinate sets, assuming that 0.0 and 1.0 are coincident. The last bit is the tricky part: you can imagine that enabling texture wrapping in one direction causes the system to treat a texture as though it were "wrapped" around a cylinder. For example, take the following illustration:

The preceding diagram shows how wrapping in the U direction affects the way the system interpolates texture coordinates. Using the same points we used in the example for "normal", or non-wrapped, textures, you can see that the shortest route between points A and B is no longer across the middle of the texture; it's now across the border where 0.0 and 1.0 exist together. Wrapping in the V direction is similar, only it "wraps" the texture around a cylinder that is lying on its side. Wrapping in both the U and V directions is a little more complex. In this situation, you might envision the texture as a torus, or doughnut.

The most common practical application for texture wrapping is to perform environment mapping. Usually, an object textured with an environment map appears very reflective, showing a mirrored image of the object's surroundings in the scene. For the sake of this discussion, picture a room with four walls, each one painted with a letter R, G, B, Y and the corresponding colors: red, green, blue, and yellow. The environment map for such a simple room might look like:

Imagine that the room's ceiling is held up by a perfectly reflective, four sided, pillar. Mapping the environment map texture to the pillar is pretty simple — making it look as though it's reflecting the letters and colors as they appear on the walls isn't as easy. The following diagram shows a wire frame of the pillar with the applicable texture coordinates listed near the top vertices (the "seam" where wrapping will cross the edges of the texture is shown with a dotted line):

With wrapping enabled in the U direction, the textured pillar shows the colors and symbols from the environment map appropriately and, at the "seam" in the front of the texture, the rasterizer properly chooses the shortest route between the texture coordinates, assuming that U coordinates 0.0 and 1.0 share the same location. The textured pillar would look something like the following:

If texture wrapping wasn't enabled, the rasterizer would not interpolate in the direction needed to generate a believable, reflected, image. Rather, the area at the front of the pillar would contain a horizontally compressed version of the texels between U coordinates 0.175 and 0.875, as they pass through the center of the texture. The effect would be ruined.


Using Texture Wrapping

The process of enabling texture wrapping differs across versions the Direct3D device interfaces. If your application uses the IDirect3DDevice3 interface, you enable texture wrapping individually for each texture in the multi-texture cascade. In this case, call the IDirect3DDevice3::SetRenderState method to enable texture wrapping, passing one of the D3DRENDERSTATE_WRAP0 through D3DRENDERSTATE_WRAP7 enumerated values as the first parameter to identify which stage's wrapping state is being set. Specify the D3DWRAP_U and D3DWRAP_V flags in the second parameter to enable texture wrapping in the corresponding direction, or combine the two to enable wrapping in both directions. If you omit one or both of the flags, texture wrapping in the corresponding direction is disabled. To disable texture wrapping for a texture stage, set the value for the corresponding render state to 0.

If your application uses the legacy IDirect3DDevice2 or IDirect3DDevice interfaces, you still enable texture wrapping by calling the SetRenderState method; however, these interface versions do not support D3DRENDERSTATE_WRAP0 through D3DRENDERSTATE_WRAP7. Instead, use the D3DRENDERSTATE_WRAPU or D3DRENDERSTATE_WRAPV value in the first parameter. Specify TRUE as in the second parameter to enable wrapping, or FALSE to disable it.

Note The IDirect3DDevice3 interface does recognize the legacy D3DRENDERSTATE_WRAPU and D3DRENDERSTATE_WRAPV render states, even though they were superseded by D3DRENDERSTATE_WRAP0 through D3DRENDERSTATE_WRAP7. These older render states, when passed to the IDirect3DDevice3 version of SetRenderState, affect U and V texture wrapping for the first texture stage (stage 0).


Texture Blending

Direct3D can produce transparency effects by blending a texture with a primitive's color. It can also blend multiple textures onto a primitive. This section presents information on how texture blending is done. It is divided into the following topics:

  • Alpha Texture Blending
  • Multipass Texture Blending
  • Multiple Texture Blending
  • Light Mapping With Textures

If you want your application to use texture blending, the program should first check to see if the user's hardware supports it. The relevant information is found in the dwTextureCaps member of the D3DPRIMCAPS structure. For details on how to query the user's hardware for texture blending capabilities, see IDirect3DDevice3::GetCaps and D3DDEVICEDESC.


Alpha Texture Blending

When Direct3D renders a primitive, it generates a color for the primitive based on the primitive's material and lighting information. For details, see Lighting and Materials. If an application enables texture blending, Direct3D must then blend the texel colors of one or more textures with the primitive's current colors. Direct3D uses the following formula to determine the final color for each pixel in the primitive's image.

FinalColor = | TexelColor * SourceBlendFactor +
 | PixelColor * DestBlendFactor

In the preceding formula, FinalColor is the pixel color that is output to the target rendering surface. TexelColor stands for the color of the texel that corresponds to the current pixel. For details on how Direct3D maps pixels to texels, see Texture Filtering. SourceBlendFactor is a calculated value that Direct3D uses to determine the percentage of the texel color to apply to the final color. PixelColor is the color of the current pixel in the primitive's image. DestBlendFactor represents the percentage of the current pixel's color that will be used in the final color. The values of SourceBlendFactor and DestBlendFactor range from 0.0 or 1.0 inclusive.

As you can see from the preceding formula, a texture is not rendered as transparent at all if the SourceBlendFactor is 1.0 and the DestBlendFactor is 0.0. It is completely transparent if the SourceBlendFactor is 0.0 and the DestBlendFactor is 1.0. If an application sets these factors to any other values, the resulting texture will be blended with some degree of transparency.

Every texel in a texture has a red, a green, and a blue color value. By default, Direct3D uses the alpha values of texels as the SourceBlendFactor. Therefore, applications can control the transparency of textures by setting the alpha values in their textures.

Your application can control the blending factors with the D3DRENDERSTATE_SRCBLEND and D3DRENDERSTATE_DESTBLEND enumerated values. Invoke the IDirect3DDevice3::SetRenderState method and pass either D3DRENDERSTATE_SRCBLEND or D3DRENDERSTATE_DESTBLEND as the value of the first parameter. The second parameter must be a member of the D3DBLEND enumerated type.


Multipass Texture Blending

Direct3D applications can achieve numerous special effects by applying many textures onto a primitive in more than one pass. The common term for this is multipass texture blending. A typical use for multipass texture blending is to apply shadows to primitives in addition to whatever textures they might normally have. For more information, see Light Mapping With Textures.

All Direct3D device interfaces support multipass texture blending. Beginning with the IDirect3DDevice3 interface, DirectX is also able to apply multiple textures to primitives in a single pass, if the user's hardware supports it. For details, see Multiple Texture Blending.

If your user's hardware does not support multiple texture blending, your application can use multipass texture blending to achieve the same visual effects. However, it will not be able to sustain the frame rates that are possible when using multiple texture blending.

Applications enable multipass texture blending by invoking the IDirect3DDevice3::SetRenderState method, and passing the enumerated value D3DRENDERSTATE_ALPHABLENDENABLE as the value of the first parameter. Pass TRUE as the value of the second parameter to enable texture blending, or FALSE to disable it.

Once texture blending is enabled, your application should set the source and destination blending factors based on the effect you want to achieve. For more information on the source and destination blending factors, see Alpha Texture Blending. Applications control the source blending factors by calling the IDirect3DDevice3::SetRenderState and passing it the enumerated value D3DRENDERSTATE_SRCBLEND as the value of the first parameter. Your program can set the destination blending factor by passing D3DRENDERSTATE_DESTBLEND as the value of the first parameter to IDirect3DDevice3::SetRenderState. In either case, the second parameter must be a member of the D3DBLEND enumerated type.

Applications set the blending operation by passing D3DRENDERSTATE_TEXTUREMAPBLEND as the value of the first parameter in a call to IDirect3DDevice3::SetRenderState. The second parameter must be a member of the D3DTEXTUREBLEND enumerated type.

On each pass, your application must set the current texture. Its texel colors will be blended with the existing pixel colors in the frame buffer. For information on setting the current texture, see Current Texture.


Multiple Texture Blending

With the introduction of the IDirect3D3 and IDirect3DDevice3 interfaces, Direct3D can now blend as many as eight textures onto primitives in a single pass. The use of multiple texture blending can profoundly increase the frame rate of Direct3D applications. Applications employ multiple texture blending to apply textures, shadows, specular lighting, diffuse lighting, and other special effects in a single pass.

To blend multiple textures, applications assign textures into the set of current textures, and then create blending stages. The topics in the following list present information on how these steps are accomplished:

  • Texture Stages and the Texture Blending Cascade
  • Texture Blending Operations and Arguments
  • Assigning the Current Textures
  • Creating Blending Stages
  • Legacy Blending Modes and Texture Stages


Texture Stages and the Texture Blending Cascade

Direct3D supports single-pass multiple texture blending through the use of "texture stages." A texture stage takes two arguments and performs a blending operation on them, passing the result on for further processing or for rasterization. You could visualize a texture stage as shown in the following figure.

As the preceding illustration shows, texture stages blend two arguments by using a specified operator. Common operations include simple modulation or addition of the color or alpha components of the arguments, but more than two dozen operations are currently supported. The arguments for a stage can be an associated texture, the iterated color or alpha (iterated during Gouraud shading), arbitrary color and alpha, or the result from the previous texture stage. For more information, see Texture Blending Operations and Arguments.

The combination of arguments and operations used by multiple blending stages define a simple flow-based blending language. The results from one stage flow down to another stage, and then from that stage to the next, and so on. The idea that results flow from stage to stage to eventually be rasterized on a polygon is often called the "texture blending cascade." The following illustration shows how individual texture stages make up the texture blending cascade.

Each stage in a device has a zero-based index. Direct3D for DirectX 6.0 allows up to eight blending stages, although you should always check device capabilities to determine how many stages the current hardware supports. The first blending stage is at index 0, the second is at 1, and so on up to index 7. The system blends stages in increasing order of index.

Use only the number of stages you need; the unused blending stages are disabled by default. So, if your application only uses the first two stages, it need only set operations and arguments for stage 0 and 1, leaving the remaining stages alone. The system blends the two stages, and ignores the disabled stages.

Optimization Note If your application varies the number of stages it uses for different situations—such as four stages for some objects, and only two for others—you don't need to explicitly disable all previously used stages. If you disable the color operation for the first unused stage, all stages with a higher index will not be applied. You can disable texture mapping altogether by setting the color operation for the first texture stage (stage 0).


Texture Blending Operations and Arguments

Applications associate a blending stage with each texture in the set of current textures. As mentioned in Texture Stages and the Texture Blending Cascade, Direct3D evaluates each blending stage in order, beginning with the first texture in the set and ending with the eighth.

Direct3D applies the information from each texture in the set of current textures to the blending stage that is associated with it. Applications control what information from a given texture stage is used by calling IDirect3DDevice3::SetTextureStageState. You can set separate operations for the color and alpha channels independently, and each operation uses two arguments. Specify color channel operations by using the D3DTSS_COLOROP stage state, and D3DTSS_ALPHAOP for alpha operations–both use values from the D3DTEXTUREOP enumerated type.

Texture blending arguments use the D3DTSS_COLORARG1, D3DTSS_COLORARG2, D3DTSS_ALPHARG1, and D3DTSS_ALPHARG2 members of the D3DTEXTURESTAGESTATETYPE enumerated type. The corresponding argument values are identified using texture argument flags.

Note: You can disable a texture stage—and any subsequent texture blending stages in the cascade—by setting the color operation for that stage to D3DTOP_DISABLE. Disabling the color operation effectively disables the alpha operation as well.


Assigning the Current Textures

Direct3D maintains a list of up to eight current textures. It blends these textures onto all of the primitive it renders. Only textures created as texture interface pointers can be used in the set of current textures.

Applications call the IDirect3DDevice3::SetTexture method to assign textures into the set of current textures. The first parameter must be from the a number in the range of 0-7 inclusive. Pass the texture interface pointer as the second parameter.

The following code fragment demonstrates how a texture can be assigned into the set of current textures:

// This code fragment assumes that the variable lpd3dDev is a valid
// pointer to an IDirect3D3 interface and lpd3dTexture is a valid
// pointer to an IDirect3DTexture2 interface.

// Set the third texture.
lpd3dDev->SetTexture(2, lpd3dTexture);

Note Software devices do not support assigning a texture to more than one texture stage at a time.


Creating Blending Stages

A blending stage is a set of texture operations, together with their arguments, that define how textures are blended. When making a blending stage, applications invoke the IDirect3DDevice3::SetTextureStageState function. The first call specifies the operation that will be performed. Two additional invocations define the arguments to which the operation will be applied. The following code fragment illustrates the creation of a blending stage:

// This example assumes that lpD3DDev is a valid pointer to an
// IDirect3DDevice3 interface.

// Set the operation for the 1st texture.
lpD3DDev->SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_ADD);

// Set arg1 for the texture operation.
lpD3DDev->SetTextureStageState(0,                 // First texture
                               D3DTSS_COLORARG1,  // Set color arg 1
                               D3DTA_TEXTURE);    // Color arg 1 value

// Set arg2 for the texture operation.
lpD3DDev->SetTextureStageState(0,                 // First texture
                               D3DTSS_COLORARG2,  // Set color arg 2
                               D3DTA_DIFFUSE);    // Color arg 2 value

Texel data in textures contain color and alpha values. Programs can define separate operations for both color and alpha values in a single blending stage. Each operation (color and alpha) has its own arguments. For details, see D3DTEXTURESTAGESTATETYPE.

Although not part of the Direct3D API, the following macros can also be inserted into your program to abbreviate the code required for creating texture blending stage.

#define SetTextureColorStage( dev, i, arg1, op, arg2 )       \
   dev->SetTextureStageState( i, D3DTSS_COLOROP, op);        \
   dev->SetTextureStageState( i, D3DTSS_COLORARG1, arg1 );   \
   dev->SetTextureStageState( i, D3DTSS_COLORARG2, arg2 );

#define SetTextureAlphaStage( dev, i, arg1, op, arg2 )       \
   dev->SetTextureStageState( i, D3DTSS_ALPHAOP, op);        \
   dev->SetTextureStageState( i, D3DTSS_ALPHARG1, arg1 );    \
   dev->SetTextureStageState( i  D3DTSS_ALPHARG2, arg2 );


Legacy Blending Modes and Texture Stages

Although Direct3D still supports the texture blending render state, D3DRENDERSTATE_TEXTUREMAPBLEND, the blending modes it offers should not be used in combination with texture stage based texture blending, as the results can be unpredictable. However, you can "build" your own equivalents to the legacy blending modes by using texture stages.

This list shows the legacy blending modes (identified by the members of the D3DTEXTUREBLEND enumerated type), followed by a short example that sets up the same blend by way of texture stage states. (For all examples, the g_lpDev variable is assumed to be a valid pointer to an IDirect3DDevice3 interface):

D3DTBLEND_ADD
g_lpDev->SetTextureStageState(0, COLOROP, D3DTOP_ADD);
g_lpDev->SetTextureStageState(0, COLORARG1, D3DTA_TEXTURE);
g_lpDev->SetTextureStageState(0, COLORARG2, D3DTA_DIFFUSE);

g_lpDev->SetTextureStageState(0, ALPHAOP, D3DTOP_SELECTARG2);
g_lpDev->SetTextureStageState(0, ALPHAARG2, D3DTA_DIFFUSE);
D3DTBLEND_COPY and D3DTBLEND_DECAL
g_lpDev->SetTextureStageState(0, COLOROP, D3DTOP_SELECTARG1);
g_lpDev->SetTextureStageState(0, COLORARG1, D3DTA_TEXTURE);

g_lpDev->SetTextureStageState(0, ALPHAOP, D3DTOP_SELECTARG1);
g_lpDev->SetTextureStageState(0, ALPHAARG2, D3DTA_TEXTURE);
D3DTBLEND_DECALALPHA
g_lpDev->SetTextureStageState(0, COLOROP, D3DTOP_BLENDTEXTUREALPHA);
g_lpDev->SetTextureStageState(0, COLORARG1, D3DTA_TEXTURE);
g_lpDev->SetTextureStageState(0, COLORARG2, D3DTA_DIFFUSE);

g_lpDev->SetTextureStageState(0, ALPHAOP, D3DTOP_SELECTARG2);
g_lpDev->SetTextureStageState(0, ALPHAARG2, D3DTA_DIFFUSE);
D3DTBLEND_MODULATE
g_lpDev->SetTextureStageState(0, COLOROP, D3DTOP_MODULATE);
g_lpDev->SetTextureStageState(0, COLORARG1, D3DTA_TEXTURE);
g_lpDev->SetTextureStageState(0, COLORARG2, D3DTA_DIFFUSE);

if ( the_texture_has_an_alpha_channel )
{
    g_lpDev->SetTextureStageState(0, ALPHAOP, D3DTOP_SELECTARG1);
    g_lpDev->SetTextureStageState(0, ALPHAARG1, D3DTA_TEXTURE);
}
else
{
    g_lpDev->SetTextureStageState(0, ALPHAOP, D3DTOP_SELECTARG2);
    g_lpDev->SetTextureStageState(0, ALPHAARG2, D3DTA_DIFFUSE);
}
D3DTBLEND_MODULATEALPHA
g_lpDev->SetTextureStageState(0, COLOROP, D3DTOP_MODULATE);
g_lpDev->SetTextureStageState(0, COLORARG1, D3DTA_TEXTURE);
g_lpDev->SetTextureStageState(0, COLORARG2, D3DTA_DIFFUSE);

g_lpDev->SetTextureStageState(0, ALPHAOP, D3DTOP_MODULATE);
g_lpDev->SetTextureStageState(0, ALPHAARG1, D3DTA_TEXTURE);
g_lpDev->SetTextureStageState(0, ALPHAARG2, D3DTA_DIFFUSE);
D3DTBLEND_DECALMASK and D3DTBLEND_MODULATEMASK
Not supported in DirectX 6.0.


Light Mapping With Textures

For an application to realistically render a 3-D scene, it must take into account the effect that light sources have on the appearance of the scene. Although techniques such as flat and Gouraud shading are valuable tools in this respect, they can be insufficient for your needs. Direct3D supports multipass and multiple texture blending. These capabilities enable your application to render scenes whose appearance is much more realistic than scenes rendered with shading techniques alone. By applying one or more light maps, your application can map areas of light and shadow onto its primitives.

A light map is a texture or group of textures that contain information about lighting in a 3-D scene. You can store the lighting information in the alpha values of the light map, in the color values, or in both.

If you implement light mapping using multipass texture blending, your program should render the light map onto its primitives on the first pass. It should use a second pass to render the base texture. The exception to this is specular light mapping. In that case, render the base texture first, then add the light map.

Multiple texture blending enables your application to render both the light map and the base texture in one pass. If your user's hardware provides for multiple texture blending, your application should take advantage of it when performing light mapping. It will significantly improve your application's performance.

Using light maps, a Direct3D application can achieve a variety of lighting effects when it renders primitives. It can not only map monochrome and colored lights in a scene, it can add details such as specular highlights and diffuse lighting.

Information on using Direct3D texture blending to perform light mapping is presented in the following topics:

  • Monochrome Light Maps
  • Color Light Maps
  • Specular Light Maps
  • Diffuse Light Maps


Monochrome Light Maps

Some older 3-D accelerator boards do not support texture blending using the alpha value of the destination pixel (see Alpha Texture Blending). These adapters also generally do not support multiple texture blending. If your application is running on an adapter such as this, it can use multipass texture blending to perform monochrome light mapping.

To perform monochrome light mapping, an application stores the lighting information in the alpha data of its light map textures. The program uses the texture filtering capabilities of Direct3D to perform a mapping from each pixel in the primitive's image to a corresponding texel in the light map. It sets the source blending factor to the alpha value of the corresponding texel.

The following code fragment illustrates how an application can use a texture as a monochrome light map:

// This example assumes that lpD3DDev is a valid pointer to an
// IDirect3DDevice3 interface and that lptexLightMap is a valid
// pointer to a texture that contains monochrome light map data.

// Set the light map texture as the current texture.
lpD3DDev->SetTexture(0,lptexLightMap);

// Set the color operation.
lpD3DDev->SetTextureStageState(0,D3DTSS_COLOROP,
                               D3DTOP_SELECTARG1);

// Set argument 1 to the color operation.
lpD3DDev->SetTextureStageState(0,D3DTSS_COLORARG1,
                               D3DTA_TEXTURE | D3DTA_ALPHAREPLICATE);

Since display adapters that do not support destination alpha blending usually do not support multiple texture blending, this example sets the light map as the first texture, which is available on all 3-D accelerator cards. The sample code sets the color operation for the texture's blending stage to blend the texture data with the primitive's existing color. It then selects the first texture and the primitive's existing color as the input data.


Color Light Maps

Your application will usually render 3-D scenes more realistically if it uses colored light maps. A colored light map uses the RGB data in the light map for its lighting information. The following code fragment demonstrates light mapping with RGB color data:

// This example assumes that lpD3DDev is a valid pointer to an
// IDirect3DDevice3 interface and that lptexLightMap is a valid
// pointer to a texture that contains RGB light map data.

// Set the light map texture as the 1st texture.
lpD3DDev->SetTexture(0, lptexLightMap);

lpD3DDev->SetTextureStageState(0,D3DTSS_COLOROP,
                               D3DTOP_MODULATE);

lpD3DDev->SetTextureStageState(0,D3DTSS_COLORARG1,
                               D3DTA_TEXTURE);

lpD3DDev->SetTextureStageState(0,D3DTSS_COLORARG2,
                               D3DTA_DIFFUSE);

This sample sets the light map as the first texture. It then sets state of the first blending stage to modulate the incoming texture data. It uses the first texture and the current color of the primitive as the arguments to the modulate operation.


Specular Light Maps

When illuminated by a point light source, shiny surfaces, such as metal or color light maps, your Direct3D applications can apply specular light maps to primitives.

To perform specular light mapping, first modulate the specular light map with the primitive's existing texture. Then add the monochrome or RGB light map. The following code fragment illustrates this process:

// This example assumes that lpD3DDev is a valid pointer to an
// IDirect3DDevice3 interface.
// lptexBaseTexture is a valid pointer to a texture.
// lptexSpecLightMap is a valid pointer to a texture that contains RGB
// specular light map data.
// lptexLightMap is a valid pointer to a texture that contains RGB
// light map data.

// Set the base texture.
lpD3DDev->SetTexture(0,lptexBaseTexture );

// Set the base texture operation and args
lpD3DDev->SetTextureStageState(0,D3DTSS_COLOROP,
                               D3DTOP_MODULATE );
lpD3DDev->SetTextureStageState(0,D3DTSS_COLORARG1, D3DTA_TEXTURE );
lpD3DDev->SetTextureStageState(0,D3DTSS_COLORARG2, D3DTA_DIFFUSE );

// Set the specular light map.
lpD3DDev->SetTexture(1,lptexSpecLightMap );

// Set the specular light map operation and args
lpD3DDev->SetTextureStageState(1,D3DTSS_COLOROP,
                               D3DTOP_MODULATE );
lpD3DDev->SetTextureStageState(1,D3DTSS_COLORARG1, D3DTA_TEXTURE );
lpD3DDev->SetTextureStageState(1,D3DTSS_COLORARG2, D3DTA_CURRENT );

// Set the RGB light map.
lpD3DDev->SetTexture(2,lptexLightMap);

// Set the RGB light map operation and args
lpD3DDev->SetTextureStageState(2,D3DTSS_COLOROP, D3DTOP_ADD);
lpD3DDev->SetTextureStageState(2,D3DTSS_COLORARG1, D3DTA_TEXTURE );
lpD3DDev->SetTextureStageState(2,D3DTSS_COLORARG2, D3DTA_CURRENT );


Diffuse Light Maps

When illuminated by a point light source, matte surfaces display diffuse light reflection. The brightness of diffuse light depends on the distance from the light source and the angle between the surface normal and the light source direction vector.

Your application can simulate diffuse lighting with texture light maps. Do this by adding the diffuse light map to the base texture, as shown in the following code fragment:

// This example assumes that lpD3DDev is a valid pointer to an
// IDirect3DDevice3 interface.
// lptexBaseTexture is a valid pointer to a texture.
// lptexDiffuseLightMap is a valid pointer to a texture that contains
// RGB diffuse light map data.

// Set the base texture.
lpD3DDev->SetTexture(0,lptexBaseTexture );

// Set the base texture operation and args
lpD3DDev->SetTextureStageState(0,D3DTSS_COLOROP,
                               D3DTOP_MODULATE );
lpD3DDev->SetTextureStageState(0,D3DTSS_COLORARG1, D3DTA_TEXTURE );
lpD3DDev->SetTextureStageState(0,D3DTSS_COLORARG2, D3DTA_DIFFUSE );

// Set the diffuse light map.
lpD3DDev->SetTexture(1,lptexDiffuseLightMap );

// Set the blend stage.
lpD3DDev->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_ADD );
lpD3DDev->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE );
lpD3DDev->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_CURRENT );


Texture Compression

DirectDraw provides services to compress surfaces that will be used for texturing 3-D models. For information on creating and manipulating the data in a compressed texture surface, see Compressed Texture Surfaces in the DirectDraw documentation.

Once your application creates a rendering device, it can determine if the device supports texturing from compressed texture surfaces by calling the IDirect3DDevice3::EnumTextureFormats method. The method calls the D3DEnumPixelFormatsCallback callback function that you provide for each pixel format that the device supports for texture maps. If any of the enumerated pixel formats use the DXT1, DXT2, DXT3, DXT4, or DXT5 four character codes (FOURCCs), the device can texture directly from a compressed texture surface that uses that format. If so, you can use compressed texture surfaces directly with Direct3D by calling the IDirect3DDevice3::SetTexture method. If the device doesn't support texturing from compressed texture surfaces, you can still store texture data in a compressed format surface, but you must convert any compressed textures to a supported format before they can be used for texturing. The DirectDraw blit methods, IDirectDrawSurface4::Blt and IDirectDrawSurface4::BltFast, automatically perform conversion of compressed formats to standard RGBA formats. To minimize loss of information, try to pick a destination pixel format that closely matches the compressed format. For instance, ARGB:1555 would be a good destination format for DXT1, but ARGB:4444 would be a better choice for DXT3 since DXT3 contains four bits of alpha information.


Automatic Texture Management

Texture management, in short, is the process of determining which textures are needed for rendering at a given time, and ensuring that those textures are loaded into video memory. Like any algorithm, texture management schemes vary in complexity, but any approach to texture management involves the following key tasks:

  • Tracking the amount of available texture memory.
  • Calculating which textures are currently needed for rendering, and which aren't.
  • Determining which of the existing texture surfaces can be reloaded with another texture image, and which surfaces should be destroyed and replaced with new texture surfaces.

Previously, Direct3D applications were responsible for managing textures on their own. Direct3D Immediate Mode for DirectX 6.0 introduces system supported texture management, where Direct3D efficiently and intelligently performs texture management, ensuring that textures are loaded for optimal performance. (Texture surfaces that Direct3D manages are casually referred to as "managed textures.")

You request automatic texture management for textures when you create them. To get a managed texture, simply create a texture surface that also includes the DDSCAPS2_TEXTUREMANAGE flag in the dwCaps2 member of the associated DDSCAPS2 structure. Note that you are not allowed to specify where you want the texture created–you can't use the DDSCAPS_SYSTEMMEMORY or DDSCAPS_VIDEOMEMORY flags when creating a managed texture. After creating the managed texture, you can call the IDirect3DDevice3::SetTexture method to set it to a stage in the rendering device's texture cascade.

Direct3D automatically downloads textures into video memory as needed. (The system might cache managed textures in local or non-local video memory, depending on the availability of non-local video memory or other factors. Where your managed textures are cached is not communicated to your application, nor is this knowledge required to take advantage of automatic texture management.) If your application uses more textures than can fit in video memory, Direct3D will evict older textures from video memory to make room for the new textures. If you use an evicted texture again, the system uses the original system memory texture surface to reload the texture in the video memory cache. Reloading the texture is a minor, but obviously necessary, performance hit to the application.

You can dynamically modify the original system memory copy of the texture by blitting or locking the texture surface. When the system detects a "dirty" surface–after a blit is completed, or when the surface is unlocked–the texture manager automatically updates the video memory copy of the texture. The performance hit incurred is similar to reloading an evicted texture.

When entering a new level in a game, your application may need to flush all managed textures from video memory. You can explicitly request that all managed textures be evicted by calling the IDirect3D3::EvictManagedTextures method. When you call this method, Direct3D destroys any cached local and non-local video memory textures, but leaves the original system memory copies untouched.

Note You cannot retrieve a texture handle for a managed texture by calling the IDirect3DTexture2::GetHandle method.


Hardware Considerations for Texturing

Current hardware does not necessarily implement all of the functionality that the Direct3D interface enables. Your program must test user's hardware and adjust its rendering strategies accordingly.

Many 3-D accelerator cards do not support diffuse iterated values as arguments to blending units. However, your program can introduce iterated color data when it performs texture blending.

Some 3-D hardware may not have a blending stage associated with the first texture. On these adapters, your application will need to perform blending in the second and third texture stages in the set of current textures.

Due to limitations in much of today's hardware, few display adapters can perform trilinear mipmap interpolation through the multiple texture blending interface offered by IDirect3DDevice3. Specifically, there is little support for setting the D3DTSS_MIPFILTER texture stage state to D3DTFP_LINEAR. Your application can use multipass texture blending to achieve the same effects, or degrade to the D3DTFP_POINT mipmap filter mode, which is widely supported.


Depth Buffers

This section presents information on using depth buffers for hidden line and hidden surface removal. It is organized into the following topics:

  • What Are Depth Buffers?
  • Using Depth Buffers

The Direct3D Immediate Mode tutorials provide additional information about using depth buffers. See Tutorial 2: Adding a Depth Buffer for details.


What Are Depth Buffers?

A depth buffer, often called a z-buffer or a w-buffer, is a DirectDraw surface that stores depth information to be used by Direct3D. When Direct3D renders a 3-D scene to a target surface, it can use the memory in an attached depth buffer surface as a workspace to determine how the pixels of rasterized polygons occlude one another. Direct3D uses an off-screen DirectDraw surface as the target to which final color values are written. The depth buffer surface that is attached to the render target surface is used to store depth information which tells Direct3D how "deep" each visible pixel is in the scene.

When a 3-D scene is rasterized with depth buffering enabled, each point on the rendering surface is tested. The values in the depth buffer can be a point's z coordinate or its homogeneous w coordinate–from the point's (x,y,z,w) location in projection space. A depth buffer that uses z values is often called a "z-buffer," and one that uses w values called a "w-buffer." Each type of depth buffer has its advantages and disadvantages, which are discussed later.

At the beginning of the test, the depth value in the depth buffer is set to the largest possible value for the scene. The color value on the rendering surface is set to either the background color value, or the color value of the background texture at that point. Each polygon in the scene is tested to see if it intersects with the current coordinate (x,y) on the rendering surface. If it does, the depth value (which will be the z coordinate in a z-buffer, and the w coordinate in a w-buffer) at the current point is tested to see if it is smaller than the depth value already stored in the depth buffer. If the depth of the polygon value is smaller, it is stored in the depth buffer and the color value from the polygon is written to the current point on the rendering surface. If the depth value of the polygon at that point is larger, the next polygon in the list is tested. This process is shown in the following illustration.

Note Although most applications don't use this feature, you can change the comparison Direct3D uses to determine which values will be placed in the depth buffer and subsequently the render target surface. To do so, change the value for the D3DRENDERSTATE_ZFUNC render state.

Nearly all 3-D accelerators on the market support z-buffering, making z-buffers the most common type of depth buffer today. However ubiquitous, z-buffers do have their drawbacks. Due to the mathematics involved, the generated z values in a z-buffer tend not to be distributed evenly across the z-buffer range (typically 0.0 to 1.0, inclusive). Specifically, the ratio between the far and near clipping planes strongly affects how unevenly z values are distributed. Using a far-plane distance to near-plane distance ratio of 100, 90% of the depth buffer range is spent on the first 10% of the scene depth range. Typical applications for entertainment or visual simulations with exterior scenes often require far plane/near plane ratios of anywhere between 1000 to 10000. At a ratio of 1000, 98% of the range is spent on the 1st 2% of the depth range, and the distribution gets worse with higher ratios. This can cause hidden surface artifacts in distant objects, especially when using 16-bit depth buffers (the most commonly supported bit-depth).

A w-based depth buffer, on the other hand, is often more evenly distributed between the near and far clip planes than z-buffer. The key benefit is that the ratio of distances for the far and near clipping planes is no longer an issue. This allows applications to support large maximum ranges, while still getting relatively accurate depth buffering close to the eye point. A w-based depth buffer isn't perfect, and can sometimes exhibit hidden surface artifacts for near objects. Another drawback to the w-buffered approach is related to hardware support: w-buffering isn't supported as widely in hardware as z-buffering.

The DirectDraw HEL can create depth buffers for use by Direct3D or other 3-D–rendering software. The HEL supports 16-bit depth buffers. The DirectDraw device driver for a 3-D accelerator can permit the creation of depth buffers in display memory by exposing the DDSCAPS_ZBUFFER flag. You can query for the supported depth buffer bit-depths by calling the IDirect3D3::EnumZBufferFormats method.

Whenever a z-buffer surface is created, your application should maintain a pointer to the z-buffer until it shuts the Direct3D system down. Your program should release the z-buffer surface just before it releases the rendering surface.

Z-buffering requires overhead during rendering. Various techniques can be used to optimized rendering when using z-buffers. For details, see Z-Buffer Performance.

Note The actual interpretation of a depth value is specific to the 3-D renderer.


Using Depth Buffers

The following topics discuss common usage scenarios for depth buffers:

  • Querying for Depth Buffer Support
  • Creating a Depth Buffer
  • Enabling Depth Buffering
  • Clearing Depth Buffers
  • Changing Depth Buffer Write Access
  • Changing Depth Buffer Comparison Functions
  • Using Z-Bias

For a conceptual overview and an introduction to depth buffering, see What Are Depth Buffers?. For more information about using depth-buffers in your applications, see Tutorial 2: Adding a Depth Buffer.


Querying for Depth Buffer Support

As with any feature, don't assume that the driver your application uses supports depth buffering; you should always check the driver's capabilities. Although most driver support z-based depth buffering, not all will be able to provide support to w-based depth buffering. (For general information about depth buffering, see What Are Depth Buffers?) Drivers do not fail if you attempt to enable an unsupported scheme, falling-back on another depth buffering method instead, or sometimes disabling depth buffering altogether, which can result in rendered scenes that show major depth sorting artifacts.

You can check for general support for depth buffers by querying the DirectDraw for the display device your application uses before you create a Direct3D device. If the DirectDraw object reports that it supports depth buffering, any hardware devices you create from this DirectDraw object will support z-buffering (but you don't yet know if the driver supports w-buffering).

To query for general depth buffering support

  1. Call the IDirectDraw4::GetCaps method of the DirectDraw object for the display device your application uses, passing initialized DDCAPS structures as parameters. After the call, the DDCAPS structures contain information about DirectDraw's hardware and emulation capabilities.
  2. Examine the ddsCaps member of the structure you passed as the first parameter. If this member–a DDSCAPS2 structure–includes the DDSCAPS_ZBUFFER flag, the driver supports depth buffering through z-buffers.

Once you know that the driver supports z-buffers, you can verify w-buffer support. Although z-buffers are supported for all software rasterizers, w-buffers are only supported by the reference rasterizer, which is hardly suited for use by real-world applications. No matter what type of device your application uses, you should verify support for w-buffers before you attempt to enable w-based depth buffering.

To determine support for w-buffers

  1. After creating your device (HAL or emulated), call the IDirect3DDevice3::GetCaps method, passing initialized D3DDEVICEDESC structures in both parameters.
  2. After the call, the dpcTriCaps and dpcLineCaps members (D3DPRIMCAPS structures) contain information about the driver's support for rendering primitives.
  3. If the dwRasterCaps member of these structures contains the D3DPRASTERCAPS_WBUFFER flag, then the driver supports w-based depth buffering for that primitive type.


Creating a Depth Buffer

You usually create a depth buffer during your application's startup sequence, before creating a Direct3D device object for rendering. Use the following steps to create and attach a depth buffer surface to the render target surface:

To create a depth buffer

  1. Call the IDirect3D3::EnumZBufferFormats method to determine the depth-buffer pixel formats that the device supports.
  2. Prepare a DDSURFACEDESC2 structure that describes a DirectDraw surface that matches the render target surface's dimensions, includes the DDSCAPS_ZBUFFER capability flag, and uses a supported depth-buffer pixel format (retrieved in Step 1).
  3. Create the surface in video memory or system memory, depending on what type of rendering device your application will use. (See note.)
  4. Attach the depth buffer surface to the rendering surface using the IDirectDrawSurface4::AddAttachedSurface method.

After creating the depth buffer surface and attaching it to the render target surface, call the IDirect3D3::CreateDevice method to create a rendering device that uses the render target surface and its depth buffer.

Create the depth buffer in video memory–with the DDSCAPS_VIDEOMEMORY surface capability–when your application uses a hardware driver (HAL device), and in system memory–the DDSCAPS_SYSTEMMEMORY surface capability–when using software emulation drivers (the MMX or RGB devices). Failing to create a depth buffer in the appropriate type of memory will cause the CreateDevice method to fail.

Note Some popular hardware devices require that the render target and depth buffer surfaces use the same bit depth. On such hardware, if your application uses a 16-bit render target surface, the attached depth buffer must also be 16-bits. For a 32-bit render target surface, the depth buffer must be 32-bits, of which 8-bits can be used for stencil buffering (if needed).

If the hardware upon which your application is running has this requirement, and your application fails to meet it, any attempts to create a rendering device that uses the non-compliant surfaces will fail. You can use the DirectDraw method, IDirectDraw4::GetDeviceIdentifier to track hardware that imposes this limitation.


Enabling Depth Buffering

After you create a depth buffer (as described in Creating a Depth Buffer), enabling depth buffering is as simple as calling the IDirect3DDevice3::SetRenderState method. Set the D3DRENDERSTATE_ZENABLE render state to enable depth-buffering. Use the D3DZB_TRUE value (or TRUE) to enable z-buffering, D3DZB_USEW to enable w-buffering, or D3DZB_FALSE (or FALSE) to disable depth buffering.

Note To use w-buffering, your application must set a compliant projection matrix even if it doesn't use the Direct3D transformation pipeline, and perspective-correct texture mapping must be enabled. For information about providing an appropriate projection matrix, see A W-Friendly Projection Matrix. (The projection matrix discussed in What Is the Projection Transformation? is compliant.) To enable perspective-correct texture mapping, set the D3DRENDERSTATE_TEXTUREPERSPECTIVE render state to TRUE. For DirectX 6.0 and later, this is the default value.


Clearing Depth Buffers

You should clear the depth buffer each time you render a new frame. You can explicitly clear the depth buffer through Direct3D by using the IDirect3DViewport3::Clear and IDirect3DViewport3::Clear2 methods. The Clear method always uses the "deepest" value, but Clear2 allows you to specify an arbitrary depth value.

You can also use DirectDraw to clear a depth buffer. Call the depth buffer surface's IDirectDrawSurface4::Blt method to clear it. The DDBLT_DEPTHFILL flag indicates that the blit is being used to a clear depth buffer. When this flag is specified, the DDBLTFX structure passed to the IDirectDrawSurface4::Blt method should be initialized and have its dwFillDepth member set to the required depth.

If the DirectDraw device driver for a 3-D accelerator is designed to provide support for depth buffer clearing in hardware, it will report the DDCAPS_BLTDEPTHFILL flag and should handle DDBLT_DEPTHFILL blits. The destination surface of a depth-fill blit must be a depth buffer surface.


Changing Depth Buffer Write Access

By default, the Direct3D system is allowed to write to the depth buffer. Most applications will leave writing to the depth buffer enabled, but there are some special effects that can be achieved by not allowing the Direct3D system to write to the depth buffer.

You can disable depth buffer writes by calling the IDirect3DDevice3::SetRenderState method with the dwRenderStateType parameter set to D3DRENDERSTATE_ZWRITEENABLE and the dwRenderState parameter should be set to 0.


Changing Depth Buffer Comparison Functions

By default, when depth testing performed on a rendering surface, the Direct3D system updates the render target surface if the corresponding depth value (z or w) for each point is less than the value already in the depth buffer. You can change how the system performs comparisons on depth values by calling the IDirect3DDevice3::SetRenderState method with the dwRenderStateType parameter set to D3DRENDERSTATE_ZFUNC. The dwRenderState parameter should be set to one of the values in the D3DCMPFUNC enumeration.


Using Z-Bias

Polygons that are coplanar in your 3-D space can be made to appear as if they are not coplanar by adding a z-bias to each one. This is a technique commonly used to ensure that shadows in a scene are displayed properly. For instance, a shadow on a wall will likely have the same depth value as the wall does. If you render the wall first, then the shadow, the shadow might not be visible, or depth artifacts may be visible. You could reverse the order in which you render the coplanar objects in hopes of reversing the effect, but it depth artifacts are still likely.

You can help ensure that coplanar polygons are rendered properly by adding a bias to the z-values that the system uses when rendering the sets of coplanar polygons. To add a z-bias to a set of polygons, call the IDirect3DDevice3::SetRenderState method just before rendering them, setting the dwRenderStateType parameter to D3DRENDERSTATE_ZBIAS, and the dwRenderState parameter to a value between 0-16 inclusive. A higher z-bias value will increase the likelihood that the polygons you render will be visible when displayed with other, coplanar, polygons.


Stencil Buffers

This section presents a discussion of the purpose and use stencil buffers. It is divided into the following topics"

  • What is a Stencil Buffer?
  • How the Stencil Buffer Works
  • Customizing the Stencil Buffer


What is a Stencil Buffer?

The stencil buffer enables or disables drawing to the rendering target surface on a pixel-by-pixel basis. At its most fundamental level, it enables applications to mask off sections of the rendered image so that it is not displayed. Applications often use stencil buffers for special effects such as dissolves, decaling, and outlining. For details, see Stencil Buffer Techniques.

Stencil buffer information is embedded in the z-buffer data. Your application can test the user's hardware to see if it supports stencil buffers by invoking the IDirect3D3::EnumZBufferFormats method. To obtain information about the particular format of the z-buffer data, call the IDirectDrawSurface4::GetPixelFormat method, which passes a DDPIXELFORMAT structure to your application. The relevant information is in the dwZBufferBitDepth, dwStencilBitDepth, dwZBitMask, and dwStencilBitMask members.


How the Stencil Buffer Works

Direct3D performs a test on the contents of the stencil buffer on a pixel-by-pixel basis. For each pixel in the target surface, it performs a test using the corresponding value in the stencil buffer, a stencil reference value, and a stencil mask value. If the test passes, Direct3D performs an action. The test is performed using the following steps:

  1. Bitwise AND the stencil reference value with the stencil mask.
  2. Bitwise AND the stencil buffer value for the current pixel with the stencil mask.
  3. Compare the result of step 1 to the result of step 2 using the comparison function.

Written in pseudocode, these steps would look like this:

(StencilRef & StencilMask) CompFunc (StencilBufferValue & StencilMask)

Where StencilBufferValue is the contents of the stencil buffer for the current pixel. This pseudocode uses the & symbol to represent the bitwise AND operation. StencilMask represents the value of the stencil mask, and StencilRef represents the stencil reference value. CompFunc is the comparison function.

The current pixel is written to the target surface if the stencil test passes, and ignored otherwise. The default comparison behavior is to write the pixel no matter how each of the bitwise operations turn-out (D3DCMP_ALWAYS). You can change this behavior by changing the value of the D3DRENDERSTATE_STENCILFUNC render state, passing one of the members of the D3DCMPFUNC enumerated type to identify the desired comparison function.


Customizing the Stencil Buffer

Your application can customize the operation of the stencil buffer. It can set the comparison function, the stencil mask, and the stencil reference value. it can also control the action that Direct3D takes when the stencil test passes or fails. For more information, see Stencil Buffer State.


Vertex Buffers

This section introduces the concepts necessary to understand and use vertex buffers in a Direct3D application. Information is divided into the following sections:

  • What Are Vertex Buffers?
  • Vertex Buffer Descriptions
  • Vertex Buffers and Device Types
  • Using Vertex Buffers


What Are Vertex Buffers?

Vertex buffers, represented by the IDirect3DVertexBuffer interface, are simply memory buffers that contain vertex data. Vertex buffers can contain any vertex type—transformed or untransformed, lit or unlit—that can be rendered through the use of the vertex buffer rendering methods in the IDirect3DDevice3 interface. You can process the vertices in a vertex buffer to perform operations such as transformation, lighting, or generating clipping flags. (Transformation is always performed.)

The flexibility of vertex buffers make them ideal staging points for reusing transformed geometry. You could create a single vertex buffer, transform, light, and clip the vertices in it, and render the model in the scene as many times as you need without retransforming it, even with interleaved render state changes. This can be very useful when rendering models that use multiple textures: the geometry is only transformed once, and then portions of it can be rendered as needed, interleaved with the required texture changes. Render state changes made after vertices are processed take effect the next time the vertices are processed. For more information, see Processing Vertices.

You can optimize geometry in vertex buffers to get maximum performance for vertex operations and rendering. See Optimizing a Vertex Buffer for details.

Note Internally, vertex buffers use DirectDrawSurface objects for their memory management services. As a result, the semantics for accessing vertex buffer memory are similar to those of DirectDrawSurface objects. In fact, the IDirect3DVertexBuffer::Lock method accepts the same flags as the IDirectDrawSurface4::Lock method. For more information, see Accessing Vertex Buffer Memory.


Vertex Buffer Descriptions

A vertex buffer is described in terms of its capabilities: if it can only exist in system memory, if it is only to be used for write operations, the type and number of vertices it can contain, and whether or not it has been optimized since it was created. All these traits are held within a D3DVERTEXBUFFERDESC structure.

Vertex buffer descriptions tell the system how to create a vertex buffer or tell your application how an existing buffer was created (and if it has been optimized since being created). You must specify a complete description to create a new vertex buffer, and you provide an empty description structure for the system to fill with the capabilities of a previously created vertex buffer. For more information about these tasks, see Creating a Vertex Buffer and Retrieving Vertex Buffer Descriptions.

The dwSize member, common to most DirectX structures, is used for identify structure versions and must be set to the structure size before the structure can be used with any methods. The dwCaps structure member contains general capability flags. The D3DVBCAPS_SYSTEMMEMORY flag indicates that the system should create (or already has created) the vertex buffer in system memory. Create an explicit system memory vertex buffer if your application uses a software rendering device; otherwise, it is best to let the system determine the best location by omitting the flag. For more information about explicit system memory vertex buffers, see Vertex Buffers and Device Types.

The presence of the D3DVBCAPS_WRITEONLY flag in dwCaps hints to the system that the vertex buffer memory is used only for write operations. This frees the driver to place the vertex data in the best possible memory location it can to enable fast processing and rendering. Reading from a vertex buffer that uses this flag can result in very slow memory access times. If the D3DVBCAPS_WRITEONLY flag isn't used, the driver is less likely to put the data in a location inefficient for read operations, sacrificing some processing and rendering speed. If no flags are specified, it is assumed that applications will perform read and write operations on the data within the vertex buffer.

Note The D3DVBCAPS_OPTIMIZED flag is not used during vertex buffer creation. The system sets this capability when it optimizes a vertex buffer.

The final two D3DVERTEXBUFFERDESC structure members describe other capabilities. The dwFVF member contains a combination of flexible vertex format flags that identify the type of vertices that the buffer can contain. Vertex buffer capacity is measured by the total number of vertices it can contain, given in the dwNumVertices member.


Vertex Buffers and Device Types

A Direct3D software rendering device can only be used with explicit system-memory vertex buffers. To create a vertex buffer in system memory, include the D3DVBDESC_SYSTEMMEMORY flag in the description structure that you provide to the IDirect3D3::CreateVertexBuffer method.

If your application uses a hardware accelerated device, it's best to omit the D3DVBDESC_SYSTEMMEMORY flag. This allows the system to place the vertex buffer in memory for best performance, but hardware devices can work with vertex buffers regardless of their location.


Using Vertex Buffers

The following topics discuss common tasks that applications will perform when working with vertex buffers:

  • Creating a Vertex Buffer
  • Accessing Vertex Buffer Memory
  • Processing Vertices
  • Optimizing a Vertex Buffer
  • Rendering From a Vertex Buffer
  • Retrieving Vertex Buffer Descriptions


Creating a Vertex Buffer

The following figure illustrates the steps necessary to create a single vertex buffer.

You create a vertex buffer object by calling the IDirect3D3::CreateVertexBuffer method, which accepts four parameters. The first parameter is the address of a D3DVERTEXBUFFERDESC structure that describes the desired vertex format, buffer size, and general capabilities. These capabilities are detailed in Vertex Buffer Descriptions. Normally, the system automatically determines the best memory location (system or display memory) for the vertex buffer. However, software devices can only be used with explicit system-memory vertex buffers. For more information, see Vertex Buffers and Device Types.

The second parameter that CreateVertexBuffer accepts is the address of a variable that will be filled with a pointer to the new IDirect3DVertexBuffer interface of the vertex buffer object if the call succeeds. The third parameter determines if the vertex buffer will be capable of containing clipping information—in the form of clip flags—for vertices that exist outside the viewing area. Set this to 0 to create a "clipping-capable" vertex buffer, or include the D3DDP_DONOTCLIP flag to create a vertex buffer that cannot contain clip flags. The D3DDP_DONOTCLIP flag is only applied if you also indicate that the vertex buffer will contain transformed vertices (the D3DFVF_XYZRHW flag is included in the dwFVF member of the description structure). The CreateVertexBuffer method ignores the D3DDP_DONOTCLIP flag if you indicate that the buffer will contain untransformed vertices (the D3DFVF_XYZ flag). Clipping flags occupy additional memory, making a clipping-capable vertex buffer slightly larger than a vertex buffer incapable of containing clipping flags. Because these resources are allocated when the vertex buffer is created, you must request a clipping-capable vertex buffer ahead of time.

Note Creating a vertex buffer that can contain clip flags does not necessarily mean that you must request that clip flags be generated during vertex processing or applied during rendering. Each vertex buffer rendering method accepts the D3DDP_DONOTCLIP flag to bypass clipping during rendering, and the IDirect3DVertexBuffer::ProcessVertices method accepts the D3DVOP_CLIP flag, which can be omitted to prevent the system from generating clip flags while it processes vertices.

There is no way to produce clip flags for a vertex buffer that was created without support for them. Attempts to use the IDirect3DVertexBuffer::ProcessVertices method to do this will fail in debug builds, returning D3DERR_INVALIDVERTEXFORMAT. Rendering methods will ignore clipping requests when rendering from a transformed vertex buffer that does not contain clip flags.

The last parameter that CreateVertexBuffer accepts is provided for future compatibility with COM aggregation features. Currently, aggregation isn't supported, so this parameter must be set to NULL.

The following example shows what creating a vertex buffer might look like in code:

    /*
     * For the purposes of this example, the g_lpD3D variable is the
     * address of an IDirect3D3 interface exposed by a Direct3D
     * object, and the fIsAHardwareDevice variable is a BOOL variable
     * that is assumed to be set during application initialization.
     */

    D3DVERTEXBUFFERDESC vbdesc;
    ZeroMemory(&vbdesc, sizeof(D3DVERTEXBUFFERDESC));
    vbdesc.dwSize        = sizeof(D3DVERTEXBUFFERDESC);
    vbdesc.dwCaps        = 0L;
    vbdesc.dwFVF         = D3DFVF_VERTEX;
    vbdesc.dwNumVertices = NUM_FLAG_VERTICES;

    // If this isn't a hardware device, make sure the
    // vertex buffer uses system memory.
    if( !fIsAHardwareDevice )
        vbdesc.dwCaps |= D3DVBCAPS_SYSTEMMEMORY;

    // Create a clipping-capable vertex buffer.
    if(FAILED(g_lpD3D->CreateVertexBuffer(&vbdesc,
                                          &g_pvbVertexBuffer, 0L,
                                          NULL)))
        return E_FAIL;


Accessing Vertex Buffer Memory

Vertex buffer objects enable applications to directly access the memory allocated for vertex data. You can retrieve a pointer to vertex buffer memory by calling the IDirect3DVertexBuffer::Lock method, then access the memory as needed to fill the buffer with new vertex data, or to read any data it already contains.

The IDirect3DVertexBuffer::Lock method accepts three parameters. The first, dwFlags, tells the system how the memory should be locked, and can be used to hint how the application will be accessing the data within the buffer. (You can hint for read-only or write-only access, which allows the driver to lock the memory to provide the best performance given the requested access type. These hints are not required, but can improve performance for memory access in some situations.) Because vertex buffers use DirectDrawSurface objects to contain vertex data, the flags that IDirect3DVertexBuffer::Lock accepts are identical to those accepted by the IDirectDrawSurface4::Lock method, with identical results.

The second parameter accepted by the Lock method, lplpData, is the address of an LPVOID variable that will contain a valid pointer to the vertex buffer memory if the call succeeds. The last parameter, lpdwSize, is the address of a variable that will contain the size, measured in bytes, of the buffer at lplpData after the call returns. You can set lpdwSize to NULL if your application doesn't need information about the buffer size.

Performance Notes Use the DDLOCK_READONLY flag if your application will only be reading from the vertex buffer memory. Including this flag enables Direct3D to optimize its internal procedures to improve efficiency, given that access to the memory will be read-only. Although it is possible to write to memory locked with the DDLOCK_READONLY flag, doing so can produce unexpected results. In addition, attempting to read from a vertex buffer that was created with the D3DVBCAPS_WRITEONLY flag can be extremely slow, even if you lock the buffer for read-only access.

The vertex buffer memory itself is a simple array of vertices, specified in flexible vertex format. If your application is uses the legacy vertex structures, D3DVERTEX, D3DLVERTEX, and D3DTLVERTEX, the stride is simply the size of the structure, in bytes. If you are using a vertex format different from the legacy formats, use the stride of whatever vertex format structure you define. You can calculate the stride of each vertex at run time by examining the flexible vertex format flags contained within the vertex buffer description. The following table shows the size for each vertex component.

Vertex Format Flag | Size
D3DFVF_DIFFUSE | sizeof(DWORD)
D3DFVF_NORMAL | sizeof(float) × 3
D3DFVF_SPECULAR | sizeof(DWORD)
D3DFVF_TEXn | sizeof(float) × 2 × n
D3DFVF_XYZ | sizeof(float) × 3
D3DFVF_XYZRHW | sizeof(float) × 4

The number of texture coordinates present in the vertex format is described by the D3DFVF_TEXn flags (where n is a value from 0 to 8). Because each set of texture coordinates in the vertex format occupies the space of two float variables, multiply the number of texture coordinate sets by the size of one set of texture coordinates to calculate the memory required for that number of texture coordinates.

Use the total vertex stride to increment and decrement the memory pointer as needed to access particular vertices.


Processing Vertices

Processing the vertices in a vertex buffer applies the current transformation matrices for the device, and can optionally apply vertex operations such as lighting, generating clip flags, and updating extents. The IDirect3DVertexBuffer interface exposes the IDirect3DVertexBuffer::ProcessVertices method to process vertices.

You process vertices from a source vertex buffer into a destination vertex buffer by calling the ProcessVertices method of the destination vertex buffer, not the source buffer. The method accepts seven parameters that describe the operations to be performed, the location of the source vertex buffer's IDirect3DVertexBuffer interface, the rendering device that will perform the vertex operations, and the location and quantity of vertices that the method targets. After the call, the destination buffer contains the processed vertex data, and the source buffer is unchanged.

When preparing to process vertices, set the first parameter, dwVertexOp, to indicate the vertex operations you want to perform. You must include the D3DVOP_TRANSFORM flag, or the method will fail, but the remaining operations are optional. You can include any combination of optional flags to light the vertices, generate clip flags, and update extents during vertex processing.

The second and third parameters, dwDestIndex and dwCount, reflect the index within the destination buffer at which the vertices will be placed and the total number of vertices that should be processed and placed in the destination buffer. The fourth parameter, lpSrcBuffer, should be set to the address of the IDirect3DVertexBuffer of the vertex buffer object that contains the source vertices. The dwSrcIndex specifies the index at which the method should start processing vertices. (The total number of source vertices to be processed is implied from the dwCount parameter.) Set the lpD3DDevice parameter to the address of the IDirect3DDevice3 interface for the rendering device that process the vertices. The final parameter is reserved for future use, and must be set to 0.

Take care to create vertex buffers that use compatible vertex formats. At the least, the source buffer should contain untransformed vertices (using the D3DFVF_XYZ flag in the vertex format of the buffer description), and the destination buffer should contain transformed vertices (using the D3DFVF_XYZRHW flag). Any lighting or clipping services require that the source and destination vertex formats contain the appropriate fields. For instance, don't request lighting on vertices when the vertex format doesn't include a vertex normal. Likewise, you can't request that the system produce clip flags for a destination vertex buffer that was created without clipping capabilities. Attempts to perform operations on incompatible buffers will fail in debug builds.

You cannot process vertices when the source or destination vertex buffers are locked.


Optimizing a Vertex Buffer

Optimizing a vertex buffer causes the system to modify the contents of the buffer for better performance when processing or rendering vertices. Exactly how vertices are optimized is platform-specific and subject to change. Consequently, you cannot lock or otherwise access the contents of an optimized vertex buffer.

Call the IDirect3DVertexBuffer::Optimize method to optimize a vertex buffer. Optimizing a vertex buffer improves performance of vertex operations and rendering. The IDirect3DVertexBuffer::Optimize method accepts two parameters, only one of which is used. Set the lpD3DDevice parameter to the address of the device for which the vertices will be optimized, and set the last parameter to 0. Locked vertex buffers cannot be optimized until they are unlocked.

You can improve performance by keeping vertices in optimized format. However, optimized vertex buffers should be used only for static geometry, because once a vertex buffer is optimized, you can't lock it to change the optimized contents. After you optimize a vertex buffer, it can only be used with the IDirect3DVertexBuffer::ProcessVertices method and the vertex buffer rendering methods.


Rendering From a Vertex Buffer

As introduced in Rendering, the IDirect3DDevice3 interface includes methods to render primitives from a vertex buffer. These methods work very much like other rendering methods in IDirect3DDevice3, but employ slightly different parameters to accommodate vertex buffer objects.

The following topics introduce common rendering situations, and discuss specific issues related to calling the vertex buffer rendering methods:

  • About Vertex Buffer Rendering
  • Calling Vertex Buffer Rendering Methods


About Vertex Buffer Rendering

There are two common situations in which your application will render vertices from a vertex buffer. At the most basic level, the two situations break down according to the type of vertex that is in the vertex buffer at "render time," but indirectly, the procedure your application uses also determines when vertex and rendering operations occur. The following diagram illustrates the process of rendering from an untransformed vertex buffer.

As shown in the preceding illustration, the IDirect3DDevice3::DrawPrimitiveVB and IDirect3DDevice3::DrawIndexedPrimitiveVB methods are capable of rendering from a non-transformed vertex buffer. In this case, the system performs vertex and rendering operations each time you call a rendering method. For DirectX 6.0, using this approach isn't likely to provide improved performance over traditional DrawPrimitive rendering methods, but it might be more convenient in some situations. You can optimize performance by reusing transformed vertex data when you can, as shown in the following illustration.

In this case, your application creates two vertex buffers: one for untransformed geometry, and another for transformed geometry. The second buffer receives transformed vertex data when the IDirect3DVertexBuffer::ProcessVertices is called. The ProcessVertices method reads the vertices in the source buffer, performs the requested vertex operations on them, and places the results in the destination buffer. You can call the same rendering methods for transformed vertices that you would to render untransformed vertices. However, unlike untransformed vertices, Direct3D automatically detects that the data in the vertex buffer is transformed, sending it be rasterized right away. The performance overhead is kept to a minimum by eliminating unnecessary transformations.

You can optimize vertex buffer contents to increase performance even more. For more information, see Optimizing a Vertex Buffer.


Calling Vertex Buffer Rendering Methods

The IDirect3DDevice3::DrawPrimitiveVB method corresponds to the IDirect3DDevice3::DrawPrimitive method. Like its relative, the DrawPrimitiveVB method assumes that vertices appear in sequential order within the vertex buffer.

The DrawPrimitiveVB method accepts five parameters. Set the d3dptPrimitiveType parameter to indicate the type of primitive being rendered by using one the members of the D3DPRIMITIVETYPE enumerated type. Specify the address of the vertex buffer that contains the vertices in the second parameter, lpd3dVertexBuffer, then set values in the dwStartVertex and dwNumVertices parameters to reflect the first vertex and the total number of vertices that will be rendered. You don't need to render all the vertices that the vertex buffer contains, but you must use the appropriate number of vertices for that primitive type (as documented in the reference information for D3DPRIMITIVETYPE). The last parameter, dwFlags, determines the rendering behavior. These flags are identical to those used with other rendering methods. You can set flags to enable lighting and clipping, or to update the viewport extents during rendering.

The IDirect3DDevice3::DrawIndexedPrimitiveVB method renders primitives by indexing the vertices within a vertex buffer. The first two parameters are identical to those of the DrawPrimitiveVB method. The third parameter, lpwIndices, should be set to the address of an ordered array of WORD indices that the method will use to access the vertices to be rendered, and the fourth parameter, dwIndexCount, should be set to the number of index values that the array contains. The dwFlags parameter is identical to its counterpart in the DrawPrimitiveVB method.

You cannot request that vertex buffer rendering methods perform lighting if the format of the vertices within the buffer does not contain a vertex normal. Nor can you request that the rendering methods clip vertices when rendering from a transformed vertex buffer created with the D3DDP_DONOTCLIP flag. (This is allowed for untransformed vertex buffers, as the system will create a clipping-capable version at render time.) Attempts to request unavailable services will not cause the method to fail in debug builds, but the services will not be applied.

A software device, as opposed to a hardware-accelerated device, can only render from vertex buffers that were created with the D3DVBCAPS_SYSTEMMEMORY flag. For more information, see Vertex Buffers and Device Types.


Retrieving Vertex Buffer Descriptions

Applications often need to retrieve information about existing vertex buffers at run time. Direct3D makes this possible through the IDirect3DVertexBuffer::GetVertexBufferDesc method. Call this method using the IDirect3DVertexBuffer interface of any vertex buffer to retrieve its current description.

The GetVertexBufferDesc accepts only one parameter: the address of a properly initialized D3DVERTEXBUFFERDESC structure. To initialize the structure, set the dwSize member to the structure size, in bytes, and set the remaining members to 0. After the method returns, the structure will contain information about the vertex buffer capabilities, the vertex format in the buffer, and the total number of vertices that it can contain.

Note Optimizing a vertex buffer sets the D3DVBCAPS_OPTIMIZED capability flag in the dwFlags member of the D3DVERTEXBUFFERDESC structure. If this flag is set, the vertex buffer cannot be locked, and its contents are not made available to anything but rendering methods and the IDirect3DVertexBuffer::ProcessVertices method.

For general information, see Vertex Buffer Descriptions.


Common Techniques and Special Effects

Direct3D provides a powerful set of tools that can be used to increase the realistic appearance of a 3-D scene. This section presents information on some common special effects that can be produced with Direct3D. The range of possible effects is by no means limited to those presented here. The discussion in this section is organized into the following topics:

  • Fog
  • Billboarding
  • Clouds, Smoke, and Vapor Trails
  • Texture Blending Techniques
  • Fire, Flares, Explosions, and More
  • Motion Blur
  • Stencil Buffer Techniques
  • Colored Lights
  • Antialiasing


Fog

The following topics introduce fog and present information about using various fog features in Direct3D applications:

  • Introduction to Fog
  • Fog Formulas
  • Fog Blending
  • Fog Color
  • Range-Based Fog
  • Pixel Fog
  • Vertex Fog


Introduction to Fog

Adding fog to a 3-D scene can enhance realism, provide ambience or set a mood, and obscure artifacts sometimes caused when distant geometry comes into view. Direct3D Immediate Mode supports two fog models, pixel fog and vertex fog, each with its own features and programming interface.

Essentially, fog is implemented by blending the color of objects in a scene with a chosen fog color based on the depth of an object in a scene, or its distance from the viewpoint. As objects grow more distant, their original color blends more and more into the chosen fog color, creating the illusion that the object is being increasingly obscured by tiny particles floating in the scene—fog. The following screen capture shows a scene rendered without fog, and a similar scene rendered with fog enabled.

In the preceding figure, the scene on the left has a clear horizon, beyond which no scenery is visible, even though it would be visible in the real world. The scene on the right obscures the horizon by using a fog color identical to the background color, making polygons appear to fade into the distance. By combining discrete fog effects with creative scene design you can add mood and soften the color of objects in a scene.

Direct3D provides applications with two ways to add fog to a scene, pixel fog and vertex fog, named according to how the fog effects are applied. For details, see Pixel Fog and Vertex Fog.


Fog Formulas

Applications can control how fog affects the color objects in a scene by changing how Direct3D computes fog effects over distance. The D3DFOGMODE enumerated type contains members that identify the three fog formulas. All formulas calculate a fog factor as a function of distance, given parameters that your application sets. How distance itself is computed varies on the projection matrix or if range-based fog is enabled. For more information, see Eye-Relative vs. Z-Based Depth and Range-Based Fog.

D3DFOG_LINEAR

In the linear formula, start is the distance at which fog effects begin, end is the distance at which fog effects no longer increase, and d represents depth (or distance from the viewpoint) within a scene. Values for d increase as objects become more distant. The linear formula is supported for both pixel fog and vertex fog, but the exponential formulas are currently only supported when using pixel fog:

D3DFOG_EXP

D3DFOG_EXP2

In the preceding two exponential formulas, e is the base of natural logarithms (approximately 2.71828), density is an arbitrary fog density that can range from 0.0 to 1.0, and d is depth (or distance from the viewpoint) within a scene.

Note The system stores the fog factor in the alpha component of the specular color for a vertex. If your application performs its own transformation and lighting, you can insert fog factor values manually, to be applied by the system during rendering.

The following illustration graphs these formulas, by using common values as in the formula parameters.

When Direct3D calculates fog effects, it uses the fog factor from one of the preceding equations in a blending formula, shown here:

This formula effectively scales the color of the current polygon Ci by the fog factor f, and adds the product to the fog color Cf scaled by the bitwise inverse of the fog factor. The resulting color value is a blend of the fog color and the original color, as a factor of distance. The formula applies to all devices supported in DirectX 6.0. For the legacy ramp device, the fog factor scales the diffuse and specular color components, clamped to the range of 0.0 and 1.0, inclusive. The fog factor typically starts at 1.0 for the near plane and decreases to 0.0 at the far plane.


Fog Blending

Fog blending refers to the application of the fog factor to the fog and object colors to produce the final color that appears in a scene, as discussed in the Fog Formulas topic. The D3DRENDERSTATE_FOGENABLE render state controls fog blending. Set this render state to TRUE to enable fog blending (the default is FALSE), as in the following example code:

//
// For this example, g_lpDevice is a valid pointer
// to an IDirect3DDevice3 interface.
HRESULT hr;
hr = g_lpDevice->SetRenderState(
                     D3DRENDERSTATE_FOGENABLE,
                     TRUE);
if FAILED(hr)
    return hr;

You must enable fog blending for both pixel fog and vertex fog. For information about using these types of fog, see Pixel Fog and Vertex Fog.


Fog Color

Fog color for both pixel and vertex fog is set through the D3DRENDERSTATE_FOGCOLOR render state. The render state values can be any RGB color, specified as an RGBA color (the alpha component is ignored).

The following example sets the fog color to white:

/* For this example, the g_lpD3DDevice variable is
 * a valid pointer to an IDirect3DDevice3 interface.
 */
HRESULT hr;

hr = pd3dDevice->SetRenderState(
                    D3DRENDERSTATE_FOGCOLOR,
                    0x00FFFFFF); // Highest 8 bits aren't used.

if(FAILED(hr))
    return hr;


Range-Based Fog

Sometimes, using fog can introduce graphic artifacts that cause objects to be blended with the fog color in non-intuitive ways. For example, imagine a scene in which there are two visible objects, one distant enough to be affected by fog, and the other near enough to be unaffected. If the viewing area rotates in place, the apparent fog effects can change, even if the objects are stationary. The following illustration shows a top-down view of such a situation.

Range-based fog is another, more accurate, way to determine the fog effects. In range-based fog, Direct3D uses the actual distance from the viewpoint to a vertex for its fog calculations, increasing the effects of fog as the distance between the two points increases, rather than the depth of the vertex within in the scene, thereby avoiding rotational artifacts.

If the current device supports range-based fog, it will set the D3DPRASTERCAPS_FOGRANGE capability flag in the dwRasterCaps member of the D3DPRIMCAPS structure when you call the IDirect3DDevice3::GetCaps method. To enable range-based fog, set the D3DRENDERSTATE_RANGEFOGENABLE render state to TRUE.

Range-based fog is computed by Direct3D during transformation and lighting. As discussed in About Vertex Fog, applications that don't use the Direct3D transformation and lighting engine must also perform their own vertex fog calculations. In this case, provide the range-based fog factor in the alpha component of the specular component for each vertex.

Note No hardware currently exists that supports per-pixel range-based fog. As a result, Direct3D performs range-based fog only when using vertex fog with the Direct3D transformation and lighting engine. If your application performs its own transformation and lighting it must perform its own fog calculations, range-based or otherwise.


Pixel Fog

This section introduces the concept of pixel fog and provides information about using it in Direct3D applications. Information is divided into the following topics:

  • About Pixel Fog
  • Eye-Relative vs. Z-Based Depth
  • Pixel Fog Parameters
  • Using Pixel Fog


About Pixel Fog

Pixel fog gets its name from the fact that it is calculated on a per-pixel basis in the device driver. (This is unlike vertex fog, in which Direct3D computes fog effects when it performs transformation and lighting.) Pixel fog is sometimes called "table fog" because some drivers use a precalculated look-up table to determine the fog factor (using the depth of each pixel) to be applied in blending computations. Pixel fog can be applied using any of the fog formulas identified by members of the D3DFOGMODE enumerated type. Pixel-fog formula implementations are driver-specific, and if a driver doesn't support a complex fog formula, it should degrade to a less complex formula.

Note As discussed in Range-Based Fog, pixel fog does not support range-based fog calculations.


Eye-Relative vs. Z-based Depth

To alleviate fog-related graphic artifacts caused by uneven distribution of z-values within a depth buffer, most hardware devices use eye-relative depth instead of z-based depth values for pixel fog. Eye-relative depth is essentially the w element from a homogenous coordinate set. (Direct3D takes the reciprocal of the RHW element from a device space coordinate set to reproduce true w.) If a device supports eye-relative fog, it sets the D3DPRASTERCAPS_WFOG flag in the dwRasterCaps member of the D3DPRIMCAPS when you call IDirect3DDevice3::GetCaps method. (The D3DDEVICEDESC structure you pass to GetCaps contains multiple D3DPRIMCAPS structures that describe capabilities for various types of primitives.)

Note With the exception of the reference rasterizer, software devices always use z to calculate pixel fog effects.

When eye-relative fog is supported, the system will automatically use eye-relative depth in favor of z-based depth if the provided projection matrix produces z-values in world space that are equivalent to w-values in device space. (You set the projection matrix by calling the IDirect3DDevice3::SetTransform method, using the D3DTRANSFORMSTATE_PROJECTION value and passing a D3DMATRIX structure that represents the desired matrix.) If the projection matrix isn't compliant with this requirement, fog effects will not be applied properly. For details about producing a compliant matrix, see A W-Friendly Projection Matrix. (The perspective projection matrix provided in What Is the Projection Transformation? produces a compliant projection matrix.)

Usage Notes: To use eye-relative fog, perspective-correct texture mapping must be enabled. To enable perspective-correct texture mapping, set the D3DRENDERSTATE_TEXTUREPERSPECTIVE render state to TRUE. For DirectX 6.0 and later, this is the default value.

Direct3D uses the currently set projection matrix in its w-based depth calculations. As a result, applications must set a compliant projection matrix to receive the desired w-based features, even if they do not use the Direct3D transformation pipeline.

Direct3D checks the fourth column of the projection matrix, and if the coefficients are [0,0,0,1] (for an affine projection) the system will use z-based depth values for fog. In this case, you must also specify the start and end distances for linear fog effects in device space, which ranges from 0.0 at the nearest point to the user, and 1.0 at the farthest point.


Pixel Fog Parameters

All parameters for pixel fog are controlled through device render states. Pixel fog supports all of the formulas introduced in Fog Formulas. Choose the formula you want the system to use by setting the D3DRENDERSTATE_FOGTABLEMODE to the desired member from the D3DFOGMODE enumerated type.

When using the linear fog formula, you set the starting and ending distances through the D3DRENDERSTATE_FOGTABLESTART and D3DRENDERSTATE_FOGTABLEEND render states. These distances are in world-space units except when using a software device, in which case distances are in device space, which ranges from 0.0 at the nearest visible point to 1.0 at the farthest visible point.

The D3DRENDERSTATE_FOGTABLEDENSITY render state controls the fog density applied when an exponential fog formula is enabled. Fog density is a essentially weighting factor, ranging from 0.0 to 1.0 (inclusive), that scales the distance value in the exponent.

As discussed in Fog Color, the D3DRENDERSTATE_FOGCOLOR render state controls what color the system uses for fog blending.


Using Pixel Fog

Use the following steps to enable pixel fog in your application:

To enable pixel fog

  1. Enable fog blending by setting the D3DRENDERSTATE_FOGENABLE render state to TRUE.
  2. Set the desired fog color in the D3DRENDERSTATE_FOGCOLOR render state.
  3. Choose the fog formula you want to use by setting the D3DRENDERSTATE_FOGTABLEMODE render state to the corresponding member of the D3DFOGMODE enumerated type.
  4. Set the fog parameters as desired for the selected fog mode in the associated render states. This includes the start and end distances for linear fog, and fog density for exponential fog mode.

The following example shows what these steps might look like in code:

// For brevity, error values in this example are not checked
// after each call. A real-world application should check
// these values appropriately.
//
// For the purposes of this example, g_lpDevice is a valid
// pointer to an IDirect3DDevice3 interface.
void SetupPixelFog(DWORD dwColor, DWORD dwMode)
{
    float fStart = 0.5f,    // for linear mode
          fEnd   = 0.8f,
          fDensity = 0.66;  // for exponential modes

    // Enable fog blending.
    g_lpDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, TRUE);

    // Set the fog color.
    g_lpDevice->SetRenderState(D3DRENDERSTATE_FOGCOLOR, dwColor);

    // Set fog parameters.
    if(D3DFOG_LINEAR == dwMode)
    {
        g_lpDevice->SetRenderState(D3DRENDERSTATE_FOGTABLEMODE, dwMode);
        g_lpDevice->SetRenderState(D3DRENDERSTATE_FOGTABLESTART, *(DWORD *)(&fStart));
        g_lpDevice->SetRenderState(D3DRENDERSTATE_FOGTABLEEND,   *(DWORD *)(&fEnd));
    }
    else
    {
        g_lpDevice->SetRenderState(D3DRENDERSTATE_FOGTABLEMODE, dwMode);
        g_lpDevice->SetRenderState(D3DRENDERSTATE_FOGTABLEDENSITY, *(DWORD *)(&fDensity));
    }

}

Note Some fog parameters are required as floating-point values, even though the IDirect3DDevice3::SetRenderState method only accepts DWORD values in the second parameter. The preceding example provides the floating-point values to SetRenderState without data translation by casting the addresses of the floating-point variables as DWORD pointers, then dereferencing them.


Vertex Fog

This section introduces vertex fog and provides details about using it in Direct3D applications. Information is divided into the following topics:

  • About Vertex Fog
  • Vertex Fog Parameters
  • Using Vertex Fog


About Vertex Fog

When the system performs vertex fogging, it applies fog calculations at each vertex in a polygon, then interpolates the results across the face of the polygon during rasterization. Unlike pixel fog, vertex fog only supports the linear fog formula (D3DFOG_LINEAR). Because vertex fog effects are computed by the Direct3D lighting and transformation engine, most vertex fog parameters are exposed in the device lighting states set through the IDirect3DDevice3::SetLightState method. For more information, see Vertex Fog Parameters.

If your applications doesn't use Direct3D for transformation and lighting, it must perform fog calculations on its own. In this case, your application can place the fog factor it computes in the alpha component of the specular color for each vertex. You are free to use whatever formulas you desire—range-based or otherwise. Direct3D uses the supplied fog factor to interpolate across the face of each polygon. Applications that do not use Direct3D transformation and lighting need not set vertex fog parameters through light states, but must still enable fog and set the fog color through the associated render states. For more information, see Vertex Fog Parameters.


Vertex Fog Parameters

Vertex fog parameters related to the chosen fog formula are controlled by setting specific device lighting states (not render states) with the IDirect3DDevice3::SetLightState method. Currently, the only supported formula for vertex fog is the linear formula, which you can choose by setting the D3DLIGHTSTATE_FOGMODE lighting state to D3DFOG_LINEAR. Set the starting and ending distances for linear fog through the D3DLIGHTSTATE_FOGSTART and D3DLIGHTSTATE_FOGEND lighting states. All distances are in world space.

Note Although exponential fog formulas are not currently supported for vertex fog, the D3DLIGHTSTATETYPE enumerated type used with the SetLightState method contains a D3DLIGHTSTATE_FOGDENSITY member. This member is not currently used, and is included to allow for future expansion.

The color that the system uses for fog blending is controlled through the D3DRENDERSTATE_FOGCOLOR device render state. For more information, see Fog Color and Fog Blending.

Applications that perform their own transformation and lighting must also perform their own vertex fog calculations, and as such they probably wouldn't use light states at all. As a result, such an application need only enable fog blending and set the fog color through the associated render states, as described in Fog Blending and Fog Color.


Using Vertex Fog

Use the following steps to enable vertex fog in your application:

To enable vertex fog

  1. Enable fog blending by setting D3DRENDERSTATE_FOGENABLE to TRUE.
  2. Set the fog color in the D3DRENDERSTATE_FOGCOLOR render state.
  3. Choose the desired fog formula by setting the D3DLIGHTSTATE_FOGMODE lighting state to a member of the D3DFOGMODE enumerated type. (Currently, only D3DFOG_LINEAR is supported for vertex fog.)
  4. Set the fog parameters as desired for the selected fog formula in the associated lighting states. Do not use the fog parameter related render states—those are used only for pixel fog.

The following example shows what these steps might look like in code:

// For brevity, error values in this example are not checked
// after each call. A real-world application should check
// these values appropriately.
//
// For the purposes of this example, g_lpDevice is a valid
// pointer to an IDirect3DDevice3 interface.
void SetupVertexFog(DWORD dwColor, BOOL fUseRange)
{
    float fStart = 0.5f,    // linear fog distances
          fEnd   = 0.8f;

    // Enable fog blending.
    g_lpDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, TRUE);

    // Set the fog color.
    g_lpDevice->SetRenderState(D3DRENDERSTATE_FOGCOLOR, dwColor);

    // Set fog parameters.
    //
    // REMEMBER: Vertex fog formula parameters are connected
    // to the lighting states, not render states.
    g_lpDevice->SetLightState(D3DLIGHTSTATE_FOGMODE, D3DFOG_LINEAR);
    g_lpDevice->SetLightState(D3DLIGHTSTATE_FOGSTART, *(DWORD *)(&fStart));
    g_lpDevice->SetLightState(D3DLIGHTSTATE_FOGEND,   *(DWORD *)(&fEnd));

    // Enable range-based fog if desired (only supported for vertex fog).
    // For this example, it is assumed that fUseRange is set to non-zero
    // only if the driver exposes the D3DPRASTERCAPS_FOGRANGE capability.
    //
    // Note: this is slightly more performance intensive
    //       than non-range-based fog.
    if(fUseRange)
        g_lpDevice->SetRenderState(
                       D3DRENDERSTATE_RANGEFOGENABLE,
                       TRUE);
}

Note Some fog parameters are required as floating-point values, even though the IDirect3DDevice3::SetRenderState and IDirect3DDevice3::SetLightState methods only accept DWORD values in the second parameter. The preceding example successfully provides the floating-point values to these methods without data translation by casting the addresses of the floating-point variables as DWORD pointers, then dereferencing them.


Billboarding

When creating 3-D scenes, applications can sometimes gain performance advantages by rendering 2-D objects in a way that makes them appear to be 3-D objects. This is the basic idea behind the technique of billboarding.

A billboard in the normal sense of the word is a sign along a roadway. Direct3D applications can easily create and render this type of billboard by defining a rectangular solid and applying a texture to it. Billboarding in the more specialized sense of 3-D graphics is an extension of this. The goal is to make 2-D objects appear to be 3-D. The technique is to apply a texture containing the object's image to a rectangular primitive. The primitive is rotated so that it always faces the viewer. It doesn't matter if the object's image is not rectangular. Portions of the billboard can be made transparent, so the parts of the billboard image that you don't want seen are not visible.

Many games employ billboarding for their animated sprites. For instance, when the player is moving through a 3-D maze, he or she may see weapons or rewards that can be picked up. These are typically 2-D images textured onto a rectangular primitive. Billboarding is often used in games to render images of trees and bushes.

When an image is applied to a billboard, the rectangular primitive must first be rotated so that the resulting image faces the viewer. Your application must then translate it into position. The program can then apply a texture to the primitive.

Billboarding works best for symmetrical objects, especially objects that are symmetrical around the vertical axis. It also requires that the altitude of the viewpoint doesn't increase too much. If the user is allowed to view the billboarded from above, it will become readily apparent that the object is 2-D rather than 3-D.


Clouds, Smoke, and Vapor Trails

Clouds, smoke, and vapor trails can all be created by an extension of the billboarding technique (see Billboarding). By rotating the billboard around two axes instead of one, your application can enable the viewer to look at a billboard from any angle. Typically, your application will rotate the billboard around the horizontal and vertical axes.

To make a simple cloud, your application can rotate a rectangular primitive around one or two axes so that it faces the viewer. A cloud-like texture can then be applied to the primitive with transparency. For details on applying transparent textures to primitives, see Texture Blending. The cloud can be animated by applying a series of textures over time.

Applications can created more complex clouds by forming them from a group of primitives. The each part of the cloud is a rectangular primitive. The primitives can be moved independently over time to give the appearance of a dynamic mist. This concept is illustrated in the following figure.

The appearance of smoke is displayed in a manner similar to clouds. It typically requires multiple billboards, like complex clouds. Smoke usually billows and rises over time, so the billboards that make up the smoke plume need to be moved accordingly. More billboards may need to be added as the plume rises and disperses.

A vapor trail is just a smoke plume that doesn't rise. However, like a smoke plume, it does disperse over time. The figure below illustrates the technique of using billboards to simulate a vapor trail.


Texture Blending Techniques

The power of texture blending as tool for producing realism in a 3-D scene goes beyond adding finishes and light maps to primitives. In fact, it is fair to say that not even cutting-edge researchers have yet discovered all of the possibilities that the current texture blending features offer. There are, however, common special effects that are widely used in 3-D applications. Direct3D applications provides copious support these techniques.

This section provides an overview of common uses of texture blending to produce special effects in a 3-D scene or enhance its appearance of realism. The information is divided into the following topics:

  • Bump Mapping
  • Detail Texture Mapping


Bump Mapping

Texture blending enables applications to create the appearance of a complex texture on a primitive. This works well for smooth surfaces. For instance, your application can use the texture blending feature of Direct3D to apply a smooth wood grain finish onto a tabletop in a scene.

However, texture blending alone is insufficient to model rough surfaces such as the bark of a tree. Fortunately, the Direct3D enables applications to easily use a technique called bump mapping. A Bump map is a texture that stores depth information. That is, it stores the values indicating the high and low spots on a surface.

Your application applies the bump map to the texture using blending stages. Set the texture blending operation of the blending stage containing the bump map to D3DTOP_BUMPENVMAP or D3DTOP_BUMPENVMAPLUMINANCE. For more information, see D3DTEXTUREOP and Creating Blending Stages.


Detail Texture Mapping

Through multitexturing or multipass rendering, Direct3D enables your application to apply detail textures to primitives. Use detail textures to apply scuff marks, bumps, and other surface attributes that give the appearance of realism. You may want to use mipmaps for applying detail textures. See Texture Filtering With Mipmaps.

Detail textures can also be used as depth cues. For instance, suppose your application simulates landing a helicopter. As the helicopter approaches the ground, it is not unusual for the ground textures to be magnified so much that they begin to look fuzzy. In this situation, the user would have difficulty distinguishing the distance to the ground. Adding a detail texture that resembles gravel as the user approaches the ground helps the user derive sufficient depth cues to pilot the helicopter properly.

If the viewer is far from the primitive, you probably don't want the details shown. Be aware, that a primitive may appear brighter when your application does not apply the detail texture. One way to compensate is by applying a light map texture to darken the primitive.


Fire, Flares, Explosions, and More

Applications can use Direct3D to simulate natural phenomena involving energy releases. For instance, a program can generate the appearance of fire by applying flame-like textures to a set of billboards. This is especially effective if the program uses a sequence of fire textures to animate the flames on each billboard in the fire. Varying the speed of the animation playback from billboard to billboard increases the appearance of real flames. The semblance of intermingled 3-D flames can be achieved by layering the billboards, and the textures on the billboards.

Flares and flashes can be simulated by applying successively brighter light maps to all primitives in a scene. Although this is a computationally high-overhead technique, it allows your program to simulate a localized flare or flash. That is, the portion of the scene where the flare or flash originates can be brightened first.

Another technique is to position a billboard in front of the viewport so that the entire viewport is covered. The program applies successively whiter textures to the billboard and decreases the transparency over time. The entire scene will fade to white as time passes. This is a low overhead method of creating a flare. However, using this technique, it can be difficult to generate the appearance of a bright flash from a single point light source.

Explosions can be displayed in a 3-D scene procedures like those used for fire, flashes, and flares. For instance, your program might use a billboard to display a shock wave an rising plume of smoke when the explosion occurs. At the same time, your application can use a set of billboards to simulate flames. In addition, it can position a single billboard in front of the viewport to add a flare of light to the entire scene.

Energy beams can be simulated using billboards. Your application can also display them using primitives that are defined as line lists or line strips. For details, see Line Lists and Line Strips.

Your application can create force fields using billboards or primitives defined as triangle lists. To create a force field from triangle lists, define a set of disjoint triangles in a triangle list equally spaced over the region covered by the force field. The gaps between the triangles will allow the viewer to see the scene behind the triangles, as you might expect when looking at a force field. Apply a texture to the triangle list that gives the triangles the appearance of glowing with energy. For further information, see Triangle Lists and Current Texture.


Motion Blur

The perceived speed of an object in a 3-D scene can be enhanced by blurring the object, and by leaving a blurred trail of object images behind the object. Direct3D applications can accomplish this by rendering the object multiple times per frame.

Recall that Direct3D applications typically render scenes into an off-screen buffer. The contents of the buffer are displayed on the screen when the application calls the IDirectDrawSurface4::Flip method. Your Direct3D program can render the object multiple times into a scene before it displays the frame on the screen.

Programmatically, your application makes multiple calls to a DrawPrimitive method, repeatedly passing the same 3-D object. Before each call, the position of the object is updated slightly, producing a series of blurred object images on the target rendering surface. If the object has one or more textures, your application can enhance the motion blur effect by rendering the first image of the object with all of its textures nearly transparent. Each time the object is rendered, the transparency of the object's texture is decreased. When your program renders the object in its final position, it should render the object's textures without transparency. The exception is if you're adding motion blur to another effect that requires texture transparency. In any case, the initial image of the object in the frame should be the most transparent. The final image should be the least transparent.

After your application renders the series of object images onto the target rendering surface and renders the rest of the scene, it should call the IDirectDrawSurface4::Flip method to display the frame on the screen.

If your program is simulating the effect of the user moving through a scene at high speed, it can add motion blur to the entire scene. In this case, your application would render the entire scene multiple times per frame. Each time the scene is rendered, your program must move the viewpoint slightly. If your scene is highly complex, your user may see a visible performance degradation as acceleration is increased because of the increasing number of scene renderings per frame.


Stencil Buffer Techniques

Applications use the stencil buffer to mask pixels in an image. The mask controls whether or not the pixel is drawn. For more information on the stencil buffer, see Stencil Buffers.

Direct3D applications can achieve a wide range of special effects with the stencil buffer. Some of the more common effects are listed below. This list is by no means exhaustive.

  • Dissolves, Fades, and Swipes
  • Decaling
  • Compositing
  • Outlines and Silhouettes


Dissolves, Fades, and Swipes

Applications are increasingly employing special effects that are commonly used in movies and video, such as dissolves, swipes, and fades.

In a dissolve, one image is gradually replaced by another in a smooth sequence of frames. Although Direct3D provides methods of using multiple texture blending to achieve the same effect, applications that use the stencil buffer for dissolves can utilize the texture blending capabilities for other effects while they do a dissolve.

When your application performs a dissolve, it must render two different images. It uses the stencil buffer to control which pixels from each image are drawn to the rendering target surface. You can define a series of stencil masks and copy them into the stencil buffer on successive frames. Alternately, you can define a base stencil mask for the first frame and alter it incrementally.

At the beginning of the dissolve, your application sets the stencil function and stencil mask such that most of the pixels from the starting image pass the test. Most of the pixels of the ending image should fail the stencil test. On successive frames, the stencil mask is updated so that fewer and fewer of the pixels in the starting image pass the test. As the frames progress, fewer and fewer of the pixels in the ending image fail the test. In this manner, your application can perform a dissolve using any arbitrary dissolve pattern.

Fading in or fading out is just a special case of dissolving. When fading in, the stencil buffer is used to dissolve from a black (or white) image to a rendering of a 3-D scene. Fading out is the opposite, your application starts with a rendering of a 3-D scene and dissolves to black (or white). The fade can be done using any arbitrary pattern you want to employ.

Direct3D applications use a similar technique for swipes. When an application performs, for instance, a left-to-right swipe. The ending image appears to gradually slide on top of the starting image from left to right. just as in doing a dissolve, you must define a series of stencil masks that are loaded into the stencil buffer on successive frames, or successively modify the starting stencil mask. The stencil masks are used to disable the writing of pixels from the starting image and enable the writing of pixels from the ending image.

A swipe is somewhat more complex than a dissolve in that your application must read pixels from the ending image in the reverse order of the swipe. That is, if the swipe is moving left to right, your application must read pixels from the ending image from right to left.


Decaling

Direct3D applications use the technique of decaling to control which pixels from a particular primitive image are drawn to the rendering target surface. Programs apply decals to the images of primitives to enable co-planar polygons to be rendered correctly.

For instance, when applying tire marks and yellow lines to a roadway, the markings should appear directly on top of the road. However, the z values of the markings and the road are the same. Therefore, the depth buffer might not produce a clean separation between the two. Some pixels in the back primitive may be rendered on top of the front primitive and visa versa. The resulting image appears to shimmer from frame to frame. This effect is called "Z Fighting" or "flimmering".

To solve this problem, use a stencil to mask out the section of the back primitive where the decal will appear. Turn off z-buffering and render the image of the front primitive into the masked-off area of the render target surface.

Although multiple texture blending can be used to solve this problem, doing so limits the number of other special effects that your application can produce. Using the stencil buffer to apply decals frees up texture blending stages for other effects.


Compositing

Your application can use the stencil buffer to composite 2-D or 3-D images onto a 3-D scene. A mask in the stencil buffer is used to occlude an area of the rendering target surface. Stored 2-D information, such as text or bitmaps, can then be written to the occluded area. Alternately, your application can render additional 3-D primitives to the stencil-masked region of the rendering target surface. It can even render an entire scene.

Games often composite multiple 3-D scenes together. For instance, driving games typically display a rear-view mirror. The mirror contains the view of the 3-D scene behind the driver. It is essentially a second 3-D scene composited together with the driver's forward view.


Outlines and Silhouettes

The stencil buffer can be used for more abstract effects, such as outlining and silhouetting.

If your program applies a stencil mask to the image of a primitive that is the same shape, but slightly smaller than the primitive, the resulting image will only contain the primitive's outline. It can then fill the stencil-masked area of the image with a solid color, giving the primitive an embossed look.

If the stencil mask is the same size and shape as the primitive you are rendering, the resulting image will contain a "hole" where the primitive should be. Your program can then fill the "hole" with black to produce a silhouette of the primitive.


Colored Lights

The dcvColor member of the D3DLIGHT2 structure specifies a D3DCOLORVALUE structure. The colors defined by this structure are RGBA values that generally range from zero to one, with zero being black. Although you will usually want the light color to fall within this range, you can use values outside the range for special effects. For example, you could create a strong light that washes out a scene by setting the color to large values. You could also set the color to negative values to create a dark light, which actually removes light from a scene. Dark lights are useful for forcing dramatic shadows in scenes and other special effects.

When you use the ramp (monochromatic) lighting mode, the ambient light is built into the ramp, so you can't make your scene any darker than the current ambient light level. Also, remember that colored lights in RGB mode are converted into a gray-scale shade in ramp mode; a red light that looks good in RGB mode will be a dim white light in ramp mode.


Antialiasing

Antialiasing is a technique you can use to reduce the appearance of "jaggies"—the stair-step pixels used to draw any line that isn't exactly horizontal or vertical. In three-dimensional scenes, this artifact is most noticeable on the boundaries between polygons of different colors. Antialiasing effectively blends the pixels at these boundaries to produce a more natural look to the scene.

Direct3D supports two antialiasing techniques: edge antialiasing and full-surface antialiasing. Which technique is best for your application depends on your requirements for performance and visual fidelity.

  • Edge antialiasing
  • Full-scene antialiasing


Edge Antialiasing

In edge antialiasing, you render a scene, then re-render the convex silhouettes of the objects to be antialiased with lines. The system redraws those edges, blurring them to reduce artifacts.

If a device supports edge antialiasing, it exposes the D3DPRASTERCAPS_ANTIALIASEDGES capability flag in the D3DPRIMCAPS structure (filled by calling the IDirect3DDevice3::GetCaps method). If it does, set the D3DRENDERSTATE_EDGEANTIALIAS flag to TRUE, then redraw only the edges in the scene, using IDirect3DDevice3::DrawPrimitive and either the D3DPT_LINESTRIP or D3DPT_LINELIST primitive type. The behavior of edge antialiasing is undefined for primitives other than lines, so make sure to disable the feature by setting D3DRENDERSTATE_EDGEANTIALIAS to FALSE when antialiasing is complete.

Redrawing every edge in your scene can work without introducing major artifacts, but it can be computationally expensive. In addition, it can be difficult to determine which edges should be antialiased. The most important edges to redraw are those between areas of very different color (for example, silhouette edges) or boundaries between very different materials. Antialiasing the edge between two polygons of roughly the same color will have no effect, yet is still computationally expensive. For these reasons, full-scene antialiasing is often preferred, given that the current hardware supports it. For more information, see Full-scene Antialiasing.


Full-scene Antialiasing

Full-scene antialiasing refers to blurring the edges of each polygon in the scene as it is rasterized in a single pass—no second pass is required. Note that full-scene antialiasing, when supported, only affects triangles and groups of triangles; lines cannot be antialiased by using Direct3D services.

On some hardware, full-scene antialiasing can be applied only when the application renders the polygons sorted from back to front. To find out whether this is true for the current device, retrieve the device capabilities by calling IDirect3DDevice3::GetCaps method. After the call, check the dwRasterCaps member of the associated D3DPRIMCAPS structures. If the device requires back to front rendering for antialiasing, it exposes the D3DPRASTERCAPS_ANTIALIASSORTDEPENDENT capability flag in dwRasterCaps. If the device can perform antialiasing without regard to polygon order, it will expose the D3DPRASTERCAPS_ANTIALIASSORTINDEPENDENT flag. Of course, the absence of both flags indicates that the device cannot perform full-scene antialiasing at all.

After finding out whether or not you need to sort the polygons, set the D3DRENDERSTATE_ANTIALIAS render state to D3DANTIALIAS_SORTDEPENDENT or D3DANTIALIAS_SORTINDEPENDENT and draw the scene.

When you no longer need full-scene antialiasing, disable it by setting D3DRENDERSTATE_ANTIALIAS to D3DANTIALIAS_NONE.


GUIDs

Direct3D uses globally unique identifiers, or GUIDs, to identify parts of the interface. When you use the QueryInterface method to determine whether an object supports an interface, you identify the interface you're interested in by using its GUID.

To use GUIDs successfully in your application, you must either define INITGUID prior to all other include and define statements, or you must link to the Dxguid.lib library. You should define INITGUID in only one of your source modules.

Note that you use GUIDs differently depending on whether your application is written in C or C++. In C, you pass a pointer to the GUID (&IID_IDirect3D, for example), but in C++, you pass a reference to it (simply IID_IDirect3D).


Performance Optimization

Every developer who creates real-time applications that use 3-D graphics is concerned about performance optimization. This section provides you with guidelines about getting the best performance from your code.

You can use the guidelines in the following sections for any Direct3D application:

  • Databases and Culling
  • Batching Primitives
  • Lighting Tips
  • Texture Size
  • Triangle Flags
  • Clip Tests on Execution
  • General Performance Tips
  • Ramp Performance Notes
  • Z-buffer Performance


Databases and Culling

Building a reliable database of the objects in your world is the key to excellent performance in Direct3D — it is more important than improvements to rasterization or hardware.

You should maintain the lowest polygon count you can possibly manage. Design for a low polygon count, building low-poly models from the start, and add polygons if you feel that you can do so without sacrificing performance later in the development process. Try to keep the total number of polygons in the neighborhood of 2500. Remember, "the fastest polygons are the ones you don't draw."


Batching Primitives

To get the best rendering performance during execution, you should try to work with primitives in batches and keep the number of render-state changes as low as possible. For example, if you have an object with two textures, group the triangles that use the first texture and follow them with the necessary render state to change the texture, then group all the triangles that use the second texture. The simplest hardware support for Direct3D is called with batches of render states and batches of primitives through the hardware abstraction layer (HAL). The more effectively the instructions are batched, the fewer HAL calls are performed during execution.


Lighting Tips

Since lights add a per-vertex cost to each rendered frame, you can achieve significant performance improvements by being careful about how you use them in your application. Most of the following tips derive from the maxim, "the fastest code is code that is never called."

  • Use as few lights as possible. If you just need to bring up the overall level of lighting, use the ambient light instead of adding a new light. (It's much cheaper.)
  • Directional lights are cheaper than point lights or spotlights. For directional lights, the direction to the light is fixed and doesn't need to be calculated on a per-vertex basis.
  • Spotlights can be cheaper than point lights, because the area outside of the cone of light is calculated quickly. Whether or not they are cheaper depends on how much of your scene is lit by the spotlight.
  • Use the range parameter to limit your lights to only the parts of the scene you need to illuminate. All the light types exit fairly early when they are out of range.
  • Specular highlights almost double the cost of a light—use them only when you must. Use the D3DLIGHT_NO_SPECULAR flag in the D3DLIGHT2 structure as often as reasonable. When defining materials you must set the specular power value to zero to turn off specular highlights for that material—simply setting the specular color to 0,0,0 is not enough.


Texture Size

Texture-mapping performance is heavily dependent on the speed of memory. There are a number of ways to maximize the cache performance of your application's textures.

  • Keep the textures small; the smaller the textures are, the better chance they have of being maintained in the main CPU's secondary cache.
  • Do not change the textures on a per-primitive basis. Try to keep polygons grouped in order of the textures they use.
  • Use square textures whenever possible. Textures whose dimensions are 256×256 are the fastest. If your application uses four 128×128 textures, for example, try to ensure that they use the same palette and place them all into one 256×256 texture. This technique also reduces the amount of texture swapping. Of course, you should not use 256×256 textures unless your application requires that much texturing because, as already mentioned, textures should be kept as small as possible.


Triangle Flags

The wFlags member of the D3DTRIANGLE structure includes flags that allow the system to reuse vertices when building triangle strips and fans. Effective use of these flags allows some hardware to run much faster than it would otherwise.

Applications can use these flags in two ways as acceleration hints to the driver.

D3DTRIFLAG_STARTFLAT(len)
If the current triangle is culled, the driver can also cull the number of subsequent triangles given by len in the strip or fan.
D3DTRIFLAG_ODD and D3DTRIFLAG_EVEN
The driver needs to reload only one new vertex from the triangle and it can reuse the other two vertices from the last triangle that was rendered.

The best possible performance occurs when an application uses both the D3DTRIFLAG_STARTFLAT flag and the D3DTRIFLAG_ODD and D3DTRIFLAG_EVEN flags.

Because some drivers might not check the D3DTRIFLAG_STARTFLAT flag, applications must be careful when using it. An application using a driver that doesn't check this flag might not render polygons that should have been rendered.

Applications must use the D3DTRIFLAG_START flag before using the D3DTRIFLAG_ODD and D3DTRIFLAG_EVEN flags. D3DTRIFLAG_START causes the driver to reload all three vertices. All triangles following the D3DTRIFLAG_START flag can use the D3DTRIFLAG_ODD and D3DTRIFLAG_EVEN flags indefinitely, providing the triangles share edges.

The debugging version of this SDK validates the D3DTRIFLAG_ODD and D3DTRIFLAG_EVEN flags.


Clip Tests on Execution

Applications that use execute buffers can use the IDirect3DDevice::Execute method to render primitives with or without automatic clipping. Using this method without clipping is always faster than setting the clipping flags because clipping tests during either the transformation or rasterization stages slow the process. If your application does not use automatic clipping, however, it must ensure that all of the rendering data is wholly within the viewing frustum. The best way to ensure this is to use simple bounding volumes for the models and transform these first. You can use the results of this first transformation to decide whether to wholly reject the data because all the data is outside the frustum, whether to use the no-clipping version of the IDirect3DDevice::Execute method because all the data is within the frustum, or whether to use the clipping flags because the data is partially within the frustum. In Immediate Mode it is possible to set up this sort of functionality within one execute buffer by using the flags in the D3DSTATUS structure and the D3DOP_BRANCHFORWARD member of the D3DOPCODE enumerated type to skip geometry when a bounding volume is outside the frustum. Direct3D Retained Mode automatically uses these features to speed up its use of execute buffers.


General Performance Tips

You can follow a few general guidelines to increase the performance of your application.

  • Only clear when you must.
  • Minimize state changes.
  • Use perspective correction only if you must.
  • If you can use smaller textures, do so.
  • Gracefully degrade special effects that require a disproportionate share of system resources.
  • Constantly test your application's performance.
  • Ensure that your application runs well both with hardware acceleration and software emulation.


Ramp Performance Notes

Direct3D applications can use either the ramp software emulation driver (for the monochromatic color model) or the RGB software emulation driver. The performance notes in the following sections apply to the ramp driver:

  • Ramp Textures
  • Copy Texture-blending Mode
  • Ramp Performance Tips

Note The ramp software emulation driver is obsolete, and not supported in DirectX 6.0 and later. You cannot create a Direct3D ramp device by using the IDirect3D3 interface, nor can you query an existing ramp device for the IDirect3DDevice3 interface. In short, ramp devices do not support any multiple texture blending options. The notes in this section apply only to using the ramp device with the IDirect3D2, IDirect3DDevice2 or earlier interfaces.


Ramp Textures

Applications that use the ramp driver should be conservative with the number of texture colors they require. Each color used in a monochromatic texture requires its own lookup table during rendering. If your application uses hundreds of colors in a scene during rendering, the system must use hundreds of lookup tables, which do not cache well. Also, try to share palettes between textures whenever possible. Ideally, all of your application's textures will fit into one palette, even when you are using a ramp driver with depths greater than 8-bit color.


Copy Texture-blending Mode

Applications that use the ramp driver can sometimes improve performance by using the D3DTBLEND_COPY texture-blending mode from the D3DTEXTUREBLEND enumerated type. This mode is an optimization for software rasterization; for applications using a HAL, it is equivalent to the D3DTBLEND_DECAL texture-blending mode.

Copy mode is the simplest form of rasterization and hence the fastest. When copy mode rasterization is used, no lighting or shading is performed on the texture. The bytes from the texture are copied directly to the screen and mapped onto polygons using the texture coordinates in each vertex. Hence, when using copy mode, your application's textures must use the same pixel format as the primary surface. They must also use the same palette as the primary surface.

If your application uses the monochromatic model with 8-bit color and no lighting, performance can improve if you use copy mode. If your application uses 16-bit color, however, copy mode is not quite as fast as using modulated textures; for 16-bit color, textures are twice the size as in the 8-bit case, and the extra burden on the cache makes performance slightly worse than using an 8-bit lit texture.

Copy mode implements only two rasterization options, z-buffering and chromakey transparency. The fastest mode is to simply map the texels to the polygons, with no transparency and no z-buffering. Enabling chromakey transparency accelerates the rasterization of invisible pixels because only the texture read is performed, but visible pixels will incur a slight performance degradation because of the chromakey test.

Enabling z-buffering incurs the largest performance degradation for 8 bit copy mode. When z-buffering is enabled, a 16 bit value has to be read and conditionally written per pixel. Even so, enabling z-buffering for copy mode can be faster than disabling it if the average overdraw goes over two and the scene is rendered in front-to-back polygon order.

If your scene has overdraw of less than 2 (which is very likely) you should not use z-buffering in copy mode. The only exception to this rule is if the scene complexity is very high. For example, if you have more than about 1500 rendered polygons in the scene, the sort overhead begins to get high. In that case, it may be worth considering a z-buffer again.

Direct3D is fastest when all it needs to draw is one long triangle instruction. Render state changes just get in the way of this; the longer the average triangle instruction, the better the triangle throughput. Therefore, peak sorting performance can be achieved when all the textures for a given scene are contained in only one texture map or texture page. Although this adds the restriction that no texture coordinate can be larger than 1.0, it has the performance benefit of completely avoiding texture state changes.

For normal simple scenes use one texture, one material, and sort the triangles. Use z-buffering only when the scene becomes complex.


Ramp Performance Tips

Applications should use the following techniques to achieve the best possible performance when using the monochromatic (ramp) driver:

  • Share the same palette among all textures.
  • Keep the number of colors in the palette as low as possible—64 or fewer is best.
  • Keep the ramp size in materials at 16 or less.
  • Make all materials the same (except the texture handle)—allow the textures to specify the coloring. For example, make all the materials white and keep their specular power the same. Many applications do not need more than two materials in a scene: one with a specular power for shiny objects, and one without for matte objects.
  • Keep textures as small as possible.
  • Fit multiple small textures into a single texture that is 256×256 pixels.
  • Render small triangles by using the Gouraud shade mode, and render large triangles by using the flat shade mode.

Developers who must use more than one palette can optimize their code by using one palette as a master palette and ensuring that the other palettes contain a subset of the colors in the master palette.


Z-Buffer Performance

Applications can increase performance when using z-buffering and texturing by ensuring that scenes are rendered from front to back. Textured z-buffered primitives are pretested against the z-buffer on a scan line basis. If a scan line is hidden by a previously rendered polygon, the system rejects it quickly and efficiently. Z-buffering can improve performance, but the technique is most useful when a scene includes a great deal of overdraw. Overdraw is the average number of times a screen pixel is written to. Overdraw is difficult to calculate exactly, but you can often make a close approximation. If the overdraw averages less than 2, you can achieve the best performance by turning z-buffering off, and rendering the scene from back-to-front.

You can also improve the performance of your application by z-testing primitives; that is, by testing a given list of primitives against the z-buffer. If you render the bounding box of a complex object using z-visibility testing, you can easily discover whether the object is completely hidden. If it is hidden, you can avoid even starting to render the object. For example, imagine that the camera is in a room full of 3-D objects. Adjoining this room is a second room full of 3-D objects. The rooms are connected by an open door. If you render the first room and then draw the doorway to the second room using a z-test polygon, you may discover that the doorway is hidden by one of the objects in the first room and that you don't need to render anything at all in the second room.

On faster personal computers, software rendering to system memory is often faster than rendering to video memory, although it has the disadvantage of not being able to use double buffering or hardware-accelerated clear operations. If your application can render to either system or video memory, and if you include a routine that tests which is faster, you can take advantage of the best approach on the current system. The Direct3D sample code in this SDK demonstrates this strategy. It is necessary to implement both methods because there is no other way to test the speed. Speeds can vary enormously from computer to computer, depending on the main-memory architecture and the type of graphics adapter being used.


Troubleshooting

This section lists common categories of problems that you may encounter when writing Direct3D programs, and what you should do to prevent them.

  • Device Creation
  • Nothing Visible
  • Debugging
  • Borland Floating-Point Initialization
  • Parameter Validation
  • Miscellaneous


Device Creation

If your application fails during device creation, check for the following common errors:

  • You must specify DDSCAPS_3DDEVICE when you create the DirectDraw surface.
  • If you're using a palettized device, you must attach the palette.
  • If you're using a z-buffer, you must attach it to the rendering target.
  • Make sure you check the device capabilities, particularly the render depths.
  • Check whether you are using system or video memory.
  • Ensure that the registry has not been corrupted.


Nothing Visible

If your application runs but nothing is visible, check for the following common errors:

  • Ensure that your triangles are not degenerate.
  • Make sure that your index lists are internally consistent—that you don't have entries like 1, 2, 2 (which are silently dropped).
  • Ensure that your triangles are not being culled.
  • Make sure that your transformations are internally consistent.
  • Check the viewport to be sure it will allow your triangles to be seen.
  • Check the description of the execute buffer.


Debugging

Debugging a Direct3D application can be challenging. In addition to checking all the return values (a particularly important piece of advice in Direct3D programming, which is so dependent on very different hardware implementations), try the following techniques:

  • Switch to debug DLLs.
  • Force a software-only device, turning off hardware acceleration even when it is available.
  • Force surfaces into system memory.
  • Create an option to run in a window, so that you can use an integrated debugger.

The second and third options in the preceding list can help you avoid the Win16 lock which can otherwise cause your debugger to hang.

Also, try adding the following entries to WIN.INI:

[Direct3D]
debug=3
[DirectDraw]
debug=3


Borland Floating-Point Initialization

Compilers from the Borland company report floating-point exceptions in a manner that is incompatible with Direct3D. To solve this problem, you should include a _matherr() exception handler like the following:

// Borland floating point initialization
#include <math.h>
#include <float.h>

void initfp(void)
{
    // disable floating point exceptions
    _control87(MCW_EM,MCW_EM);
}

int _matherr(struct _exception  *e)
{
    e;               // dummy reference to catch the warning
    return 1;    // error has been handled
}


Parameter Validation

For performance reasons, the debug version of the Direct3D Immediate Mode runtime performs more parameter validation than the retail version, which sometimes performs no validation at all. This allows applications to perform robust debugging with the slower debug runtime component before using the faster retail version for performance tuning and final release.

Although several Direct3D Immediate Mode methods impose limits on the values that they can accept, these limits are often only checked and enforced by the debug version of the Direct3D Immediate Mode runtime. Applications must conform to these limits, or unpredictable (and highly undesirable) results can occur when running on the retail version of Direct3D. For example, the IDirect3DDevice3::DrawPrimitive method accepts a parameter (dwVertexCount) that indicates the number of vertices that the method will render. The method can only accept values between 0 and 65,535 (0x0000 and 0xFFFF). In the debug version of Direct3D, if you pass 65,536 (one more than the limit), the method will fail gracefully, printing an error message to the error log, and returning an error value to your application. Conversely, if your application makes the same error when it is running with the retail version of the runtime, behavior is undefined. For performance reasons, the method does not validate the parameters, resulting in unpredictable and completely situational behavior when they are not valid. In some cases the call might work, and in other cases it might cause a memory fault in Direct3D. If an invalid call consistently works with a particular hardware configuration and DirectX version, there is no guarantee that it will continue to function on other hardware or with future releases of DirectX.

If your application encounters unexplained failures when running with the retail Direct3D Immediate Mode runtime, test against the debug version and look closely for cases where your application passes invalid parameters.


Miscellaneous

The following tips can help you uncover common miscellaneous errors:

  • Check the memory type (system or video) for your textures.
  • Verify that the current hardware can do texturing.
  • Make sure that you can restore any lost surfaces.
  • Always specify D3DLIGHTSTATE_MATERIAL, even in RGB mode, because it is always necessary in monochromatic mode.


Direct3D Immediate Mode Tutorials

This section contains a series of tutorials, each providing step-by-step instructions for implementing the basics of Direct3D® Immediate Mode in an application. The tutorials are written parallel to a set of sample files that are provided with this SDK in the \Samples\Multimedia\D3DIM\Tutorials directory, following their code path and providing explanations along the way. Readers are encouraged to follow along in the sample code as they move through these tutorials.

The tutorials in this section show how to use Direct3D for common tasks by dividing those tasks into required steps. In some cases, steps are organized into substeps for clarity. The following tutorials are presented here:

  • Tutorial 1: Rendering a Single Triangle
  • Tutorial 2: Adding a Depth Buffer

Note The sample files in these tutorials are written in C++. If you are using a C compiler, you must make the appropriate changes to the files for them to successfully compile. At the very least, you need to add the vtable and this pointers to the interface methods.

Some comments in the included sample code might differ from the source files in the SDK. Changes are made for brevity only, and are limited to comments to avoid changing the behavior of the code.


Tutorial 1: Rendering a Single Triangle

To use Direct3D, you first create an application window, then create and initialize DirectDraw® and Direct3D-related objects. You use the COM interfaces that these objects implement to manipulate them and to create the subordinate objects required to render a scene. The Triangle sample project upon which this tutorial is based illustrates these tasks by rendering the simplest possible scene: a single triangle. The Triangle sample uses the following steps to set up Direct3D, render a scene, and eventually shut down:

  • Step 1: Create a Window
  • Step 2: Initialize System Objects
  • Step 3: Initialize the Scene
  • Step 4: Monitor System Messages
  • Step 5: Render and Display the Scene
  • Step 6: Shut Down

In addition to these steps, Triangle performs some standard tasks common to windowed applications. Although these tasks aren't difficult, the Triangle sample (and all other windowed samples) performs the following tasks as the needed:

  • Handle Window Movement
  • Handle Window Resizing


Step 1: Create a Window

The first thing any Windows application must do when it is executed is create an application window to display a user interface. Keeping with this, when Triangle begins execution at its WinMain function, it uses the following code to perform window initialization:

INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT )
{
    // Register the window class
    WNDCLASS wndClass = { CS_HREDRAW | CS_VREDRAW, WndProc, 0, 0, hInst,
                          LoadIcon( hInst, MAKEINTRESOURCE(IDI_MAIN_ICON)),
                          LoadCursor(NULL, IDC_ARROW),
                          (HBRUSH)GetStockObject(WHITE_BRUSH), NULL,
                          TEXT("Render Window") };
    RegisterClass( &wndClass );

    // Create our main window
    HWND hWnd = CreateWindow( TEXT("Render Window"),
                              TEXT("D3D Tutorial: Drawing One Triangle"),
                              WS_OVERLAPPEDWINDOW, CW_USEDEFAULT,
                              CW_USEDEFAULT, 300, 300, 0L, 0L, hInst, 0L );
    ShowWindow( hWnd, SW_SHOWNORMAL );
    UpdateWindow( hWnd );

The preceding code is standard Windows programming, covered here mostly for thoroughness. The sample starts by defining and registering a window class called "Render Window." The window class is defined to redraw on size events, to use an application-provided icon as a resource, and to have a white background. After the class is registered, the code creates a basic top-level window that uses the registered class, with a client area of 300 pixels wide by 300 pixels tall, and has no menu or child windows. The sample uses the WS_OVERLAPPEDWINDOW window style to create a window that includes minimize, maximize, and close boxes common to windowed applications. (If the sample were to run in full-screen mode, the preferred window style is WS_EX_TOPMOST.) Once the window is created, the code calls standard Win32® functions to show and update the window.

With the application window ready, you can begin setting up the essential DirectX® objects, which is the topic of Step 2: Initialize System Objects.


Step 2: Initialize System Objects

After you create an application window, you can begin initializing the primary DirectX objects whose services you will draw on to render the scene. For a Direct3D application, this means creating and configuring DirectDraw, rendering surfaces, a rendering device, and a viewport. For clarity, the Triangle sample separates system object initialization code from the code for initializing the scene. As a result, geometry, application-specific data structures, and lesser Direct3D objects like materials are initialized with the scene. This isn't a requirement, but it makes for simpler code.

The Triangle sample performs system initialization in the Initialize3DEnvironment application-defined function, called from WinMain after the window is created. Although preparing these objects isn't complex, the code is a little too lengthy to discuss in one place. As a result, the steps taken by the Initialize3DEnvironment function are presented in the following substeps:

  • Step 2.1: Initialize DirectDraw
  • Step 2.2: Set Up DirectDraw Surfaces
  • Step 2.3: Initialize Direct3D
  • Step 2.4: Prepare the Viewport

Note The Triangle sample code performs initialization by calling methods from within the WinMain function, immediately after the application window is created, rather than in response to system creation messages such as WM_CREATE. It does this to avoid relying on system message ordering, which can differ across platforms.


Step 2.1: Initialize DirectDraw

After creating the application window, the first object you will create is the DirectDraw object, which is required to set your application's cooperative level, and to create the surfaces for display and for use as the render target of a rendering device.

The Triangle sample starts performing initialization by creating a DirectDraw object and setting the application's cooperative level, as shown in the following code:

HRESULT Initialize3DEnvironment( HWND hWnd )
{
    HRESULT hr;

    // Create a DirectDraw object.
    hr = DirectDrawCreate( NULL, &g_pDD1, NULL );
    if( FAILED( hr ) )
        return hr;

    // Get a ptr to an IDirectDraw4 interface. This interface to DirectDraw
    // represents the DX6 version of the API.
    hr = g_pDD1->QueryInterface( IID_IDirectDraw4, (VOID**)&g_pDD4 );
    if( FAILED( hr ) )
        return hr;

The preceding code creates a DirectDraw object by calling the DirectDrawCreate DirectDraw global function. It passes NULL in the first parameter to request that the function create a DirectDraw object for the active display driver. For hardware that doesn't support GDI, such as 3-D only hardware, you should explicitly specify the globally unique identifier (GUID) of the desired driver in the first parameter. These GUIDs are normally obtained through enumeration. The second parameter is the address of a global variable that DirectDrawCreate fills with the address of the IDirectDraw interface for the DirectDraw object, and the last parameter is set to NULL to indicate that the new object will not be used with COM aggregation features. If the DirectDraw object is created successfully, the code queries for the latest iteration of the DirectDraw interface, IDirectDraw4.

The sample continues by setting the application's cooperative level, as follows:

    hr = g_pDD4->SetCooperativeLevel( hWnd, DDSCL_NORMAL );
    if( FAILED( hr ) )
        return hr;

The sample sets the cooperative level by calling the IDirectDraw4::SetCooperativeLevel method. Setting the cooperative level effectively tells the system whether or not the application will render in full-screen mode or in a window. (Note that some hardware cannot render into a window. You can detect such hardware by checking for the absence of the DDCAPS2_CANRENDERWINDOWED capability flag when you call IDirectDraw4::GetCaps.) The code requests windowed cooperative level, also called the "normal" cooperative level, by including the DDSCL_NORMAL in the second parameter it passes to SetCooperativeLevel. The SetCooperativeLevel method can fail if another application already controls owns full-screen, exclusive mode.

Note You can include the DDSCL_FPUSETUP cooperative level flag to increase performance. For more information about this cooperative level flag, see DirectDraw Cooperative Levels and FPU Precision. For general information, see Cooperative Levels in the DirectDraw documentation.

Once you create the DirectDraw object and set the cooperative level, you're ready to prepare the surfaces that will be used to contain and display a rendered scene. The Triangle sample does this as discussed in Step 2.2: Set Up DirectDraw Surfaces.


Step 2.2: Set Up DirectDraw Surfaces

After you create a DirectDraw object and set the cooperative level, you can create the surfaces that your application will use to render and display a scene. Exactly how you create your surfaces depends largely on whether or not your application will run in a window or in full-screen mode.

Full-screen Application Note Applications that will run in full-screen mode can create surfaces as shown in the preceding code examples. More often, these applications should take advantage of page-flipping, a feature only available in full-screen, exclusive mode. In this case, instead of explicitly creating two surfaces, you can create a flipping chain of surfaces with a single call. For more information, see Creating Complex Surfaces and Flipping Chains.

The Triangle sample, designed to run in a window, starts by creating a primary surface, which represents the display:

    // Prepare a surface description for the primary surface.
    DDSURFACEDESC2 ddsd;
    ZeroMemory( &ddsd, sizeof(DDSURFACEDESC2) );
    ddsd.dwSize         = sizeof(DDSURFACEDESC2);
    ddsd.dwFlags        = DDSD_CAPS;
    ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;

    // Create the primary surface.
    hr = g_pDD4->CreateSurface( &ddsd, &g_pddsPrimary, NULL );
    if( FAILED( hr ) )
        return hr;

The description for the primary surface doesn't contain information about dimensions or pixel format, as these traits are assumed to be the same as the display mode. If the current display mode is 800x600, 16-bit color, DirectDraw ensures that the primary surface matches. After creating the primary surface, you can create the render target surface. In the case of Triangle, this is a separate off-screen surface created as follows:

    ddsd.dwFlags        = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
    ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;

    // Set the dimensions of the back buffer. Note that if our window changes
    // size, we need to destroy this surface and create a new one.
    GetClientRect( hWnd, &g_rcScreenRect );
    GetClientRect( hWnd, &g_rcViewportRect );
    ClientToScreen( hWnd, (POINT*)&g_rcScreenRect.left );
    ClientToScreen( hWnd, (POINT*)&g_rcScreenRect.right );
    ddsd.dwWidth  = g_rcScreenRect.right - g_rcScreenRect.left;
    ddsd.dwHeight = g_rcScreenRect.bottom - g_rcScreenRect.top;

    // Create the back buffer. The most likely reason for failure is running
    // out of video memory. (A more sophisticated app should handle this.)
    hr = g_pDD4->CreateSurface( &ddsd, &g_pddsBackBuffer, NULL );
    if( FAILED( hr ) )
        return hr;

The preceding code creates an off-screen surface that is equal to the dimensions of the program window. There is no need to create a larger surface, because the dimensions of the window dictate what is visible to the user. (This code also initializes two global variables that are later used to set up the viewport and track the application window size and position.) As the preceding excerpt shows, you must include the DDSCAPS_3DDEVICE capability for any surface that will be used as a render target. This capability causes the system to allocate additional internal data structures that are used only for 3-D rendering. As when creating the primary surface, the pixel format for the off-screen surface is assumed to be the same as the display mode when it isn't provided in the surface description.

Note Applications that will use a depth buffer should create one and attach it to the render target surface at this point. For simplicity, this tutorial doesn't employ a depth buffer, but they are covered in Tutorial 2: Adding a Depth Buffer and in Depth Buffers.

After creating the primary and render target surface, you can create and attach a DirectDrawClipper object to the display surface. Using a clipper frees you from attempting to handle cases when the window is partially obscured by other windows, or when the window is partially outside the display area. Clippers aren't needed for applications that run in full-screen mode. The Triangle sample uses the following code to create a clipper and associate it with the display window:

    LPDIRECTDRAWCLIPPER pcClipper;

    // Create the clipper.
    hr = g_pDD4->CreateClipper( 0, &pcClipper, NULL );
    if( FAILED( hr ) )
        return hr;

    // Assign it to the window handle, then set
    // the clipper to the desired surface.
    pcClipper->SetHWnd( 0, hWnd );
    g_pddsPrimary->SetClipper( pcClipper );
    pcClipper->Release();

Having created the basic DirectDraw objects, you can move on to setting up the essential Direct3D objects that will render the scene. The Triangle sample performs this task in Step 2.3: Initialize Direct3D.


Step 2.3: Initialize Direct3D

After you create the surfaces your application will need to render and display a scene, you can begin initializing Direct3D objects by retrieving a pointer to the IDirect3D3 interface for the DirectDraw object, which is used to create all the objects you'll need to render a scene. Note that this interface is exposed by the DirectDraw object, and represents a separate set of features, not a separate object. You retrieve the IDirect3D3 interface by calling the IUnknown::QueryInterface method of the DirectDraw object. The following code from Triangle performs this task:

    // Query DirectDraw for access to Direct3D
    g_pDD4->QueryInterface( IID_IDirect3D3, (VOID**)&g_pD3D );
    if( FAILED( hr) )
        return hr;

After retrieving a pointer to the IDirect3D3 interface, you can create a rendering device by calling the IDirect3D3::CreateDevice method. The CreateDevice method accepts the globally unique identifier (GUID) of the desired device, the address of the IDirectDrawSurface4 interface for the surface that the device will render to, and the address of a variable that the method will set to an IDirect3DDevice3 interface pointer if the device object is created successfully. Although the tutorial uses hard-coded GUID values, a real application should enumerate devices to get a GUID. For information about device enumeration, see Enumerating Direct3D Devices.

(The Triangle sample checks the display mode prior to creating the device. If the display is set to a palettized mode, it exits. Attempting to create a device for a palettized surface that doesn't have an associated palette will cause the CreateDevice method to fail. This is done for simplicity. A real-world application should create a render target surface and attach a palette, or require that the user set their display mode to 16-bit color or higher.)

The following code, taken from Triangle, checks the display mode, and creates a rendering device:

    // Check the display mode, and
    ddsd.dwSize = sizeof(DDSURFACEDESC2);
    g_pDD4->GetDisplayMode( &ddsd );
    if( ddsd.ddpfPixelFormat.dwRGBBitCount <= 8 )
        return DDERR_INVALIDMODE;

    // The GUID here is hardcoded. In a real-world application
    // this should be retrieved by enumerating devices.
    hr = g_pD3D->CreateDevice( IID_IDirect3DHALDevice,
                               g_pddsBackBuffer,
                               &g_pd3dDevice, NULL );
    if( FAILED( hr ) )
    {
        // If the hardware GUID doesn't work, try a software device.
        hr = g_pD3D->CreateDevice(IID_IDirect3DRGBDevice,
                                  g_pddsBackBuffer,
                                  &g_pd3dDevice, NULL );
         if( FAILED( hr ) )
            return hr;
    }

The IDirect3D3::CreateDevice method can fail for many reasons. The most likely cause is when the primary display device doesn't support 3-D features. Another possibility is if the display hardware cannot render in the current display mode. These possibilities should be checked during device enumeration. To keep the code simple, Triangle attempts to create a software rendering device if the hardware device cannot be created.

Note Even though the CreateDevice method accepts a pointer to a DirectDrawSurface object, a rendering device is not a surface. Rather, it is a discrete COM object that uses a surface to contain graphics for a rendered scene.

After the device is created, you can create a viewport object and assign it to the device, as described in Step 2.4: Prepare the Viewport.


Step 2.4: Prepare the Viewport

After you create a rendering device, you can create a viewport object and assign it to the device. In short, the viewport determines how the geometry in a 3-D scene is clipped and then represented in the 2-D space of a display screen. (For a conceptual overview about viewports, see Viewports and Clipping.)

Setting up a viewport is a straight-forward process that starts with preparing the viewport parameters in a D3DVIEWPORT2 structure. The Triangle sample sets the viewport parameters to the dimensions of the render target surface, with a standard 3-D clipping region that exists from -1.0 to 1.0 in x, from 1.0 to -1.0 in y, and from 0.0 to 1.0 in z:

    // Set up the viewport data parameters
    D3DVIEWPORT2 vdData;
    ZeroMemory( &vdData, sizeof(D3DVIEWPORT2) );

    // Always set the structure size!
    vdData.dwSize       = sizeof(D3DVIEWPORT2);
    vdData.dwWidth      = g_rcScreenRect.right - g_rcScreenRect.left;
    vdData.dwHeight     = g_rcScreenRect.bottom - g_rcScreenRect.top;
    vdData.dvClipX      = -1.0f;
    vdData.dvClipWidth  = 2.0f;
    vdData.dvClipY      = 1.0f;
    vdData.dvClipHeight = 2.0f;
    vdData.dvMaxZ       = 1.0f;

Once the viewport parameter structure is ready, Triangle creates the viewport and assigns it to the rendering device. Note that it doesn't actually apply the parameters until after the viewport is assigned to the device. This is a requirement.

    // Create the viewport.
    hr = g_pD3D->CreateViewport( &g_pvViewport, NULL );
    if( FAILED( hr ) )
        return hr;

    // Associate the viewport with the device.
    g_pd3dDevice->AddViewport( g_pvViewport );

    // Set the parameters for the new viewport.
    g_pvViewport->SetViewport2( &vdData );

Assigning the viewport to the device merely adds it to an internal list of viewports for the device, it doesn't actually select the viewport to be used during rendering. The following code selects the viewport:

    // Set the current viewport for the device
    g_pd3dDevice->SetCurrentViewport( g_pvViewport );

Now that the basic DirectX objects have been created, you can start preparing the subordinate objects required to render scene, which is the topic of Step 3: Initialize the Scene.


Step 3: Initialize the Scene

After creating the primary Direct3D-related objects—a DirectDraw object, a rendering device, and a viewport—you can begin initializing the scene by setting up geometry, preparing materials, and configuring the transformation matrices your application will use. The Triangle sample uses an application-defined function, App_InitDeviceObjects, to perform the following steps that initialize the scene:

  • Step 3.1: Prepare Geometry
  • Step 3.2: Set Up Material and Initial Lighting States
  • Step 3.3: Prepare and Set Transformation Matrices


Step 3.1: Prepare Geometry

After you create the primary system objects used with DirectDraw and Direct3D, you can begin initializing the scene. The Triangle sample takes this opportunity to initialize geometry by defining vertices in an array of D3DVERTEX structure. Technically, you aren't required to set up the geometry at this time—you can do it anytime prior to calling rendering methods:

HRESULT App_InitDeviceObjects( LPDIRECT3DDEVICE3 pd3dDevice,
                               LPDIRECT3DVIEWPORT3 pvViewport )
{
    // Data for the geometry of the triangle. Note that this tutorial only
    // uses ambient lighting, so the vertices' normals are not actually used.
    D3DVECTOR p1( 0.0f, 3.0f, 0.0f );
    D3DVECTOR p2( 3.0f,-3.0f, 0.0f );
    D3DVECTOR p3(-3.0f,-3.0f, 0.0f );
    D3DVECTOR vNormal( 0.0f, 0.0f, 1.0f );

    // Initialize the 3 vertices for the front of the triangle
    g_pvTriangleVertices[0] = D3DVERTEX( p1, vNormal, 0, 0 );
    g_pvTriangleVertices[1] = D3DVERTEX( p2, vNormal, 0, 0 );
    g_pvTriangleVertices[2] = D3DVERTEX( p3, vNormal, 0, 0 );

    // Initialize the 3 vertices for the back of the triangle
    g_pvTriangleVertices[3] = D3DVERTEX( p1, -vNormal, 0, 0 );
    g_pvTriangleVertices[4] = D3DVERTEX( p3, -vNormal, 0, 0 );
    g_pvTriangleVertices[5] = D3DVERTEX( p2, -vNormal, 0, 0 );

The preceding code fragment defines three points in 3-D space that define a triangle that sits upright in the z=0 plane. After defining the geometry to be displayed, the Triangle sample prepares material and lighting parameters in Step 3.2: Set Up Material and Initial Lighting States.


Step 3.2: Set Up Material and Initial Lighting States

After you create the basic 3-D rendering objects (a DirectDraw object, a rendering device, and a viewport), you've got almost all you need to render a simple scene. The next thing to do is to create and configure a material and set some initial lighting states. These can all be changed later if needed. For an introduction to these concepts, see Lighting and Materials.

The Triangle sample starts by retrieving the IDirect3D3 interface pointer for the rendering device by calling the IDirect3DDevice3::GetDirect3D method (a pointer to the rendering device, and one to the viewport are passed to the App_InitDeviceObjects function from which this code is taken). Then, it creates a material object and sets material parameters, as shown here:

    // Create the material object.
    if( FAILED( pD3D->CreateMaterial( &g_pmtrlObjectMtrl, NULL ) ) )
        return E_FAIL;

    // Set properties for ambient reflectance.
    D3DMATERIAL       mtrl;
    D3DMATERIALHANDLE hmtrl;
    ZeroMemory( &mtrl, sizeof(D3DMATERIAL) );

    // Always set the structure size!
    mtrl.dwSize       = sizeof(D3DMATERIAL);
    mtrl.dcvAmbient.r = 1.0f;
    mtrl.dcvAmbient.g = 1.0f;
    mtrl.dcvAmbient.b = 0.0f;

    // Commit the properties to the material.
    g_pmtrlObjectMtrl->SetMaterial( &mtrl );

The preceding code creates a material object, represented by the IDirect3DMaterial3 interface, by calling the IDirect3D3::CreateMaterial object. The new interface is assigned to an application-defined global variable, g_pmtrlObjectMtrl. When created, a new material has no properties and cannot be used in rendering. The code prepares material properties in a D3DMATERIAL structure to describe a material that will reflect the red and green components of ambient light, making it appear yellow in the scene. (This tutorial only uses ambient light, so it only sets an ambient reflectance property. A real-world application would use direct light as well as ambient light, and should set therefore set diffuse and specular reflectance properties as well.) After preparing the material properties, the code applies them to the material object by calling the IDirect3DMaterial3::SetMaterial method.

Note When using textures, the object material is usually omitted or colored white.

After setting the material properties, you can retrieve the material handle that is used to select it for rendering. You retrieve a material handle by calling the IDirect3DMaterial3::GetHandle method. Once you have the material handle, you can select the current material by calling the IDirect3DDevice3::SetLightState method, passing the D3DLIGHTSTATE_MATERIAL enumerated value in the first parameter and the material handle in the second parameter. The Triangle sample does this with the following code:

    // Bind the material to the device.
    g_pmtrlObjectMtrl->GetHandle( pd3dDevice, &hmtrl );

    // Select the current material.
    pd3dDevice->SetLightState(  D3DLIGHTSTATE_MATERIAL, hmtrl );

After the current material is selected, all polygons will be rendered using this material. However, before anything in the scene will be visible you need to provide some light. The code in Triangle sets an ambient light level by calling the IDirect3DDevice3::SetLightState method to set the D3DLIGHTSTATE_AMBIENT light state for white ambient light:

    // Set up white ambient light.
    pd3dDevice->SetLightState(  D3DLIGHTSTATE_AMBIENT,  0xffffffff );

Now that the geometry, material, and initial lighting parameters are set, the sample moves on to setting up the transformation matrices. This is covered in Step 3.3: Prepare and Set Transformation Matrices.


Step 3.3: Prepare and Set Transformation Matrices

Another step in setting up a simple scene involved setting the world, view, and projection matrices. The system applies these matrices to geometry to place it in the scene, adjust for the camera's location and orientation, and scale vertex data to make distant objects appear smaller than near objects. (For a conceptual overview, see The Geometry Pipeline.)

The Triangle sample starts by creating an identity matrix in a D3DMATRIX structure, then it manipulates the matrix to produce the desired transformations. Once a matrix is ready, the code assigns it to the device by calling the IDirect3DDevice3::SetTransform method with the D3DTRANSFORMSTATE_WORLD, D3DTRANSFORMSTATE_VIEW, or D3DTRANSFORMSTATE_PROJECTION values:

    // Start by setting up an identity matrix.
    D3DMATRIX mat;
    mat._11 = mat._22 = mat._33 = mat._44 = 1.0f;
    mat._12 = mat._13 = mat._14 = mat._41 = 0.0f;
    mat._21 = mat._23 = mat._24 = mat._42 = 0.0f;
    mat._31 = mat._32 = mat._34 = mat._43 = 0.0f;

    // The world matrix controls the position and orientation
    // of the polygons in world space. We'll use it later to
    // spin the triangle.
    D3DMATRIX matWorld = mat;
    pd3dDevice->SetTransform( D3DTRANSFORMSTATE_WORLD, &matWorld );

    // The view matrix defines the position and orientation of
    // the camera. Here, we are just moving it back along the z-
    // axis by 10 units.
    D3DMATRIX matView = mat;
    matView._43 = 10.0f;
    pd3dDevice->SetTransform( D3DTRANSFORMSTATE_VIEW, &matView );

    // The projection matrix defines how the 3-D scene is "projected"
    // onto the 2-D render target surface. For more information,
    // see "What Is the Projection Transformation?"

    // Set up a very simple projection that scales x and y
    // by 2, and translates z by -1.0.
    D3DMATRIX matProj = mat;
    matProj._11 =  2.0f;
    matProj._22 =  2.0f;
    matProj._34 =  1.0f;
    matProj._43 = -1.0f;
    matProj._44 =  0.0f;
    pd3dDevice->SetTransform( D3DTRANSFORMSTATE_PROJECTION, &matProj );

After setting the transformations, Triangle is done setting up the scene. The App_InitDeviceObjects application-defined function returns S_OK to the caller, the Initialize3DEnvironment application-defined function. The Initialize3DEnvironment function then returns that value to WinMain, which moves on to process system messages, as discussed in Step 4: Monitor System Messages.


Step 4: Monitor System Messages

After you've created the application window, created the DirectX objects, then initialized the scene, you're ready to render the scene. In most cases Windows applications monitor system messages in their message loop, and render frames whenever no messages are in queue. The Triangle sample is no different; it uses the following code for its message loop:

    BOOL bGotMsg;
    MSG  msg;
    PeekMessage( &msg, NULL, 0U, 0U, PM_NOREMOVE );
    g_bReady = TRUE;

    while( WM_QUIT != msg.message  )
    {
        // Use PeekMessage() if the app is active, so we can use idle time to
        // render the scene. Else, use GetMessage() to avoid eating CPU time.
        if( g_bActive )
            bGotMsg = PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE );
        else
            bGotMsg = GetMessage( &msg, NULL, 0U, 0U );

        if( bGotMsg )
        {
                TranslateMessage( &msg );
                DispatchMessage( &msg );
        }
        else
        {
            // Render a frame during idle time (no messages are waiting)
            if( g_bActive && g_bReady )
                Render3DEnvironment();
        }
    }

This code uses a global flag variable, g_bActive, to keep track of when it's active, and another variable, g_bReady, to indicate that all system objects are ready to render a scene. The application sets g_bActive to FALSE whenever the window isn't visible, and it sets the g_bReady variable to FALSE whenever it needs to recreate the objects used to render the scene. (The latter situation is covered in Handle Window Resizing.)

If the application is active, it checks the message queue to see if there are any pending messages. If there are messages in queue, the code dispatches them like any other Windows application. Otherwise, it calls the Render3DEnvironment application-defined function to render a frame of the scene, which is the topic of Step 5: Render and Display the Scene.


Step 5: Render and Display the Scene

Whenever your application isn't processing system messages, it can render a frame of a scene. The Triangle sample renders the scene in the Render3DEnvironment application-defined function called from WinMain whenever the message queue is empty. The Render3DEnvironment function subdivides the task into three substeps:

  • Step 5.1: Update the Scene
  • Step 5.2: Render the Scene
  • Step 5.3: Update the Display


Step 5.1: Update the Scene

Immediately after it is called, the Render3DEnvironment application-defined function in the Triangle sample calls App_FrameMove (another application-defined function). The App_FrameMove function simply updates the world matrix that Direct3D applies to the geometry to reflect a rotation around the y-axis based on an internal count value, passed to the function in the fTimeKey parameter. Because the rotation is applied once per frame, the end result looks like the model is rotating in place.

HRESULT App_FrameMove( LPDIRECT3DDEVICE3 pd3dDevice, FLOAT fTimeKey )
{
    // For this simple tutorial, we are rotating the triangle about the y-axis.
    // To do this, just set up a 4x4 matrix defining the rotation, and set it
    // as the new world transform.
    D3DMATRIX matSpin;
    matSpin._11 = matSpin._22 = matSpin._33 = matSpin._44 = 1.0f;
    matSpin._12 = matSpin._13 = matSpin._14 = matSpin._41 = 0.0f;
    matSpin._21 = matSpin._23 = matSpin._24 = matSpin._42 = 0.0f;
    matSpin._32 = matSpin._32 = matSpin._34 = matSpin._43 = 0.0f;

    matSpin._11 = (FLOAT)cos( fTimeKey );
    matSpin._33 = (FLOAT)cos( fTimeKey );
    matSpin._13 = (FLOAT)sin( fTimeKey );
    matSpin._31 = (FLOAT)sin( fTimeKey );

    pd3dDevice->SetTransform( D3DTRANSFORMSTATE_WORLD, &matSpin );

    return S_OK;
}

In the real world, of course, your applications will do much more than apply a single rotation on a single model. (For more information rotation matrices, see Rotation in the 3-D Transformations section.)

After you update the geometry in the scene, you can render it to the render target surface, as the Triangle sample does in Step 5.2: Render the Scene.


Step 5.2: Render the Scene

Once the geometry has been updated to reflect the desired animation, you can render the scene. The Triangle sample takes a typical approach: the App_Render application-defined function called from the sample's Render3DEnvironment function starts by clearing the viewport:

HRESULT App_Render( LPDIRECT3DDEVICE3 pd3dDevice,
                    LPDIRECT3DVIEWPORT3 pvViewport,
                    D3DRECT* prcViewportRect )
{
    // Clear the viewport to a blue color.
    pvViewport->Clear2( 1UL, prcViewportRect, D3DCLEAR_TARGET, 0x000000ff,
                        0L, 0L );

The preceding code calls the IDirect3DViewport3::Clear2 method to clear the viewport. The first two methods that the Clear2 method accepts are the address of an array of rectangles that describe the areas on the render target surface to be cleared, and a value that informs the method how many rectangles from the array should be cleared. In most cases, you'll use a single rectangle that covers the entire render target. The third parameter determines the method's behavior. It can clear a render-target surface, an associated depth buffer, the stencil buffer, or any combination of the three. Because this tutorial doesn't use a depth buffer, D3DCLEAR_TARGET is the only flag used. The last three parameters are set to reflect clearing values for the render target, depth buffer, and stencil buffer. The Triangle sample sets the clear color for the render target surface to blue. Because the remaining parameters aren't used in this tutorial, the code just sets them to zero. The Clear2 method will ignores them when the corresponding flag isn't present.

After clearing the viewport, the Triangle sample informs Direct3D that rendering will begin, renders the scene, then signals that rendering is complete, as shown here:

    // Begin the scene.
    if( FAILED( pd3dDevice->BeginScene() ) )
        return E_FAIL;

    // Draw the triangle using a DrawPrimitive() call.
    pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, D3DFVF_VERTEX,
                               g_pvTriangleVertices, 6, NULL );

    // End the scene.
    pd3dDevice->EndScene();

    return S_OK;
}

The IDirect3DDevice3::BeginScene and IDirect3DDevice3::EndScene methods signal to the system when rendering is beginning or is complete. You can only call rendering methods between calls to these methods. Even if rendering methods fail, you should call EndScene before calling BeginScene again.

After rendering the scene to the off-screen render target, you can update the user's display. The tutorial sample performs this in Step 5.3: Update the Display.


Step 5.3: Update the Display

Once a scene has been rendered to the render-target surface, you can show the results on screen. A windowed application usually does this by blitting the content of the render-target surface to the primary surface, and a full-screen application that employs page-flipping would simply flip the surfaces in the flipping chain. The Triangle sample uses the former method because it runs in a window, using the following code:

HRESULT ShowFrame()
{
    // The g_pddsPrimary variable will be NULL when
    // the application is in the middle of recreating
    // DirectDraw objects.
    if( NULL == g_pddsPrimary )
        return E_FAIL;

    // We are in windowed mode, so perform a blit from the backbuffer to the
    // correct position on the primary surface
    return g_pddsPrimary->Blt( &g_rcScreenRect, g_pddsBackBuffer,
                               &g_rcViewportRect, DDBLT_WAIT, NULL );
}

Note that the preceding application-defined function simply blits the entire contents of the render target surface to the window on the desktop. The tutorial tracks the destination rectangle for the blit in the g_rcScreenRect global variable. This rectangle is updated whenever the user moves the window, as covered in the Handle Window Movement section.


Step 6: Shut Down

At some point during execution, your application must shut down. Shutting down a DirectX application not only means that you should destroy the application window, but you also deallocate any DirectX objects your application uses and invalidate the pointers to them. The Triangle calls an application-defined function to handle this cleanup, called Cleanup3DEnvironment, when it receives a WM_DESTROY message:

HRESULT Cleanup3DEnvironment()
{
    // Cleanup any objects created for the scene
    App_DeleteDeviceObjects( g_pd3dDevice, g_pvViewport );

    // Release the DDraw and D3D objects used by the app
    if( g_pvViewport )     g_pvViewport->Release();
    if( g_pD3D )           g_pD3D->Release();
    if( g_pddsBackBuffer ) g_pddsBackBuffer->Release();
    if( g_pddsPrimary )    g_pddsPrimary->Release();
    if( g_pDD4 )           g_pDD4->Release();

    // Do a safe check for releasing the D3DDEVICE. RefCount should be zero.
    if( g_pd3dDevice )
        if( 0 < g_pd3dDevice->Release() )
            return E_FAIL;

    // Do a safe check for releasing DDRAW. RefCount should be zero.
    if( g_pDD1 )
        if( 0 < g_pDD1->Release() )
            return E_FAIL;

    g_pvViewport     = NULL;
    g_pd3dDevice     = NULL;
    g_pD3D           = NULL;
    g_pddsBackBuffer = NULL;
    g_pddsPrimary    = NULL;
    g_pDD4           = NULL;
    g_pDD1           = NULL;

    return S_OK;
}

The preceding function deallocates the DirectX objects it uses by calling the IUnknown::Release methods for each object. Because the tutorial follows COM rules, the reference counts for most objects should become zero and are automatically removed from memory.

In addition to shut down, there are times during normal execution—such as when the user changes the desktop resolution or color depth—when you might need to destroy and re-create the DirectX objects in use. As a result, it's handy to keep your application's cleanup code in one place, which can be called when the need arises.


Handle Window Movement

Any DirectX application that runs in a window must track the position of the client area for the window so that blits to the window will appear on the desktop in the right place. Failing to track this results in graphics appearing outside the application window—a confusing sight for the user. The Triangle sample responds to the WM_MOVE messages that the system sends to the window procedure as shown here:

 .
 .
 .
    case WM_MOVE:
        // Move messages need to be tracked to update the screen rects
        // used for blitting the backbuffer to the primary.
        if( g_bActive && g_bReady )
            OnMove( (SHORT)LOWORD(lParam), (SHORT)HIWORD(lParam) );
        break;
 .
 .
 .

The g_bActive variable is set elsewhere in the window procedure to reflect whether or not the window is active—when the window is minimized it's set to FALSE. The g_bReady variable is TRUE except when the application is in the midst of re-creating the DirectX objects it uses. If these variables are both TRUE, the OnMove application-defined function gets called:

VOID OnMove( INT x, INT y )
{
    DWORD dwWidth  = g_rcScreenRect.right - g_rcScreenRect.left;
    DWORD dwHeight = g_rcScreenRect.bottom - g_rcScreenRect.top;
    SetRect( &g_rcScreenRect, x, y, x + dwWidth, y + dwHeight );
}

This function simply recalculates the size of the global variable, g_rcScreenRect, that the tutorial uses as the destination rectangle when it updates the display in Step 5.3: Update the Display.


Handle Window Resizing

Any DirectX application that runs in a window must respond to any WM_SIZE messages that the system sends. The render target surface is usually kept as small as possible to conserve memory, and the smallest size is usually the size of the window client area. When window size increases, you must destroy the render target surface and the associated objects and re-create it at an appropriate size. Technically, an application could do this only when the window gets larger, and respond to situations when window size decreases by adjusting the viewport and decreasing the size of the blit accordingly. For simplicity, this tutorial destroys and re-creates the objects it uses whenever it receives a WM_SIZE message:

         .
         .
         .
        case WM_SIZE:
            // Check to see if we are losing or gaining our window.
            // Set the active flag to match.
            if( SIZE_MAXHIDE==wParam || SIZE_MINIMIZED==wParam )
                g_bActive = FALSE;
            else g_bActive = TRUE;

            // A new window size will require a new back buffer size. The
            // easiest way to achieve this is to release and re-create
            // everything. Note: if the window gets too big, we may run out
            // of video memory and need to exit. This simple app exits
            // without displaying error messages, but a real app would
            // behave itself much better.
            if( g_bActive && g_bReady )
            {
                g_bReady = FALSE;
                if( FAILED( Cleanup3DEnvironment() ) )
                    DestroyWindow( hWnd );
                if( FAILED( Initialize3DEnvironment( hWnd ) ) )
                    DestroyWindow( hWnd );
                g_bReady = TRUE;
            }
            break;
         .
         .
         .

Note that the preceding code sets a global variable to communicate to other portions of the code that the DirectX objects in use are being invalidated. In addition, this code calls the application-defined Cleanup3DEnvironment function to destroy the objects, which is also called during application shut-down. Ending the application is discussed in Step 6: Shut Down.


Tutorial 2: Adding a Depth Buffer

Direct3D applications often rely on depth buffers to properly display objects in a scene. For a conceptual overview, see Depth Buffers. To use depth buffering, you must enumerate supported depth-buffer formats, create a depth-buffer surface, attach it to a render-target surface, and enable depth buffering for the rendering device.

This tutorial parallels the code in the Triangle sample project which uses the most commonly supported type of depth buffer, a z-buffer. The ZBuffer sample performs the following steps to use a z-buffer:

  • Step 1: Enumerate Depth-Buffer Formats
  • Step 2: Create the Depth Buffer
  • Step 3: Attach the Depth Buffer
  • Step 4: Enable Depth Buffering

Note The code in the ZBuffer sample is nearly identical to the code in Triangle. This tutorial focuses only on the depth-buffer code unique to ZBuffer, and does not cover setting up Direct3D, rendering, shutting down, or handling Windows messages. For information on these tasks, see Tutorial 1: Rendering a Single Triangle.

Because some rendering devices require depth buffers to be located in particular places in memory, the system requires that you create and attach the depth-buffer surface to the render-target surface before you create a rendering device.


Step 1: Enumerate Depth-Buffer Formats

Before you can create a depth buffer you must determine what depth-buffer formats, if any, are supported by the rendering device. Call the IDirect3D3::EnumZBufferFormats method to enumerate the depth-buffer formats that the device supports. The ZBuffer sample uses the following code to enumerate depth-buffer formats:

    //-------------------------------------------------------------------------
    // Create the z-buffer AFTER creating the back buffer and BEFORE creating
    // the d3ddevice.
    //
    // Note: before creating the z-buffer, apps may want to check the device
    // caps for the D3DPRASTERCAPS_ZBUFFERLESSHSR flag. This flag is true for
    // certain hardware that can do HSR (hidden-surface-removal) without a
    // z-buffer. For those devices, there is no need to create a z-buffer.
    //-------------------------------------------------------------------------

    DDPIXELFORMAT ddpfZBuffer;  // Passing this as a VOID*

    g_pD3D->EnumZBufferFormats( *pDeviceGUID,
                                EnumZBufferCallback, (VOID*)&ddpfZBuffer );

The EnumZBufferFormats method accepts the globally unique identifier (GUID) of the device for which the formats will be enumerated, the address of a callback function, and the address of an arbitrary data structure that will be passed to the callback function. The callback function you provide must conform to the D3DEnumPixelFormatsCallback function prototype. The system calls the specified callback function once for each supported depth-buffer format, unless the callback function returns D3DENUMRET_CANCEL. The ZBuffer sample processes callbacks as follows:

static HRESULT WINAPI EnumZBufferCallback( DDPIXELFORMAT* pddpf,
                                           VOID* pddpfDesired )
{
    // If this is ANY type of depth-buffer, stop.
    if( pddpf->dwFlags == DDPF_ZBUFFER )
    {
        memcpy( pddpfDesired, pddpf, sizeof(DDPIXELFORMAT) );

        // Return with D3DENUMRET_CANCEL to end the search.
        return D3DENUMRET_CANCEL;
    }

    // Return with D3DENUMRET_OK to continue the search.
    return D3DENUMRET_OK;
}

When the system calls the callback function, it passes the address of a DDPIXELFORMAT structure that describes the pixel format of the depth buffer. The dwFlags member will contain DDPF_ZBUFFER for any pixel formats that include depth-buffer bits. If so, the dwZBufferBitDepth member includes an integer that represents the number of bits in the pixel format reserved for depth information, and the dwZBitMask member masks the relevant bits.

For simplicity, this tutorial only uses z-buffers, which are the most common type of depth buffer. It ignores any other formats (such as DDPF_STENCILBUFFER) that the system enumerates. Applications could also check the bit depth of the z-buffer (8-, 16-, 24-, 32-bit) and make a choice based on that as well. If a suitable format is found, the function copies the provided DDPIXELFORMAT structure to the address passed in the second parameter (also a DDPIXELFORMAT structure), and returns D3DENUMRET_CANCEL to stop the enumeration.

After you determine the format of the depth buffer, you can create a DirectDrawSurface that uses that format, which is the topic of Step 2: Create the Depth Buffer.


Step 2: Create the Depth Buffer

Now that you have chosen the depth-buffer format, you can create the DirectDrawSurface object that will become the depth buffer. The pixel format of the surface is the one determined through enumeration, but the surface dimensions must be identical to the render-target surface to which it will be attached. The ZBuffer sample uses the following code for this task:

    // If the enumerated format is good (it should be), the
    // dwSize member will be properly initialized. Check this
    // just in case.
    if( sizeof(DDPIXELFORMAT) != ddpfZBuffer.dwSize )
        return E_FAIL;

    // Get z-buffer dimensions from the render target
    // Setup the surface desc for the z-buffer.
    ddsd.dwFlags        = DDSD_CAPS|DDSD_WIDTH|DDSD_HEIGHT|DDSD_PIXELFORMAT;
    ddsd.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
    ddsd.dwWidth        = g_rcScreenRect.right - g_rcScreenRect.left;
    ddsd.dwHeight       = g_rcScreenRect.bottom - g_rcScreenRect.top;
    memcpy( &ddsd.ddpfPixelFormat, &ddpfZBuffer, sizeof(DDPIXELFORMAT) );

    // Software devices require system-memory depth buffers.
    if( IsEqualIID( *pDeviceGUID, IID_IDirect3DHALDevice ) )
        ddsd.ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY;
    else
        ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;

    // Create the depth-buffer.
    if( FAILED( hr = g_pDD4->CreateSurface( &ddsd, &g_pddsZBuffer, NULL ) ) )
        return hr;

The preceding code simply prepares a DDSURFACEDESC2 structure for the depth buffer, using the dimensions of the render-target surface calculated from previously set global variables. The pixel format information retrieved during the previous step, Step 1: Enumerate Depth-Buffer Formats, is copied into the surface description.

Note A hardware device can use a depth buffer regardless of its location in memory. When using a hardware device, it's best to let the device determine the best location for the buffer by omitting the DDSCAPS_VIDEOMEMORY and DDSCAPS_SYSTEMMEMORY surface capability flags. However, a software device can only be created if the depth buffer exists in system memory. The preceding code checks for this possibility and includes the DDSCAPS_SYSTEMMEMORY flag if necessary.

Once the surface description is ready, the code calls the IDirectDraw4::CreateSurface method to create the new depth-buffer surface. After the depth buffer is created, it can be attached to the surface that will be used as the render target, as described in Step 3: Attach the Depth Buffer.


Step 3: Attach the Depth Buffer

Once the depth buffer is created, you need to attach it to the surface that will be used as the render target. Do this by calling the IDirectDrawSurface4::AddAttachedSurface method of the render-target surface. The ZBuffer sample performs this with the following code:

    // Attach the z-buffer to the back buffer.
    if( FAILED( hr = g_pddsBackBuffer->AddAttachedSurface( g_pddsZBuffer ) ) )
        return hr;

Once the depth buffer is attached to the render-target surface, the system will automatically use the depth buffer whenever depth buffering is enabled, as discussed in Step 4: Enable Depth Buffering.


Step 4: Enable Depth Buffering

After attaching the depth buffer to the render-target surface, you can create a rendering device from the render target. Given a rendering device, you enable depth buffering by setting the D3DRENDERSTATE_ZENABLE render state for the device. The D3DZBUFFERTYPE enumerated type includes members to set the depth-buffer render state. The D3DZB_TRUE member (or TRUE) enables z-buffering. The ZBuffer sample enables z-buffering during scene rendering in the App_Render application-defined function. The following is the appropriate excerpt from App_Render:

    // Enable z-buffering.
    pd3dDevice->SetRenderState( D3DRENDERSTATE_ZENABLE, TRUE );

Although this tutorial enables depth-buffering each frame, it is not necessary to do so. A real-world application would likely set the D3DRENDERSTATE_ZENABLE render state during scene initialization, only changing to disable depth buffering or to choose another type of depth buffering.

Note The D3DZBUFFERTYPE enumerated type includes the D3DZB_USEW value to enable w-based depth comparisons on compliant hardware. For more information, see Depth Buffers.


Direct3D Immediate Mode Reference

This section contains reference information for the application programming interface (API) elements provided by Direct3D® Immediate Mode. Reference material is divided into the following categories:

  • Interfaces
  • D3D_OVERLOADS
  • Callback Functions
  • Macros
  • Structures
  • Enumerated Types
  • Other Types
  • Flexible Vertex Format Flags
  • Return Values


Interfaces

This section contains reference information for the COM interfaces provided by Direct3D Immediate Mode. The following interfaces are covered:

  • IDirect3D3
  • IDirect3DDevice
  • IDirect3DDevice3
  • IDirect3DExecuteBuffer
  • IDirect3DLight
  • IDirect3DMaterial3
  • IDirect3DTexture2
  • IDirect3DVertexBuffer
  • IDirect3DViewport3

Some stub methods that were exposed in previous releases of DirectX are no longer exposed. For more information, see Unimplemented Methods.


IDirect3D3

Applications use the methods of the IDirect3D3 interface to create Direct3D objects and set up the environment. This section is a reference to the methods of this interface. For a conceptual overview, see IDirect3D3 Interface.

The IDirect3D3 interface is obtained by calling the QueryInterface method from a DirectDraw object.

The methods of the IDirect3D3 interface can be organized into the following groups:

Creation | CreateDevice
 | CreateLight
 | CreateMaterial
 | CreateVertexBuffer
 | CreateViewport
Enumeration | EnumDevices
 | EnumZBufferFormats
 | FindDevice
Miscellaneous | EvictManagedTextures

The IDirect3D3 interface extends the IDirect3D2 interface by adding methods that enable applications to create vertex buffers and enumerate texture map and depth-buffer formats.

The IDirect3D3 interface, like all COM interfaces, inherits the IUnknown interface methods. The IUnknown interface supports the following three methods:

IUnknown | AddRef
 | QueryInterface
 | Release

The LPDIRECT3D3, LPDIRECT3D2, and LPDIRECT3D types are defined as pointers to the IDirect3D3, IDirect3D2 and IDirect3D interfaces:

typedef struct IDirect3D    *LPDIRECT3D;
typedef struct IDirect3D2   *LPDIRECT3D2;
typedef struct IDirect3D3   *LPDIRECT3D3;

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.

See Also

Retrieving an IDirect3D3 Interface, Direct3D and DirectDraw


IDirect3D3::CreateDevice

The IDirect3D3::CreateDevice method creates a Direct3D device to be used with the DrawPrimitive methods.

HRESULT CreateDevice(
  REFCLSID rclsid,
  LPDIRECTDRAWSURFACE4 lpDDS,
  LPDIRECT3DDEVICE3 *  lplpD3DDevice,
  LPUNKNOWN pUnkOuter   // See remarks
);

Parameters

rclsid
Class identifier for the new device. This value can be IID_IDirect3DHALDevice, IID_IDirect3DMMXDevice, or IID_IDirect3DRGBDevice. The IID_IDirect3DRampDevice, used for the ramp emulation device, is not supported by IDirect3D3. To use ramp emulation, you must use the legacy IDirect3D2 interface.
lpDDS
Address of the IDirectDrawSurface4 interface for the DirectDrawSurface object that will be the device's rendering target. The surface must have been created as a 3-D device by using the DDSCAPS_3DDEVICE capability.
lplpD3DDevice
Address that points to the new IDirect3DDevice3 interface when the method returns.
pUnkOuter
This parameter is provided for future compatibility with COM aggregation features. Currently, however, the IDirect3D3::CreateDevice method returns an error if this parameter is anything but NULL.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value is an error. The method returns DDERR_INVALIDPARAMS if one of the arguments is invalid.

Remarks

This method was introduced with the IDirect3D2 interface. In previous versions of Direct3D, devices could be created only by calling the IDirectDrawSurface::QueryInterface method; devices created in this manner can only be used with execute buffers.

In the IDirect3D2 interface, the CreateDevice method accepts only three parameters, which are identical to the first three parameters for the IDirect3D3::CreateDevice method.

When you call IDirect3D3::CreateDevice, you create a device object that is separate from a DirectDraw surface object. This device uses a DirectDraw surface as a rendering target.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.

See Also

IDirect3DDevice3, Creating a Direct3D Device, Direct3D Devices


IDirect3D3::CreateLight

The IDirect3D3::CreateLight method allocates a Direct3DLight object. This object can then be associated with a viewport by using the IDirect3DViewport3::AddLight method.

HRESULT CreateLight(
  LPDIRECT3DLIGHT* lplpDirect3DLight,
  IUnknown* pUnkOuter
);

Parameters

lplpDirect3DLight
Address that will be filled with a pointer to an IDirect3DLight interface if the call succeeds.
pUnkOuter
This parameter is provided for future compatibility with COM aggregation features. Currently, however, the IDirect3D3::CreateLight method returns an error if this parameter is anything but NULL.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value may be one of the following values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS

Remarks

This method is unchanged from its implementation in the IDirect3D2 interface.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.

See Also

IDirect3DLight, Lights, Using Lights, Lighting and Materials


IDirect3D3::CreateMaterial

The IDirect3D3::CreateMaterial method allocates a Direct3DMaterial3 object.

HRESULT CreateMaterial(
  LPDIRECT3DMATERIAL3* lplpDirect3DMaterial,
  IUnknown* pUnkOuter
);

Parameters

lplpDirect3DMaterial
Address that will be filled with a pointer to an IDirect3DMaterial3 interface if the call succeeds.
pUnkOuter
This parameter is provided for future compatibility with COM aggregation features. Currently, however, CreateMaterial returns an error if this parameter is anything but NULL.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value is an error. For a list of possible return codes, see Direct3D Immediate Mode Return Values.

Remarks

In the IDirect3D2 interface, this method retrieves a pointer to an IDirect3DMaterial2 interface, not an IDirect3DMaterial3 interface.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.

See Also

Materials, Lighting and Materials


IDirect3D3::CreateVertexBuffer

The IDirect3D3::CreateVertexBuffer method creates a vertex buffer object.

HRESULT CreateVertexBuffer(
  LPD3DVERTEXBUFFERDESC lpVBDesc,
  LPDIRECT3DVERTEXBUFFER* lpD3DVertexBuffer,
  DWORD dwFlags,
  LPUNKNOWN pUnkOuter
);

Parameters

lpVBDesc
Address of a D3DVERTEXBUFFERDESC structure that describes the format and number of vertices that the vertex buffer will contain.
lpD3DVertexBuffer
Address of a variable that will contain a pointer to a IDirect3DVertexBuffer interface for the new vertex buffer.
dwFlags
Clipping flag value. Set this parameter to 0 to create a vertex buffer that can contain clipping information for untransformed or transformed vertices, or use the D3DDP_DONOTCLIP flag to create a vertex buffer that will contain transformed vertices, but no clipping information.
pUnkOuter
This parameter is provided for future compatibility with COM aggregation features. Currently, however, CreateVertexBuffer returns an error if this parameter is anything but NULL.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value may be one of the following values:

CLASS_E_NOAGGREGATION
D3DERR_INVALIDVERTEXFORMAT
D3DERR_VBUF_CREATE_FAILED
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_OUTOFMEMORY

Remarks

This method was introduced with the IDirect3D3 interface.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.

See Also

IDirect3DVertexBuffer, Vertex Buffers


IDirect3D3::CreateViewport

The IDirect3D3::CreateViewport method creates a Direct3DViewport object. The viewport is associated with a Direct3DDevice object by using the IDirect3DDevice3::AddViewport method.

HRESULT CreateViewport(
  LPDIRECT3DVIEWPORT3* lplpD3DViewport,
  IUnknown* pUnkOuter
);

Parameters

lplpD3DViewport
Address that will be filled with a pointer to an IDirect3DViewport3 interface if the call succeeds.
pUnkOuter
This parameter is provided for future compatibility with COM aggregation features. Currently, however, the IDirect3D3::CreateViewport method returns an error if this parameter is anything but NULL.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value may be one of the following values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS

Remarks

In the IDirect3D interface, this method retrieves a pointer to an IDirect3DViewport interface, not an IDirect3DViewport3 interface.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.


IDirect3D3::EnumDevices

The IDirect3D3::EnumDevices method enumerates all Direct3D device drivers installed on the system.

HRESULT EnumDevices(
  LPD3DENUMDEVICESCALLBACK lpEnumDevicesCallback,
  LPVOID lpUserArg
);

Parameters

lpEnumDevicesCallback
Address of the D3DEnumDevicesCallback callback function that the enumeration procedure will call every time a match is found.
lpUserArg
Address of application-defined data passed to the callback function.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value may be one of the following values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS

Remarks

To use execute buffers with an MMX device, you must call the IDirect3D3::CreateDevice method to create an MMX IDirect3DDevice3 interface and then use the QueryInterface method to create an IDirect3DDevice interface from IDirect3DDevice3.

MMX devices are enumerated only by IDirect3D3::EnumDevices and IDirect3D2::EnumDevices, not by IDirect3D::EnumDevices. If you use the QueryInterface method to create an IDirect3D interface from IDirect3D3 before you enumerate the Direct3D drivers, the enumeration will behave like IDirect3D::EnumDevices — no MMX devices will be enumerated.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.


IDirect3D3::EnumZBufferFormats

The IDirect3D3::EnumZBufferFormats method enumerates the supported depth-buffer formats for a specified device.

HRESULT EnumZBufferFormats(
  REFCLSID riidDevice,
  LPD3DENUMPIXELFORMATSCALLBACK lpEnumCallback,
  LPVOID   lpContext
);

Parameters

riidDevice
Reference to a globally unique identifier for the device whose depth-buffer formats will be enumerated.
lpEnumCallback
Address of a D3DEnumPixelFormatsCallback callback function that will be called for each supported depth-buffer format.
lpContext
Application-defined data that is passed to the callback function.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value may be one of the following values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_NOZBUFFERHW
DDERR_OUTOFMEMORY

Remarks

This method was introduced with the IDirect3D3 interface.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.


IDirect3D3::EvictManagedTextures

The IDirect3D3::EvictManagedTextures method purges all managed textures from local or non-local video memory.

HRESULT EvictManagedTextures();

Parameters

None.

Return Values

This method returns D3D_OK.

Remarks

This method causes Direct3D to remove any texture surfaces created with the DDSCAPS2_TEXTUREMANAGE flag from local or non-local video memory.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.

See Also

Automatic Texture Management


IDirect3D3::FindDevice

The IDirect3D3::FindDevice method finds a device with specified characteristics and retrieves a description of it.

HRESULT FindDevice(
  LPD3DFINDDEVICESEARCH lpD3DFDS,
  LPD3DFINDDEVICERESULT lpD3DFDR
);

Parameters

lpD3DFDS
Address of the D3DFINDDEVICESEARCH structure describing the device to be located.
lpD3DFDR
Address of the D3DFINDDEVICERESULT structure describing the device if it is found.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value is an error. For a list of possible return codes, see Direct3D Immediate Mode Return Values.

Remarks

This method is unchanged from its implementation in the IDirect3D2 interface.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.


IDirect3DDevice

Applications use the methods of the IDirect3DDevice interface to retrieve and set the capabilities of Direct3D devices. This section is a reference to the methods of these interface. For a conceptual overview, see Direct3D Devices.

The IDirect3DDevice interface supports applications that work with execute buffers. It has been extended by the IDirect3DDevice3 interface, which supports the DrawPrimitive methods.

The Direct3DDevice object is obtained by calling the QueryInterface method from a DirectDrawSurface object that was created as a 3-D–capable surface.

The methods of the IDirect3DDevice interface can be organized into the following groups.

Execute buffers | CreateExecuteBuffer
 | Execute
Information | EnumTextureFormats
 | GetCaps
 | GetDirect3D
 | GetPickRecords
 | GetStats
Matrices | CreateMatrix
 | DeleteMatrix
 | GetMatrix
 | SetMatrix
Miscellaneous | Initialize
 | Pick
 | SwapTextureHandles
Scenes | BeginScene
 | EndScene
Viewports | AddViewport
 | DeleteViewport
 | NextViewport

The IDirect3DDevice interface, like all COM interfaces, inherits the IUnknown interface methods. The IUnknown interface supports the following three methods:

IUnknown | AddRef
 | QueryInterface
 | Release

The LPDIRECT3DDEVICE type is defined as a pointer to the IDirect3DDevice interface:

typedef struct IDirect3DDevice        *LPDIRECT3DDEVICE;

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.

See Also

Execute Buffers


IDirect3DDevice::AddViewport

The IDirect3DDevice::AddViewport method adds the specified viewport to the list of viewport objects associated with the device and increments the reference count of the viewport.

HRESULT AddViewport(
  LPDIRECT3DVIEWPORT lpDirect3DViewport
);

Parameters

lpDirect3DViewport
Address of the IDirect3DViewport interface of the viewport that should be associated with this device.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value may be one of the following values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS

Remarks

In the IDirect3DDevice3 interface, this method accepts a pointer to an IDirect3DViewport3 interface.

This method will fail, returning DDERR_INVALIDPARAMS, if you attempt to add a viewport that has already been assigned to the device.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.


IDirect3DDevice::BeginScene

The IDirect3DDevice::BeginScene method begins a scene. Applications must call this method before performing any rendering, and must call IDirect3DDevice::EndScene when rendering is complete, and before calling IDirect3DDevice::BeginScene again.

HRESULT BeginScene();

Parameters

None.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value is an error.

Remarks

Do not attempt to use GDI functions that use the device context of a render-target surface between calls to BeginScene and EndScene. Attempts to do so can prevent the results of the GDI operations from being visible. If your application uses GDI functions, make sure that all GDI calls are made outside of the scene functions.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.

See Also

IDirect3DDevice::EndScene, Beginning and Ending a Scene


IDirect3DDevice::CreateExecuteBuffer

The IDirect3DDevice::CreateExecuteBuffer method allocates an execute buffer for a display list.

HRESULT CreateExecuteBuffer(
  LPD3DEXECUTEBUFFERDESC   lpDesc,
  LPDIRECT3DEXECUTEBUFFER *lplpDirect3DExecuteBuffer,
  IUnknown *pUnkOuter
);

Parameters

lpDesc
Address of a D3DEXECUTEBUFFERDESC structure that describes the Direct3DExecuteBuffer object to be created. The call will fail if a buffer of at least the specified size cannot be created.
lplpDirect3DExecuteBuffer
Address of a pointer that will be filled with the address of the new Direct3DExecuteBuffer object.
pUnkOuter
This parameter is provided for future compatibility with COM aggregation features. Currently, however, this method returns an error if this parameter is anything but NULL.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value may be one of the following values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS

Remarks

The display list may be read by hardware DMA into VRAM for processing. All display primitives in the buffer that have indices to vertices must also have those vertices in the same buffer.

The D3DEXECUTEBUFFERDESC structure describes the execute buffer to be created. At a minimum, the application must specify the size required. If the application specifies D3DDEBCAPS_VIDEOMEMORY in the dwCaps member, Direct3D will attempt to keep the execute buffer in video memory.

The application can use the IDirect3DExecuteBuffer::Lock method to request that the memory be moved. When this method returns, it will adjust the contents of the D3DEXECUTEBUFFERDESC structure to indicate whether the data resides in system or video memory.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.


IDirect3DDevice::CreateMatrix

The IDirect3DDevice::CreateMatrix method creates a matrix.

HRESULT CreateMatrix(
  LPD3DMATRIXHANDLE lpD3DMatHandle
);

Parameters

lpD3DMatHandle
Address of a variable that will contain a handle to the matrix that is created. The call will fail if a buffer of at least the size of the matrix cannot be created.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value is an error, such as DDERR_INVALIDPARAMS.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.

See Also

IDirect3DDevice::DeleteMatrix, IDirect3DDevice::SetMatrix


IDirect3DDevice::DeleteMatrix

The IDirect3DDevice::DeleteMatrix method deletes a matrix handle. This matrix handle must have been created by using the IDirect3DDevice::CreateMatrix method.

HRESULT DeleteMatrix(
  D3DMATRIXHANDLE d3dMatHandle
);

Parameters

d3dMatHandle
Matrix handle to be deleted.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value is an error, such as DDERR_INVALIDPARAMS.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.

See Also

IDirect3DDevice::CreateMatrix, IDirect3DDevice::SetMatrix


IDirect3DDevice::DeleteViewport

The IDirect3DDevice::DeleteViewport method removes the specified viewport from the list of viewport objects associated with the device and decrements the reference count of the viewport.

HRESULT DeleteViewport(
  LPDIRECT3DVIEWPORT lpDirect3DViewport
);

Parameters

lpDirect3DViewport
Address of the IDirect3DViewport interface of the viewport object that will be disassociated with this device object.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value may be one of the following values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS

Remarks

This method fails, returning DDERR_INVALIDPARAMS, if you attempt to delete a viewport from the device without previously assigning the viewport with a call to IDirect3DDevice::AddViewport.

In the IDirect3DDevice3 interface, this method accepts a pointer to an IDirect3DViewport3 interface.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.

See Also

IDirect3DDevice::AddViewport


IDirect3DDevice::EndScene

The IDirect3DDevice::EndScene method ends a scene that was begun by calling the IDirect3DDevice::BeginScene method.

HRESULT EndScene();

Parameters

None.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value is an error.

Remarks

When this method succeeds, the scene will have been rendered and the device surface will hold the contents of the rendering.

Do not attempt to use GDI functions that use the device context of a render-target surface between calls to BeginScene and EndScene. Attempts to do so can prevent the results of the GDI operations from being visible. If your application uses GDI functions, make sure that all GDI calls are made outside of the scene functions.

You must call this method before you can call the IDirect3DDevice::BeginScene method to start rendering another scene, even if the previous attempt to render was unsuccessful.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.

See Also

IDirect3DDevice::BeginScene, Beginning and Ending a Scene


IDirect3DDevice::EnumTextureFormats

The IDirect3DDevice::EnumTextureFormats method queries the current driver for a list of supported texture formats.

HRESULT EnumTextureFormats(
  LPD3DENUMTEXTUREFORMATSCALLBACK lpd3dEnumTextureProc,
  LPVOID lpArg
);

Parameters

lpd3dEnumTextureProc
Address of the D3DEnumTextureFormatsCallback function that the enumeration procedure will call for each texture format.
lpArg
Address of application-defined data passed to the callback function.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value may be one of the following values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.


IDirect3DDevice::Execute

The IDirect3DDevice::Execute method executes a buffer.

HRESULT Execute(
  LPDIRECT3DEXECUTEBUFFER lpDirect3DExecuteBuffer,
  LPDIRECT3DVIEWPORT lpDirect3DViewport,
  DWORD dwFlags
);

Parameters

lpDirect3DExecuteBuffer
Address of the execute buffer to be executed.
lpDirect3DViewport
Address of the Direct3DViewport object that describes the transformation context into which the execute buffer will be rendered.
dwFlags
Flags specifying whether or not objects in the buffer should be clipped. This parameter must be one of the following values:
D3DEXECUTE_CLIPPED
Clip any primitives in the buffer that are outside or partially outside the viewport.
D3DEXECUTE_UNCLIPPED
All primitives in the buffer are contained within the viewport.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value may be one of the following values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.

See Also

D3DEXECUTEDATA, D3DINSTRUCTION, IDirect3DExecuteBuffer::Validate


IDirect3DDevice::GetCaps

The IDirect3DDevice::GetCaps method retrieves the capabilities of the Direct3D device.

HRESULT GetCaps(
  LPD3DDEVICEDESC lpD3DHWDevDesc,
  LPD3DDEVICEDESC lpD3DHELDevDesc
);

Parameters

lpD3DHWDevDesc
Address of the D3DDEVICEDESC structure that will contain the hardware features of the device.
lpD3DHELDevDesc
Address of the D3DDEVICEDESC structure that will contain the software emulation being provided.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value may be one of the following values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS

Remarks

This method does not retrieve the capabilities of the display device. To retrieve this information, use the IDirectDraw4::GetCaps method.

This method's implementation is unchanged in the IDirect3DDevice3 interface.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.


IDirect3DDevice::GetDirect3D

The IDirect3DDevice::GetDirect3D method retrieves the Direct3D object for this device.

HRESULT GetDirect3D(
  LPDIRECT3D *lplpD3D
);

Parameters

lplpD3D
Address that will contain a pointer to the Direct3D object's IDirect3D interface when the method returns.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value is an error. For a list of possible return codes, see Direct3D Immediate Mode Return Values.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.


IDirect3DDevice::GetMatrix

The IDirect3DDevice::GetMatrix method retrieves a matrix from a matrix handle. This matrix handle must have been created by using the IDirect3DDevice::CreateMatrix method.

HRESULT GetMatrix(
  D3DMATRIXHANDLE D3DMatHandle,
  LPD3DMATRIX lpD3DMatrix
);

Parameters

D3DMatHandle
Handle to the matrix to be retrieved.
lpD3DMatrix
Address of a D3DMATRIX structure that contains the matrix when the method returns.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value is an error, such as DDERR_INVALIDPARAMS.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.

See Also

IDirect3DDevice::CreateMatrix, IDirect3DDevice::DeleteMatrix, IDirect3DDevice::SetMatrix


IDirect3DDevice::GetPickRecords

The IDirect3DDevice::GetPickRecords method retrieves the pick records for a device.

HRESULT GetPickRecords(
  LPDWORD lpCount,
  LPD3DPICKRECORD lpD3DPickRec
);

Parameters

lpCount
Address of a variable that contains the number of D3DPICKRECORD structures to retrieve.
lpD3DPickRec
Address that will contain an array of D3DPICKRECORD structures when the method returns.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value is an error.

Remarks

An application typically calls this method twice. In the first call, the second parameter is set to NULL, and the first parameter retrieves a count of all relevant D3DPICKRECORD structures. The application then allocates sufficient memory for those structures and calls the method again, specifying the newly allocated memory for the second parameter.

This method returns an unsorted list of pick records. Your application is responsible for sorting the records, if needed.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.


IDirect3DDevice::GetStats

The IDirect3DDevice::GetStats method retrieves statistics about a device.

HRESULT GetStats(
  LPD3DSTATS lpD3DStats
);

Parameters

lpD3DStats
Address of a D3DSTATS structure that will be filled with the statistics.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value may be one of the following values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS

Remarks

This method can report inaccurately low statistics when used with DirectX 6.0 and later drivers. (The also applies to this method in the legacy IDirect3DDevice2 interface.)

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.


IDirect3DDevice::Initialize

The IDirect3DDevice::Initialize method is not implemented.

HRESULT Initialize(
  LPDIRECT3D lpd3d,
  LPGUID lpGUID,
  LPD3DDEVICEDESC lpd3ddvdesc
);

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.


IDirect3DDevice::NextViewport

The IDirect3DDevice::NextViewport method enumerates the viewports associated with the device.

HRESULT NextViewport(
  LPDIRECT3DVIEWPORT  lpDirect3DViewport,
  LPDIRECT3DVIEWPORT* lplpAnotherViewport,
  DWORD dwFlags
);

Parameters

lpDirect3DViewport
Address of the IDirect3DViewport interface of a viewport in the list of viewports associated with this Direct3D device.
lplpAnotherViewport
Address that will contain a pointer to the IDirect3DViewport interface for another viewport in the device's viewport list. Which viewport the method retrieves is determined by the flag in the dwFlags parameter.
dwFlags
Flag specifying which viewport to retrieve from the list of viewports. This must be set to one of the following flags:
D3DNEXT_HEAD
Retrieve the item at the beginning of the list.
D3DNEXT_NEXT
Retrieve the next item in the list.
D3DNEXT_TAIL
Retrieve the item at the end of the list.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value may be one of the following values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS

Remarks

If you attempt to retrieve the next viewport in the list when you are at the end of the list, this method returns D3D_OK but lplpAnotherViewport is NULL.

In the IDirect3DDevice3 interface, this method requires pointers to IDirect3DViewport3 interfaces.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.


IDirect3DDevice::Pick

The IDirect3DDevice::Pick method executes a buffer without performing any rendering, but returns a z-ordered list of offsets to the primitives that intersect the upper-left corner of the rectangle specified by lpRect.

This call fails if the Direct3DExecuteBuffer object is locked.

HRESULT Pick(
  LPDIRECT3DEXECUTEBUFFER lpDirect3DExecuteBuffer,
  LPDIRECT3DVIEWPORT lpDirect3DViewport,
  DWORD dwFlags,
  LPD3DRECT lpRect
);

Parameters

lpDirect3DExecuteBuffer
Address of an execute buffer from which the z-ordered list is retrieved.
lpDirect3DViewport
Address of a viewport in the list of viewports associated with this Direct3DDevice object.
dwFlags
No flags are currently defined for this method.
lpRect
Address of a D3DRECT structure specifying the device coordinates to be picked. Currently, only primitives that intersect the x1, y1 coordinates of this rectangle are returned. The x2, y2 coordinates are ignored.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value may be one of the following values:

D3DERR_EXECUTE_LOCKED
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS

Remarks

The coordinates are specified in device-pixel space.

All Direct3DExecuteBuffer objects must be attached to a Direct3DDevice object in order for this method to succeed.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.

See Also

IDirect3DDevice::GetPickRecords


IDirect3DDevice::SetMatrix

The IDirect3DDevice::SetMatrix method applies a matrix to a matrix handle. This matrix handle must have been created by using the IDirect3DDevice::CreateMatrix method.

HRESULT SetMatrix(
  D3DMATRIXHANDLE d3dMatHandle,
  LPD3DMATRIX lpD3DMatrix
);

Parameters

d3dMatHandle
Matrix handle to be set.
lpD3DMatrix
Address of a D3DMATRIX structure that describes the matrix to be set.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value is an error, such as DDERR_INVALIDPARAMS.

Remarks

Transformations inside the execute buffer include a handle to a matrix. The IDirect3DDevice::SetMatrix method enables an application to change this matrix without having to lock and unlock the execute buffer.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.

See Also

IDirect3DDevice::CreateMatrix, IDirect3DDevice::GetMatrix, IDirect3DDevice::DeleteMatrix


IDirect3DDevice::SwapTextureHandles

The IDirect3DDevice::SwapTextureHandles method swaps two texture handles.

HRESULT SwapTextureHandles(
  LPDIRECT3DTEXTURE lpD3DTex1,
  LPDIRECT3DTEXTURE lpD3DTex2
);

Parameters

lpD3DTex1 and lpD3DTex2
Addresses of the IDirect3DTexture interfaces for the textures whose handles will be swapped.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value is an error.

Remarks

This method is useful when an application is changing all the textures in a complicated object.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.


IDirect3DDevice3

The IDirect3DDevice3 interface provides methods enabling applications to perform DrawPrimitive-based rendering; this is in contrast to the IDirect3DDevice interface, which applications use to work with execute buffers. You can create a Direct3DDevice object and retrieve a pointer to this interface by calling the IDirect3D3::CreateDevice method.

For a conceptual overview, see Direct3D Devices and The DrawPrimitive Methods.

The methods of the IDirect3DDevice3 interface can be organized into the following groups:

Information | GetCaps
 | GetDirect3D
 | GetStats
Miscellaneous | ComputeSphereVisibility
 | MultiplyTransform
Getting and Setting States | GetClipStatus
 | GetCurrentViewport
 | GetLightState
 | GetRenderState
 | GetRenderTarget
 | GetTransform
 | SetClipStatus
 | SetCurrentViewport
 | SetLightState
 | SetRenderState
 | SetRenderTarget
 | SetTransform
Rendering | Begin
 | BeginIndexed
 | DrawIndexedPrimitive
 | DrawIndexedPrimitiveStrided
 | DrawIndexedPrimitiveVB
 | DrawPrimitive
 | DrawPrimitiveStrided
 | DrawPrimitiveVB
 | End
 | Index
 | Vertex
Scenes | BeginScene
 | EndScene
Textures | EnumTextureFormats
 | GetTexture
 | GetTextureStageState
 | SetTexture
 | SetTextureStageState
 | ValidateDevice
Viewports | AddViewport
 | DeleteViewport
 | NextViewport

The IDirect3DDevice3 interface, like all COM interfaces, inherits the IUnknown interface methods. The IUnknown interface supports the following three methods:

IUnknown | AddRef
 | QueryInterface
 | Release

This interface extends the IDirect3DDevice2 interface by adding methods to support more flexible vertex formats, vertex buffers, and visibility computation. Note that all of the viewport-related methods in this interface accept slightly different parameters than their counterparts in the IDirect3DDevice2 interface. Wherever an IDirect3DDevice2 interface method might accept an IDirect3DViewport2 interface pointer as a parameter, the methods in the IDirect3DDevice3 interface accept an IDirect3DViewport3 interface pointer instead.

This interface is not intended to be used with execute buffers, and therefore does not contain any execute-buffer related methods. If you need to use some of the methods in the IDirect3DDevice interface that are not supported in IDirect3DDevice2 or IDirect3DDevice3, you can call IDirect3DDevice2::QueryInterface to retrieve a pointer to an IDirect3DDevice interface.

You can use the LPDIRECT3DDEVICE2 or LPDIRECT3DDEVICE3 data types to declare a variable that contains a pointer to an IDirect3DDevice2 or IDirect3DDevice3 interface. The D3d.h header file declares these data types with the following code:

typedef struct IDirect3DDevice2    *LPDIRECT3DDEVICE2;
typedef struct IDirect3DDevice3    *LPDIRECT3DDEVICE3;

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.

See Also

Direct3D Devices, Rendering


IDirect3DDevice3::AddViewport

The IDirect3DDevice3::AddViewport method adds the specified viewport to the list of viewport objects associated with the device and increments the reference count of the viewport.

HRESULT AddViewport(
  LPDIRECT3DVIEWPORT3 lpDirect3DViewport
);

Parameters

lpDirect3DViewport
Address of the IDirect3DViewport3 interface that should be associated with this Direct3DDevice object.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value may be one of the following values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS

Remarks

This method will fail, returning DDERR_INVALIDPARAMS, if you attempt to add a viewport that has already been assigned to the device.

In the IDirect3DDevice2 interface, this method accepts a pointer to an IDirect3DViewport interface, not an IDirect3DViewport3 interface.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.


IDirect3DDevice3::Begin

The IDirect3DDevice3::Begin method indicates the start of a sequence of rendered primitives. This method defines the type of these primitives and the type of vertices on which they are based. The only method you can legally call between calls to IDirect3DDevice3::Begin and IDirect3DDevice3::End is IDirect3DDevice3::Vertex.

HRESULT Begin(
  D3DPRIMITIVETYPE d3dpt,
  DWORD dwVertexTypeDesc,
  DWORD dwFlags
);

Parameters

d3dpt
One of the members of the D3DPRIMITIVETYPE enumerated type.
dwVertexTypeDesc
A combination of flexible vertex format flags that describe the vertex format used. Only vertices that match this description will be accepted before the corresponding IDirect3DDevice3::End.
dwFlags
One or more of the following flags defining how the primitive is drawn:
D3DDP_DONOTCLIP
The application has already done the required clipping, so the system should not necessarily clip the primitives. (This flag is a hint; the system may clip the primitive even when this flag is specified, under some circumstances.)
D3DDP_DONOTLIGHT
Disables the Direct3D lighting engine. The system uses the diffuse and specular components at each vertex for shading when it rasterizes the set of primitives. If a diffuse or specular component is not specified, the system uses the default color for the missing component (0xFFFFFFFF for diffuse and 0x00000000 for specular ).
D3DDP_DONOTUPDATEEXTENTS
Disables the updating of the screen rectangle affected by this rendering call. Using this flag can potentially help performance, but the extents returned by IDirect3DDevice3::GetClipStatus will not have been updated to account for the data rendered by this call.
D3DDP_WAIT
Causes the method to wait until the polygons have been rendered before it returns, instead of returning as soon as the polygons have been sent to the card. (On scene-capture cards, the method returns as soon as the card responds.) This flag is typically used for debugging. Applications should not attempt to use this flag to ensure that a scene is up-to-date before continuing.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value is an error. The method returns DDERR_INVALIDPARAMS if one of the arguments is invalid.

Remarks

This method differs from its counterpart in the IDirect3DDevice2 interface in that it accepts a flexible vertex format descriptor rather than a member of the D3DVERTEXTYPE enumerated type as the second parameter. If you attempt to use one of the members of D3DVERTEXTYPE, the method fails, returning DDERR_INVALIDPARAMS. For more information, see Vertex Formats.

This method fails if it is called after a call to the IDirect3DDevice3::Begin or IDirect3DDevice3::BeginIndexed method that has no bracketing call to IDirect3DDevice3::End method. Rendering calls that specify the wrong vertex type or that perform state changes will cause rendering of this primitive to fail.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.

See Also

IDirect3DDevice3::BeginIndexed, IDirect3DDevice3::End, IDirect3DDevice3::Vertex


IDirect3DDevice3::BeginIndexed

The IDirect3DDevice3::BeginIndexed method defines the start of a primitive based on indexing into an array of vertices. This method fails if it is called after a call to the IDirect3DDevice3::Begin or IDirect3DDevice3::BeginIndexed method that has no corresponding call to IDirect3DDevice3::End. The only method you can legally call between calls to IDirect3DDevice3::BeginIndexed and IDirect3DDevice3::End is IDirect3DDevice3::Index.

HRESULT BeginIndexed(
  D3DPRIMITIVETYPE dptPrimitiveType,
  DWORD  dwVertexTypeDesc,
  LPVOID lpvVertices,
  DWORD  dwNumVertices,
  DWORD  dwFlags
);

Parameters

dptPrimitiveType
Type of primitive to be rendered by this command. This must be one of the members of the D3DPRIMITIVETYPE enumerated type. Note that the D3DPT_POINTLIST member of D3DPRIMITIVETYPE is not indexed.
dwVertexTypeDesc
A combination of flexible vertex format flags that describes the vertex format being used. Only vertices that match this type will be accepted before the corresponding IDirect3DDevice3::End.
lpvVertices
Pointer to the list of vertices to be used in the primitive sequence.
dwNumVertices
Number of vertices in the array at lpvVertices.
dwFlags
One or more of the following flags defining how the primitive is drawn:
D3DDP_DONOTCLIP
The application has already done the required clipping, so the system should not necessarily clip the primitives. (This flag is a hint; the system may clip the primitive even when this flag is specified, under some circumstances.)
D3DDP_DONOTLIGHT
Disables the Direct3D lighting engine. The system uses the diffuse and specular components at each vertex for shading when it rasterizes the set of primitives. If a diffuse or specular component is not specified, the system uses the default color for the missing component (0xFFFFFFFF for diffuse and 0x00000000 for specular).
D3DDP_DONOTUPDATEEXTENTS
Disables the updating of the screen rectangle affected by this rendering call. Using this flag can potentially help performance, but the extents returned by IDirect3DDevice3::GetClipStatus will not have been updated to account for the data rendered by this call.
D3DDP_WAIT
Causes the method to wait until the polygons have been rendered before it returns, instead of returning as soon as the polygons have been sent to the card. (On scene-capture cards, the method returns as soon as the card responds.) This flag is typically used for debugging. Applications should not attempt to use this flag to ensure that a scene is up-to-date before continuing.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value may be one of the following values:

D3DERR_INVALIDRAMPTEXTURE | Ramp mode is being used and the texture handle in the current material does not match the current texture handle that is set as a render state.
DDERR_INVALIDPARAMS | One of the arguments is invalid.

Remarks

This method differs from its counterpart in the IDirect3DDevice2 interface in that it accepts a flexible vertex format descriptor rather than a member of the D3DVERTEXTYPE enumerated type as the second parameter. If you attempt to use one of the members of D3DVERTEXTYPE, the method fails, returning DDERR_INVALIDPARAMS. For more information, see Vertex Formats.

This method was first introduced in the IDirect3DDevice2 interface.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.

See Also

IDirect3DDevice3::Begin, IDirect3DDevice3::End, IDirect3DDevice3::Index


IDirect3DDevice3::BeginScene

The IDirect3DDevice3::BeginScene method begins a scene. Applications must call this method before performing any rendering, and must call IDirect3DDevice3::EndScene when rendering is complete, and before calling IDirect3DDevice::BeginScene again.

HRESULT BeginScene();

Parameters

None.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value is an error.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.

See Also

IDirect3DDevice3::EndScene


IDirect3DDevice3::ComputeSphereVisibility

The IDirect3DDevice3::ComputeSphereVisibility method calculates the visibility (complete, partial, or no visibility) of an array spheres within the current viewport for this device.

HRESULT ComputeSphereVisibility(
  LPD3DVECTOR lpCenters,
  LPD3DVALUE  lpRadii,
  DWORD       dwNumSpheres,
  DWORD       dwFlags,
  LPDWORD     lpdwReturnValues
);

Parameters

lpCenters
Array of D3DVECTOR structures describing the center point for each sphere, in world-space coordinates.
lpRadii
Array of D3DVALUE variables that represent the radius for each sphere.
dwNumSpheres
Number of spheres. This value must be greater than zero.
dwFlags
Not currently used; set to zero.
lpdwReturnValues
Array of DWORD values. The array need not be initialized, but it must be large enough to contain a DWORD for each sphere being tested. When the method returns, each element in the array contains a combination of the following flags that describe the visibility of that sphere within the current viewport for this device:
Inside flags
D3DVIS_INSIDE_BOTTOM, D3DVIS_INSIDE_FAR, D3DVIS_INSIDE_FRUSTUM, D3DVIS_INSIDE_LEFT
D3DVIS_INSIDE_NEAR, D3DVIS_INSIDE_RIGHT, D3DVIS_INSIDE_TOP
The sphere is inside the viewing frustum of the current viewport.
Intersection flags
D3DVIS_INTERSECT_BOTTOM or D3DVIS_INTERSECT_TOP
The sphere intersects the bottom or top plane of the viewing frustum for the current viewport, depending on which flag is present.
D3DVIS_INTERSECT_FAR or D3DVIS_INTERSECT_NEAR
The sphere intersects the far or near plane of the viewing frustum for the current viewport, depending on which flag is present.
D3DVIS_INTERSECT_FRUSTUM
The sphere intersects some part of the viewing frustum for the current viewport.
D3DVIS_INTERSECT_LEFT or D3DVIS_INTERSECT_RIGHT
The sphere intersects the left or right plane of the viewing frustum for the current viewport, depending on which flag is present.
Outside flags
D3DVIS_OUTSIDE_BOTTOM or D3DVIS_OUTSIDE_TOP
The sphere is outside the bottom or top plane of the viewing frustum for the current viewport, depending on which flag is present.
D3DVIS_OUTSIDE_FAR or D3DVIS_OUTSIDE_NEAR
The sphere is outside the far or near plane of the viewing frustum for the current viewport, depending on which flag is present.
D3DVIS_OUTSIDE_FRUSTUM
The sphere is somewhere outside the viewing frustum for the current viewport.
D3DVIS_OUTSIDE_LEFT or D3DVIS_OUTSIDE_RIGHT
The sphere is outside the left or right plane of the viewing frustum for the current viewport, depending on which flag is present.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value may be one of the following values:

D3DERR_INVALIDMATRIX
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS

Remarks

Sphere visibility is computed by back transforming the viewing frustum to the model space, using the inverse of the combined world, view or projection matrices. If the combined matrix can not be inverted (if the determinant is zero), the method fails, returning D3DERR_INVALIDMATRIX.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.


IDirect3DDevice3::DeleteViewport

The IDirect3DDevice3::DeleteViewport method removes the specified viewport from the list of viewport objects associated with the device and decrements the reference count of the viewport.

HRESULT DeleteViewport(
  LPDIRECT3DVIEWPORT3 lpDirect3DViewport
);

Parameters

lpDirect3DViewport
Address of the IDirect3DViewport3 interface of the viewport object that will be disassociated with this device.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value may be one of the following values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS

Remarks

This method fails, returning DDERR_INVALIDPARAMS, if you attempt to delete a viewport from the device without previously assigning the viewport with a call to IDirect3DDevice3::AddViewport.

In the IDirect3DDevice2 interface, this method accepts a pointer to an IDirect3DViewport interface, not an IDirect3DViewport3 interface.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.

See Also

IDirect3DDevice3::AddViewport


IDirect3DDevice3::DrawIndexedPrimitive

The IDirect3DDevice3::DrawIndexedPrimitive method renders the specified geometric primitive based on indexing into an array of vertices.

HRESULT DrawIndexedPrimitive(
  D3DPRIMITIVETYPE d3dptPrimitiveType,
  DWORD  dwVertexTypeDesc,
  LPVOID lpvVertices,
  DWORD  dwVertexCount,
  LPWORD lpwIndices,
  DWORD  dwIndexCount,
  DWORD  dwFlags
);

Parameters

d3dptPrimitiveType
Type of primitive to be rendered by this command. This must be one of the members of the D3DPRIMITIVETYPE enumerated type.

Note that the D3DPT_POINTLIST member of D3DPRIMITIVETYPE is not indexed.

dwVertexTypeDesc
A combination of flexible vertex format flags that describes the vertex format for this set of primitives.
lpvVertices
Pointer to the list of vertices to be used in the primitive sequence.
dwVertexCount
Defines the number of vertices in the list.

Notice that this parameter is used differently from the dwVertexCount parameter in the IDirect3DDevice3::DrawPrimitive method. In that method, the dwVertexCount parameter gives the number of vertices to draw, but here it gives the total number of vertices in the array pointed to by the lpvVertices parameter. When you call IDirect3DDevice3::DrawIndexedPrimitive, you specify the number of vertices to draw in the dwIndexCount parameter.

lpwIndices
Pointer to a list of WORDs that are to be used to index into the specified vertex list when creating the geometry to render.
dwIndexCount
Specifies the number of indices provided for creating the geometry. The maximum number of indices allowed is 65,535 (0xFFFF).
dwFlags
One or more of the following flags defining how the primitive is drawn:
D3DDP_DONOTCLIP
The application has already done the required clipping, so the system should not necessarily clip the primitives. (This flag is a hint; the system may clip the primitive even when this flag is specified, under some circumstances.)
D3DDP_DONOTLIGHT
Disables the Direct3D lighting engine. The system uses the diffuse and specular components at each vertex for shading when it rasterizes the set of primitives. If a diffuse or specular component is not specified, the system uses the default color for the missing component (0xFFFFFFFF for diffuse and 0x00000000 for specular).
D3DDP_DONOTUPDATEEXTENTS
Disables the updating of the screen rectangle affected by this rendering call. Using this flag can potentially help performance, but the extents returned by IDirect3DDevice3::GetClipStatus will not have been updated to account for the data rendered by this call.
D3DDP_WAIT
Causes the method to wait until the polygons have been rendered before it returns, instead of returning as soon as the polygons have been sent to the card. (On scene-capture cards, the method returns as soon as the card responds.) This flag is typically used for debugging. Applications should not attempt to use this flag to ensure that a scene is up-to-date before continuing.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value may be one of the following values:

D3DERR_INVALIDRAMPTEXTURE
D3DERR_INVALIDPRIMITIVETYPE
D3DERR_INVALIDVERTEXTYPE
DDERR_INVALIDPARAMS
DDERR_WASSTILLDRAWING

Remarks

Do not use this method to render very small subsets of vertices from extremely large vertex arrays. This method transforms every vertex in the provided buffer, regardless of the location or quantity of vertices being rendered. Thus, if you pass an array that contains thousands of vertices, but only intend to render hundreds, your application's performance will suffer dramatically. In cases where you need to render a small number of vertices from a large buffer, use the Direct3D vertex buffer rendering methods. For more information, see Vertex Buffers.

This method differs from its counterpart in the IDirect3DDevice2 interface in that it accepts a flexible vertex format descriptor rather than a member of the D3DVERTEXTYPE enumerated type as the second parameter. If you attempt to use one of the members of D3DVERTEXTYPE, the method fails, returning DDERR_INVALIDPARAMS. For more information, see Vertex Formats.

In current versions of DirectX, IDirect3DDevice3::DrawIndexedPrimitive can sometimes generate an update rectangle that is larger than it strictly needs to be. If a large number of vertices need to be processed, this can have a negative impact on the performance of your application. If you are using D3DTLVERTEX vertices and the system is processing more vertices than you need, you should use the D3DDP_DONOTCLIP and D3DDP_DONOTUPDATEEXTENTS flags to solve the problem.

This method was introduced with the IDirect3DDevice2 interface.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.

See Also

IDirect3DDevice3::DrawPrimitive, IDirect3DDevice3::DrawPrimitiveStrided, IDirect3DDevice3::DrawPrimitiveVB, IDirect3DDevice3::DrawIndexedPrimitiveStrided, IDirect3DDevice3::DrawIndexedPrimitiveVB


IDirect3DDevice3::DrawIndexedPrimitiveStrided

The IDirect3DDevice3::DrawIndexedPrimitiveStrided method renders a geometric primitive based on indexing into an array of strided vertices. For more information, see Strided Vertex Format.

HRESULT DrawIndexedPrimitiveStrided(
  D3DPRIMITIVETYPE d3dptPrimitiveType,
  DWORD  dwVertexTypeDesc,
  LPD3DDRAWPRIMITIVESTRIDEDDATA lpVertexArray,
  DWORD  dwVertexCount,
  LPWORD lpwIndices,
  DWORD  dwIndexCount,
  DWORD  dwFlags
);

Parameters

d3dptPrimitiveType
Type of primitive to be rendered by this command. This must be one of the members of the D3DPRIMITIVETYPE enumerated type.

Note that the D3DPT_POINTLIST member of D3DPRIMITIVETYPE is not indexed.

dwVertexTypeDesc
A combination of flexible vertex format flags vertex format for this primitive.
lpVertexArray
Array of D3DDRAWPRIMITIVESTRIDEDDATA structures that contains the vertices for this primitive, in the format specified by the flags in dwVertexTypeDesc.
dwVertexCount
Defines the number of vertices in the list.

Notice that this parameter is used differently from the dwVertexCount parameter in the IDirect3DDevice3::DrawPrimitive method. In that method, the dwVertexCount parameter gives the number of vertices to draw, but here it gives the total number of vertices in the array pointed to by the lpVertexArray parameter. When you call IDirect3DDevice3::DrawIndexedPrimitiveStrided, you specify the number of vertices to draw in the dwIndexCount parameter.

lpwIndices
Pointer to a list of WORDs that are to be used to index into the specified vertex list when creating the geometry to render.
dwIndexCount
Specifies the number of indices provided for creating the geometry. The maximum number of indices allowed is 65,535 (0xFFFF).
dwFlags
One or more of the following flags defining how the primitive is drawn:
D3DDP_DONOTCLIP
The application has already done the required clipping, so the system should not necessarily clip the primitives. (This flag is a hint; the system may clip the primitive even when this flag is specified, under some circumstances.)
D3DDP_DONOTLIGHT
Disables the Direct3D lighting engine. The system uses the diffuse and specular components at each vertex for shading when it rasterizes the set of primitives. If a diffuse or specular component is not specified, the system uses the default color for the missing component (0xFFFFFFFF for diffuse and 0x00000000 for specular).
D3DDP_DONOTUPDATEEXTENTS
Disables the updating of the screen rectangle affected by this rendering call. Using this flag can potentially help performance, but the extents returned by IDirect3DDevice3::GetClipStatus will not have been updated to account for the data rendered by this call.
D3DDP_WAIT
Causes the method to wait until the polygons have been rendered before it returns, instead of returning as soon as the polygons have been sent to the card. (On scene-capture cards, the method returns as soon as the card responds.) This flag is typically used for debugging. Applications should not attempt to use this flag to ensure that a scene is up-to-date before continuing.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value may be one of the following values:

D3DERR_INVALIDRAMPTEXTURE
D3DERR_INVALIDPRIMITIVETYPE
D3DERR_INVALIDVERTEXTYPE
DDERR_INVALIDPARAMS
DDERR_WASSTILLDRAWING

Remarks

This method does not support transformed vertices. As a result, if you include the D3DFVF_XYZRHW vertex format descriptor in the dwVertexTypeDesc parameter, the method fails, returning D3DERR_INVALIDVERTEXTYPE.

This method was introduced with the IDirect3DDevice3 interface.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.

See Also

IDirect3DDevice3::DrawPrimitive, IDirect3DDevice3::DrawPrimitiveStrided, IDirect3DDevice3::DrawPrimitiveVB, IDirect3DDevice3::DrawIndexedPrimitive, IDirect3DDevice3::DrawIndexedPrimitiveVB, Strided Vertex Format


IDirect3DDevice3::DrawIndexedPrimitiveVB

The IDirect3DDevice3::DrawIndexedPrimitiveVB method renders a geometric primitive based on indexing into an array of vertices within a vertex buffer.

HRESULT DrawIndexedPrimitiveVB(
  D3DPRIMITIVETYPE d3dptPrimitiveType,
  LPDIRECT3DVERTEXBUFFER lpd3dVertexBuffer,
  LPWORD lpwIndices,
  DWORD  dwIndexCount,
  DWORD  dwFlags
);

Parameters

d3dptPrimitiveType
Type of primitive to be rendered by this command. This must be one of the members of the D3DPRIMITIVETYPE enumerated type.

Note that the D3DPT_POINTLIST member of D3DPRIMITIVETYPE is not indexed.

lpd3dVertexBuffer
Address of the IDirect3DVertexBuffer interface for the vertex buffer that contains the array of vertices. Vertices can be transformed or untransformed, optimized or unoptimized.
lpwIndices
Address of an array of WORDs that will be used to index into the vertices in the vertex buffer.
dwIndexCount
The number of indices in the array at lpwIndices. The maximum number of indices allowed is 65,535 (0xFFFF).
dwFlags
One or more of the following flags defining how the primitive is drawn:
D3DDP_DONOTCLIP
The application has already done the required clipping, so the system should not necessarily clip the primitives. (This flag is a hint; the system may clip the primitive even when this flag is specified, under some circumstances.)
D3DDP_DONOTLIGHT
Disables the Direct3D lighting engine. The system uses the diffuse and specular components at each vertex for shading when it rasterizes the set of primitives. If a diffuse or specular component is not specified, the system uses the default color for the missing component (0xFFFFFFFF for diffuse and 0x00000000 for specular).
D3DDP_DONOTUPDATEEXTENTS
Disables the updating of the screen rectangle affected by this rendering call. Using this flag can potentially help performance, but the extents returned by IDirect3DDevice3::GetClipStatus will not have been updated to account for the data rendered by this call.
D3DDP_WAIT
Causes the method to wait until the polygons have been rendered before it returns, instead of returning as soon as the polygons have been sent to the card. (On scene-capture cards, the method returns as soon as the card responds.) This flag is typically used for debugging. Applications should not attempt to use this flag to ensure that a scene is up-to-date before continuing.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following values:

D3DERR_INVALIDPRIMITIVETYPE
D3DERR_INVALIDVERTEXTYPE
D3DERR_VERTEXBUFFERLOCKED
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_WASSTILLDRAWING

Remarks

Software devices—MMX and RGB devices—cannot render from a video memory (local or non-local) vertex buffer. To render a vertex buffer using a software device, the vertex buffer must exist in system memory. Hardware devices can render from system memory or video memory vertex buffers.

You cannot render from a locked vertex buffer; calls to the IDirect3DDevice3::DrawIndexedPrimitiveVB or IDirect3DDevice3::DrawPrimitiveVB method using a locked buffer will fail, returning D3DERR_VERTEXBUFFERLOCKED.

This method was introduced with the IDirect3DDevice3 interface.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.

See Also

IDirect3DDevice3::DrawPrimitive, IDirect3DDevice3::DrawPrimitiveStrided, IDirect3DDevice3::DrawPrimitiveVB, IDirect3DDevice3::DrawIndexedPrimitive, IDirect3DDevice3::DrawIndexedPrimitiveStrided


IDirect3DDevice3::DrawPrimitive

The IDirect3DDevice3::DrawPrimitive method renders the specified array of vertices as a sequence of geometric primitives of the specified type.

HRESULT DrawPrimitive(
  D3DPRIMITIVETYPE dptPrimitiveType,
  DWORD  dwVertexTypeDesc,
  LPVOID lpvVertices,
  DWORD  dwVertexCount,
  DWORD  dwFlags
);

Parameters

dptPrimitiveType
Type of primitive to be rendered by this command. This must be one of the members of the D3DPRIMITIVETYPE enumerated type.
dwVertexTypeDesc
A combination of flexible vertex format flags that describe the vertex format used for this set of primitives.
lpvVertices
Pointer to the array of vertices to be used in the primitive sequence.
dwVertexCount
The number of vertices in the array. The maximum number of vertices allowed is 65,535 (0xFFFF).
dwFlags
One or more of the following flags defining how the primitive is drawn:
D3DDP_DONOTCLIP
The application has already done the required clipping, so the system should not necessarily clip the primitives. (This flag is a hint; the system may clip the primitive even when this flag is specified, under some circumstances.)
D3DDP_DONOTLIGHT
Disables the Direct3D lighting engine. The system uses the diffuse and specular components at each vertex for shading when it rasterizes the set of primitives. If a diffuse or specular component is not specified, the system uses the default color for the missing component (0xFFFFFFFF for diffuse and 0x00000000 for specular).
D3DDP_DONOTUPDATEEXTENTS
Disables the updating of the screen rectangle affected by this rendering call. Using this flag can potentially help performance, but the extents returned by IDirect3DDevice3::GetClipStatus will not have been updated to account for the data rendered by this call.
D3DDP_WAIT
Causes the method to wait until the polygons have been rendered before it returns, instead of returning as soon as the polygons have been sent to the card. (On scene-capture cards, the method returns as soon as the card responds.) This flag is typically used for debugging. Applications should not attempt to use this flag to ensure that a scene is up-to-date before continuing.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following values:

D3DERR_INVALIDRAMPTEXTURE
D3DERR_INVALIDPRIMITIVETYPE
D3DERR_INVALIDVERTEXTYPE
DDERR_INVALIDPARAMS
DDERR_WASSTILLDRAWING

Remarks

This method differs from its counterpart in the IDirect3DDevice2 interface in that it accepts a flexible vertex format descriptor rather than a member of the D3DVERTEXTYPE enumerated type as the second parameter. If you attempt to use one of the members of D3DVERTEXTYPE, the method fails, returning DDERR_INVALIDPARAMS. For more information, see Vertex Formats.

This method was introduced with the IDirect3DDevice2 interface.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.

See Also

IDirect3DDevice3::DrawPrimitiveStrided, IDirect3DDevice3::DrawPrimitiveVB, IDirect3DDevice3::DrawIndexedPrimitive, IDirect3DDevice3::DrawIndexedPrimitiveStrided, IDirect3DDevice3::DrawIndexedPrimitiveVB


IDirect3DDevice3::DrawPrimitiveStrided

The IDirect3DDevice3::DrawPrimitiveStrided method renders the specified array of strided vertices as a sequence of geometric primitives. For more information, see Strided Vertex Format.

HRESULT DrawPrimitiveStrided(
  D3DPRIMITIVETYPE dptPrimitiveType,
  DWORD  dwVertexTypeDesc,
  LPD3DDRAWPRIMITIVESTRIDEDDATA lpVertexArray,
  DWORD  dwVertexCount,
  DWORD  dwFlags
);

Parameters

dptPrimitiveType
Type of primitive to be rendered by this command. This must be one of the members of the D3DPRIMITIVETYPE enumerated type.
dwVertexTypeDesc
A combination of flexible vertex format flags that describe the vertex format.
lpVertexArray
Array of D3DDRAWPRIMITIVESTRIDEDDATA structures that contains the vertices for this primitive.
dwVertexCount
Number of vertices in the array at lpVertexArray. The maximum number of vertices allowed is 65,535 (0xFFFF).
dwFlags
One or more of the following flags defining how the primitive is drawn:
D3DDP_DONOTCLIP
The application has already done the required clipping, so the system should not necessarily clip the primitives. (This flag is a hint; the system may clip the primitive even when this flag is specified, under some circumstances.)
D3DDP_DONOTLIGHT
Disables the Direct3D lighting engine. The system uses the diffuse and specular components at each vertex for shading when it rasterizes the set of primitives. If a diffuse or specular component is not specified, the system uses the default color for the missing component (0xFFFFFFFF for diffuse and 0x00000000 for specular).
D3DDP_DONOTUPDATEEXTENTS
Disables the updating of the screen rectangle affected by this rendering call. Using this flag can potentially help performance, but the extents returned by IDirect3DDevice3::GetClipStatus will not have been updated to account for the data rendered by this call.
D3DDP_WAIT
Causes the method to wait until the polygons have been rendered before it returns, instead of returning as soon as the polygons have been sent to the card. (On scene-capture cards, the method returns as soon as the card responds.) This flag is typically used for debugging. Applications should not attempt to use this flag to ensure that a scene is up-to-date before continuing.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following values:

D3DERR_INVALIDRAMPTEXTURE
D3DERR_INVALIDPRIMITIVETYPE
D3DERR_INVALIDVERTEXTYPE
DDERR_INVALIDPARAMS
DDERR_WASSTILLDRAWING

Remarks

This method does not support transformed vertices. As a result, if you include the D3DFVF_XYZRHW vertex format descriptor in the dwVertexTypeDesc parameter, the method fails, returning D3DERR_INVALIDVERTEXTYPE.

This method was introduced with the IDirect3DDevice3 interface.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.

See Also

IDirect3DDevice3::DrawPrimitive, IDirect3DDevice3::DrawPrimitiveVB, IDirect3DDevice3::DrawIndexedPrimitive, IDirect3DDevice3::DrawIndexedPrimitiveStrided, IDirect3DDevice3::DrawIndexedPrimitiveVB, Strided Vertex Format


IDirect3DDevice3::DrawPrimitiveVB

The IDirect3DDevice3::DrawPrimitiveVB method renders an array of vertices in a vertex buffer as a sequence of geometric primitives.

HRESULT DrawPrimitiveVB(
  D3DPRIMITIVETYPE d3dptPrimitiveType,
  LPDIRECT3DVERTEXBUFFER lpd3dVertexBuffer,
  DWORD dwStartVertex,
  DWORD dwNumVertices,
  DWORD dwFlags
);

Parameters

d3dptPrimitiveType
Type of primitive to be rendered by this command. This must be one of the members of the D3DPRIMITIVETYPE enumerated type.
lpd3dVertexBuffer
Address of the IDirect3DVertexBuffer interface for the vertex buffer that contains the array of vertices. Vertices can be transformed or untransformed, optimized or unoptimized.
dwStartVertex
Index value of the first vertex in the primitive. The highest possible starting index is 65,535 (0xFFFF). In debug builds, specifying a starting index value that exceeds this limit will cause the method to fail and return DDERR_INVALIDPARAMS.
dwNumVertices
Number of vertices to be rendered. The maximum number of vertices allowed is 65,535 (0xFFFF).
dwFlags
One or more of the following flags defining how the primitive is drawn:
D3DDP_DONOTCLIP
The application has already done the required clipping, so the system should not necessarily clip the primitives. (This flag is a hint; the system may clip the primitive even when this flag is specified, under some circumstances.)
D3DDP_DONOTLIGHT
Disables the Direct3D lighting engine. The system uses the diffuse and specular components at each vertex for shading when it rasterizes the set of primitives. If a diffuse or specular component is not specified, the system uses the default color for the missing component (0xFFFFFFFF for diffuse and 0x00000000 for specular).
D3DDP_DONOTUPDATEEXTENTS
Disables the updating of the screen rectangle affected by this rendering call. Using this flag can potentially help performance, but the extents returned by IDirect3DDevice3::GetClipStatus will not have been updated to account for the data rendered by this call.
D3DDP_WAIT
Causes the method to wait until the polygons have been rendered before it returns, instead of returning as soon as the polygons have been sent to the card. (On scene-capture cards, the method returns as soon as the card responds.) This flag is typically used for debugging. Applications should not attempt to use this flag to ensure that a scene is up-to-date before continuing.

Return Values

If the method succeeds, the return value is DD_OK.

If the method fails, the return value may be one of the following values:

D3DERR_INVALIDRAMPTEXTURE
D3DERR_INVALIDPRIMITIVETYPE
D3DERR_INVALIDVERTEXTYPE
D3DERR_VERTEXBUFFERLOCKED
DDERR_INVALIDPARAMS
DDERR_WASSTILLDRAWING

Remarks

Software devices—MMX and RGB devices—cannot render from a video memory (local or non-local) vertex buffer. To render a vertex buffer using a software device, the vertex buffer must exist in system memory. Hardware devices can render from system memory or video memory vertex buffers.

You cannot render from a locked vertex buffer; calls to the IDirect3DDevice3::DrawIndexedPrimitiveVB or IDirect3DDevice3::DrawPrimitiveVB method using a locked buffer will fail, returning D3DERR_VERTEXBUFFERLOCKED.

This method was introduced with the IDirect3DDevice3 interface.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.

See Also

IDirect3DDevice3::DrawPrimitive, IDirect3DDevice3::DrawPrimitiveStrided, IDirect3DDevice3::DrawIndexedPrimitive, IDirect3DDevice3::DrawIndexedPrimitiveStrided, IDirect3DDevice3::DrawIndexedPrimitiveVB


IDirect3DDevice3::End

The IDirect3DDevice3::End method signals the completion of a primitive sequence. This method fails if no corresponding call to the IDirect3DDevice3::Begin method (or IDirect3DDevice3::BeginIndexed) was made.

HRESULT End(
  DWORD dwFlags
);

Parameters

dwFlags
Reserved for future use; set to zero.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value may be one of the following values:

D3DERR_INVALIDRAMPTEXTURE | Ramp mode is being used and the texture handle in the current material does not match the current texture handle that is set as a render state.
DDERR_INVALIDPARAMS | One of the arguments is invalid.

Remarks

This method fails if the vertex count is incorrect for the primitive type. It fails without drawing if it is called before a sufficient number of vertices is specified. If the number of IDirect3DDevice3::Vertex or IDirect3DDevice3::Index calls made is not evenly divisible by 3 (in the case of triangles), or 2 (in the case of a line list), the remainder will be ignored.

This method was introduced with the IDirect3DDevice2 interface.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.

See Also

IDirect3DDevice3::Begin, IDirect3DDevice3::BeginIndexed


IDirect3DDevice3::EndScene

The IDirect3DDevice3::EndScene method ends a scene that was begun by calling the IDirect3DDevice3::BeginScene method.

HRESULT EndScene();

Parameters

None.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value is an error.

Remarks

When this method succeeds, the scene will have been rendered and the device surface will hold the contents of the rendering.

You must call this method before you can call the IDirect3DDevice3::BeginScene method to start rendering another scene, even if the previous attempt to render was unsuccessful.

This method is unchanged from its implementation in the IDirect3DDevice interface.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.

See Also

IDirect3DDevice3::BeginScene


IDirect3DDevice3::EnumTextureFormats

The IDirect3DDevice3::EnumTextureFormats method queries the current driver for a list of supported texture formats.

HRESULT EnumTextureFormats(
  LPD3DENUMPIXELFORMATSCALLBACK lpd3dEnumPixelProc,
  LPVOID lpArg
);

Parameters

lpd3dEnumTextureProc
Address of the D3DEnumPixelFormatsCallback callback function that the enumeration procedure will call for each texture format.
lpArg
Address of application-defined data passed to the callback function.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value may be one of the following values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS

Remarks

In the IDirect3DDevice2 interface, this method accepts a pointer to a D3DEnumTextureFormatsCallback function, not a D3DEnumPixelFormatsCallback.

This method might not enumerate newly implemented texture formats on some devices. Applications that require a texture format that isn't enumerated can attempt to create a surface of that format. If the creation attempt succeeds, the format is supported.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.


IDirect3DDevice3::GetCaps

The IDirect3DDevice3::GetCaps method retrieves the capabilities of the Direct3D device.

HRESULT GetCaps(
  LPD3DDEVICEDESC lpD3DHWDevDesc,
  LPD3DDEVICEDESC lpD3DHELDevDesc
);

Parameters

lpD3DHWDevDesc
Address of the D3DDEVICEDESC structure that will contain the hardware features of the device.
lpD3DHELDevDesc
Address of the D3DDEVICEDESC structure that will contain the software emulation being provided.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value may be one of the following values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS

Remarks

This method does not retrieve the capabilities of the display device. To retrieve this information, use the IDirectDraw4::GetCaps method.

This method is unchanged from its implementation in the IDirect3DDevice interface.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.


IDirect3DDevice3::GetClipStatus

The IDirect3DDevice3::GetClipStatus method gets the current clip status.

HRESULT GetClipStatus(
  LPD3DCLIPSTATUS lpD3DClipStatus
);

Parameters

lpD3DClipStatus
Address of a D3DCLIPSTATUS structure that describes the current clip status.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value is an error. The method returns DDERR_INVALIDPARAMS if one of the arguments is invalid.

Remarks

This method was introduced with the IDirect3DDevice2 interface.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.

See Also

IDirect3DDevice3::SetClipStatus


IDirect3DDevice3::GetCurrentViewport

The IDirect3DDevice3::GetCurrentViewport method retrieves the current viewport.

HRESULT GetCurrentViewport(
  LPDIRECT3DVIEWPORT3 *lplpd3dViewport
);

Parameters

lplpd3dViewport
Address that will contain a pointer to the current viewport's IDirect3DViewport3 interface when the method returns. A reference is taken to the viewport object.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value may be one of the following values:

DDERR_INVALIDPARAMS | One of the arguments is invalid.
D3DERR_NOCURRENTVIEWPORT | No current viewport has been set by a call to the IDirect3DDevice3::SetCurrentViewport method.

Remarks

This method increases the reference count of the viewport interface retrieved in the lplpd3dViewport parameter. The application must release this interface when it is no longer needed.

This method was introduced with the IDirect3DDevice2 interface. In the IDirect3DDevice2 interface, this method accepts a pointer to an IDirect3DViewport interface, not an IDirect3DViewport3 interface.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.

See Also

IDirect3DDevice3::SetCurrentViewport


IDirect3DDevice3::GetDirect3D

The IDirect3DDevice3::GetDirect3D method retrieves the Direct3D object for this device.

HRESULT GetDirect3D(
  LPDIRECT3D3 *lplpD3D
);

Parameters

lplpD3D
Address that will contain a pointer to the Direct3D object's IDirect3D3 interface when the method returns.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value is an error. For a list of possible return codes, see Direct3D Immediate Mode Return Values.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.


IDirect3DDevice3::GetLightState

The IDirect3DDevice3::GetLightState method gets a single Direct3D device lighting-related state value.

HRESULT GetLightState(
  D3DLIGHTSTATETYPE dwLightStateType,
  LPDWORD lpdwLightState
);

Parameters

dwLightStateType
Device state variable that is being queried. This parameter can be any of the members of the D3DLIGHTSTATETYPE enumerated type.
lpdwLightState
Address of a variable that will contain the Direct3DDevice light state when the method returns.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value is an error. The method returns DDERR_INVALIDPARAMS if one of the arguments is invalid.

Remarks

This method was introduced with the IDirect3DDevice2 interface.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.

See Also

IDirect3DDevice3::SetLightState


IDirect3DDevice3::GetRenderState

The IDirect3DDevice3::GetRenderState method gets a single Direct3DDevice rendering state parameter.

HRESULT GetRenderState(
  D3DRENDERSTATETYPE dwRenderStateType,
  LPDWORD lpdwRenderState
);

Parameters

dwRenderStateType
Device state variable that is being queried. This parameter can be any of the members of the D3DRENDERSTATETYPE enumerated type.
lpdwRenderState
Address of a variable that will contain the Direct3DDevice render state when the method returns.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value is an error. The method returns DDERR_INVALIDPARAMS if one of the arguments is invalid.

Remarks

This method was introduced with the IDirect3DDevice2 interface.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.

See Also

IDirect3DDevice3::SetRenderState


IDirect3DDevice3::GetRenderTarget

The IDirect3DDevice3::GetRenderTarget method retrieves a pointer to the DirectDraw surface that is being used as a render target.

HRESULT GetRenderTarget(
  LPDIRECTDRAWSURFACE4 *lplpRenderTarget
);

Parameters

lplpRenderTarget
Address that will contain a pointer to the IDirectDrawSurface4 interface of the render target surface for this device.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value is an error. The method returns DDERR_INVALIDPARAMS if one of the arguments is invalid.

Remarks

This method was introduced with the IDirect3DDevice2 interface.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.

See Also

IDirect3DDevice3::SetRenderTarget


IDirect3DDevice3::GetStats

The IDirect3DDevice3::GetStats method is obsolete, and not implemented in the IDirect3DDevice3 interface.

HRESULT GetStats(
  LPD3DSTATS lpD3DStats
);

Return Values

The method returns E_NOTIMPL.

Remarks

This method is implemented in the IDirect3DDevice2 and IDirect3DDevice interfaces, but can under-report statistics when used with DirectX 6.0 and later drivers.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.


IDirect3DDevice3::GetTexture

The IDirect3DDevice3::GetTexture method retrieves a texture assigned to a given stage for a device.

HRESULT  GetTexture(
  DWORD dwStage,
  LPDIRECT3DTEXTURE2 * lplpTexture
);

Parameters

dwStage
Stage identifier of the texture to be retrieved. Stage identifiers are zero-based. Currently, devices can have up to 8 set textures, so the maximum allowable value allowed for dwStage is 7.
lplpTexture
Address of a variable that will be filled with a pointer to the specified texture's IDirect3DTexture2 interface if the call succeeds.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value may be one of the following values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS

Remarks

This method was introduced with the IDirect3DDevice3 interface.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.

See Also

IDirect3DDevice3::SetTexture, IDirect3DDevice3::GetTextureStageState, IDirect3DDevice3::SetTextureStageState, Textures


IDirect3DDevice3::GetTextureStageState

The IDirect3DDevice3::GetTextureStageState method retrieves a state value for a currently assigned texture.

HRESULT GetTextureStageState(
  DWORD   dwStage,
  D3DTEXTURESTAGESTATETYPE dwState,
  LPDWORD lpdwValue
);

Parameters

dwStage
Stage identifier of the texture for which the state will be retrieved. Stage identifiers are zero-based. Currently, devices can have up to 8 set textures, so the maximum allowable value allowed for dwStage is 7.
dwState
Texture state to be retrieved. This parameter can be any member of the D3DTEXTURESTAGESTATETYPE enumerated type.
lpdwValue
Address of a variable that will be filled with the retrieved state value. The meaning of the retrieved value is determined by the dwState parameter.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value may be one of the following values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS

Remarks

This method was introduced with the IDirect3DDevice3 interface.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.

See Also

IDirect3DDevice3::SetTextureStageState, IDirect3DDevice3::GetTexture, IDirect3DDevice3::SetTexture, Textures


IDirect3DDevice3::GetTransform

The IDirect3DDevice3::GetTransform method gets a matrix describing a transformation state.

HRESULT GetTransform(
  D3DTRANSFORMSTATETYPE dtstTransformStateType,
  LPD3DMATRIX lpD3DMatrix
);

Parameters

dtstTransformStateType
Device state variable that is being modified. This parameter can be any of the members of the D3DTRANSFORMSTATETYPE enumerated type.
lpD3DMatrix
Address of a D3DMATRIX structure describing the transformation.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value is an error. The method returns DDERR_INVALIDPARAMS if one of the arguments is invalid.

Remarks

This method was introduced with the IDirect3DDevice2 interface.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.

See Also

IDirect3DDevice3::SetTransform


IDirect3DDevice3::Index

The IDirect3DDevice3::Index method adds a new index to the primitive sequence started with a previous call to the IDirect3DDevice3::BeginIndexed method.

HRESULT Index(
  WORD wVertexIndex
);

Parameters

wVertexIndex
Index of the next vertex to be added to the currently started primitive sequence.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value may be one of the following values:

D3DERR_INVALIDRAMPTEXTURE | Ramp mode is being used and the texture handle in the current material does not match the current texture handle that is set as a render state.
DDERR_INVALIDPARAMS | One of the arguments is invalid.

Remarks

This method was introduced with the IDirect3DDevice2 interface.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.

See Also

IDirect3DDevice3::BeginIndexed, IDirect3DDevice3::End


IDirect3DDevice3::MultiplyTransform

The IDirect3DDevice3::MultiplyTransform method multiplies a device's world, view, or projection matrices by a specified matrix. The multiplication order is lpD3DMatrix times dtstTransformStateType.

HRESULT MultiplyTransform(
  D3DTRANSFORMSTATETYPE dtstTransformStateType,
  LPD3DMATRIX lpD3DMatrix
);

Parameters

dtstTransformStateType
A member of the D3DTRANSFORMSTATETYPE enumerated type that identifies which device matrix is to be modified. The most common setting, D3DTRANSFORMSTATE_WORLD, modifies the world matrix, but you can specify that the method modify the view or projection matrices if needed.
lpD3DMatrix
Address of a D3DMATRIX structure that modifies the current transformation.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value is an error. The method returns DDERR_INVALIDPARAMS if one of the arguments is invalid.

Remarks

An application might use the MultiplyTransform method to work with hierarchies of transformations. For example, the geometry and transformations describing an arm might be arranged in the following hierarchy:

shoulder_transformation
    upper_arm geometry
    elbow transformation
        lower_arm geometry
        wrist transformation
            hand geometry

An application might use the following series of calls to render this hierarchy. (Not all of the parameters are shown in this pseudocode.)

IDirect3DDevice3::SetTransform(D3DTRANSFORMSTATE_WORLD,
    shoulder_transform)
IDirect3DDevice3::DrawPrimitive(upper_arm)
IDirect3DDevice3::MultiplyTransform(D3DTRANSFORMSTATE_WORLD,
    elbow_transform)
IDirect3DDevice3::DrawPrimitive(lower_arm)
IDirect3DDevice3::MultiplyTransform(D3DTRANSFORMSTATE_WORLD,
    wrist_transform)
IDirect3DDevice3::DrawPrimitive(hand)

This method was introduced with the IDirect3DDevice2 interface.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.

See Also

IDirect3DDevice3::DrawPrimitive, IDirect3DDevice3::SetTransform


IDirect3DDevice3::NextViewport

The IDirect3DDevice3::NextViewport method enumerates the viewports associated with the device.

HRESULT NextViewport(
  LPDIRECT3DVIEWPORT3 lpDirect3DViewport,
  LPDIRECT3DVIEWPORT3 *lplpAnotherViewport,
  DWORD dwFlags
);

Parameters

lpDirect3DViewport
Address of the IDirect3DViewport3 interface of a viewport in the list of viewports associated with this Direct3D device.
lplpAnotherViewport
Address that will contain a pointer to the IDirect3DViewport3 interface for another viewport in the device's viewport list. Which viewport the method retrieves is determined by the flag in the dwFlags parameter.
dwFlags
Flag specifying which viewport to retrieve from the list of viewports. This must be set to one of the following flags:
D3DNEXT_HEAD
Retrieve the item at the beginning of the list.
D3DNEXT_NEXT
Retrieve the next item in the list.
D3DNEXT_TAIL
Retrieve the item at the end of the list.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value may be one of the following values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS

Remarks

If you attempt to retrieve the next viewport in the list when you are at the end of the list, this method returns D3D_OK but lplpAnotherViewport is NULL.

In the IDirect3DDevice2 interface, this method requires pointers to IDirect3DViewport2 interfaces, not IDirect3DViewport3 interfaces.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.


IDirect3DDevice3::SetClipStatus

The IDirect3DDevice3::SetClipStatus method sets the current clip status.

HRESULT SetClipStatus(
  LPD3DCLIPSTATUS lpD3DClipStatus
);

Parameters

lpD3DClipStatus
Address of a D3DCLIPSTATUS structure that describes the new settings for the clip status.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value is an error. The method returns DDERR_INVALIDPARAMS if one of the arguments is invalid.

Remarks

This method was introduced with the IDirect3DDevice2 interface.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.

See Also

IDirect3DDevice3::GetClipStatus


IDirect3DDevice3::SetCurrentViewport

The IDirect3DDevice3::SetCurrentViewport method sets the current viewport.

HRESULT SetCurrentViewport(
  LPDIRECT3DVIEWPORT3 lpd3dViewport
);

Parameters

lpd3dViewport
Address of the IDirect3DViewport3 interface for the viewport that will become the current viewport if the method is successful.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value is an error. The method returns DDERR_INVALIDPARAMS if one of the arguments is invalid.

Remarks

Applications must call this method before calling any rendering functions. Before calling this method, applications must have already called the IDirect3DDevice3::AddViewport method to add the viewport to the device.

Before the first call to IDirect3DDevice3::SetCurrentViewport, the current viewport for the device is invalid, and any attempts to render using the device will fail.

This method increases the reference count of the viewport interface specified by the lpd3dViewport parameter and releases the previous viewport, if any.

This method was introduced with the IDirect3DDevice2 interface. In the IDirect3DDevice2 interface, this method accepts a pointer to an IDirect3DViewport interface, not an IDirect3DViewport3 interface.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.

See Also

IDirect3DDevice3::GetCurrentViewport


IDirect3DDevice3::SetLightState

The IDirect3DDevice3::SetLightState method sets a single Direct3DDevice lighting-related state value.

HRESULT SetLightState(
  D3DLIGHTSTATETYPE dwLightStateType,
  DWORD dwLightState
);

Parameters

dwLightStateType
Device state variable that is being modified. This parameter can be any of the members of the D3DLIGHTSTATETYPE enumerated type.
dwLightState
New value for the Direct3DDevice light state. The meaning of this parameter is dependent on the value specified for dwLightStateType. For example, if dwLightStateType were D3DLIGHTSTATE_COLORMODEL, the second parameter would be one of the values of the D3DCOLORMODEL data type.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value is an error. The method returns DDERR_INVALIDPARAMS if one of the arguments is invalid.

Remarks

This method was introduced with the IDirect3DDevice2 interface.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.

See Also

IDirect3DDevice3::GetLightState, IDirect3DDevice3::SetRenderState, IDirect3DDevice3::SetTransform


IDirect3DDevice3::SetRenderState

The IDirect3DDevice3::SetRenderState method sets a single Direct3DDevice rendering state parameter.

HRESULT SetRenderState(
  D3DRENDERSTATETYPE dwRenderStateType,
  DWORD dwRenderState
);

Parameters

dwRenderStateType
Device state variable that is being modified. This parameter can be any of the members of the D3DRENDERSTATETYPE enumerated type.
dwRenderState
New value for the Direct3DDevice render state. The meaning of this parameter is dependent on the value specified for dwRenderStateType. For example, if dwRenderStateType were D3DRENDERSTATE_SHADEMODE, the second parameter would be one of the members of the D3DSHADEMODE enumerated type.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value is an error. The method returns DDERR_INVALIDPARAMS if one of the arguments is invalid.

Remarks

This method was introduced with the IDirect3DDevice2 interface.

Applications should use the IDirect3DDevice3::SetTextureStageState method to set texture states in favor of the legacy texture-related render states. For more information, see About Render States.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.

See Also

IDirect3DDevice3::GetRenderState, IDirect3DDevice3::SetLightState, IDirect3DDevice3::SetTransform


IDirect3DDevice3::SetRenderTarget

The IDirect3DDevice3::SetRenderTarget method permits the application to easily route rendering output to a new DirectDraw surface as a render target.

HRESULT SetRenderTarget(
  LPDIRECTDRAWSURFACE4 lpNewRenderTarget,
  DWORD dwFlags
);

Parameters

lpNewRenderTarget
Address of a IDirectDrawSurface4 interface for the surface object that will be the new rendering target. This surface must be created with the DDSCAPS_3DDEVICE capability.
dwFlags
Not currently used; set to zero.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value is an error. The error may be one of the following values:

DDERR_INVALIDPARAMS | One of the arguments is invalid.
DDERR_INVALIDSURFACETYPE | The surface passed as the first parameter is invalid.

Remarks

You cannot use this method to set a new render target surface with a depth-buffer if the current render target does not have a depth buffer. Likewise, you cannot use this method to switch from a non-depth-buffered render target to a depth-buffered render target. Attempts to do this will fail in debug builds, and can exhibit unreliable behavior in retail builds. Given that both the new and old render targets use depth buffers, the depth-buffer attached to the new render target replaces the previous depth-buffer for the context.

When you change the rendering target, all of the handles associated with the previous rendering target become invalid. This means that you will have to reacquire all of the texture handles. If you are using ramp mode, you should also update the texture handles inside materials, by calling the IDirect3DMaterial3::SetMaterial method. Any execute buffers (which have embedded handles) also need to be updated. The IDirect3DDevice3::SetRenderTarget method is most useful to applications that use the DrawPrimitive methods, especially when these applications do not use ramp mode.

If the new render target surface has different dimensions from the old (length, width, pixel-format), this method marks the viewport as invalid. The viewport may be revalidated after calling IDirect3DDevice3::SetRenderTarget by calling IDirect3DViewport3::SetViewport to restate viewport parameters that are compatible with the new surface.

Capabilities do not change with changes in the properties of the render target surface. Both the Direct3D HAL and the software rasterizers have only one opportunity to expose capabilities to the application. The system cannot expose different sets of capabilities depending on the format of the destination surface.

If more than one depth-buffer is attached to the render target, this function fails.

This method was introduced with the IDirect3DDevice2 interface.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.

See Also

IDirect3DDevice3::GetRenderTarget


IDirect3DDevice3::SetTexture

The IDirect3DDevice3::SetTexture method assigns a texture to a given stage for a device.

HRESULT  SetTexture(
  DWORD dwStage,
  LPDIRECT3DTEXTURE2 lpTexture
);

Parameters

dwStage
Stage identifier to which the texture will be set. Stage identifiers are zero-based. Currently, devices can have up to 8 set textures, so the maximum allowable value allowed for dwStage is 7.
lpTexture
Address of the IDirect3DTexture2 interface for the texture being set.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value may be one of the following values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS

Remarks

This method was introduced with the IDirect3DDevice3 interface.

Software devices do not support assigning a texture to more than one texture stage at a time.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.

See Also

IDirect3DDevice3::GetTexture, IDirect3DDevice3::GetTextureStageState, IDirect3DDevice3::SetTextureStageState, Textures


IDirect3DDevice3::SetTextureStageState

The IDirect3DDevice3::SetTextureStageState method sets the state value for a currently assigned texture.

HRESULT SetTextureStageState(
  DWORD dwStage,
  D3DTEXTURESTAGESTATETYPE dwState,
  DWORD dwValue
);

Parameters

dwStage
Stage identifier of the texture for which the state value will be set. Stage identifiers are zero-based. Currently, devices can have up to 8 set textures, so the maximum allowable value allowed for dwStage is 7.
dwState
Texture state to be set. This parameter can be any member of the D3DTEXTURESTAGESTATETYPE enumerated type.
dwValue
State value to be set. The meaning of this value is determined by the dwState parameter.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value may be one of the following values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS

Remarks

This method was introduced with the IDirect3DDevice3 interface.

Applications should use this method to set texture states in favor of the legacy texture-related render states. For more information, see About Render States.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.

See Also

IDirect3DDevice3::GetTextureStageState, IDirect3DDevice3::GetTexture, IDirect3DDevice3::SetTexture, Textures


IDirect3DDevice3::SetTransform

The IDirect3DDevice3::SetTransform method sets a single Direct3DDevice transformation-related state.

HRESULT SetTransform(
  D3DTRANSFORMSTATETYPE dtstTransformStateType,
  LPD3DMATRIX lpD3DMatrix
);

Parameters

dtstTransformStateType
Device state variable that is being modified. This parameter can be any of the members of the D3DTRANSFORMSTATETYPE enumerated type.
lpD3DMatrix
Address of a D3DMATRIX structure that modifies the current transformation.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value is an error. The method returns DDERR_INVALIDPARAMS if one of the arguments is invalid.

Remarks

This method was introduced with the IDirect3DDevice2 interface.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.

See Also

IDirect3DDevice3::GetTransform, IDirect3DDevice3::SetLightState, IDirect3DDevice3::SetRenderState


IDirect3DDevice3::ValidateDevice

The IDirect3DDevice3::ValidateDevice method reports the device's ability to render the currently set texture blending operations and arguments in a single pass.

HRESULT ValidateDevice(
  LPDWORD lpdwPasses
);

Parameters

lpdwPasses
Address that will be filled with the number of rendering passes to complete the desired effect through multipass rendering.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value may be one of the following values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
D3DERR_CONFLICTINGTEXTUREFILTER
D3DERR_CONFLICTINGTEXTUREPALETTE
D3DERR_TOOMANYOPERATIONS
D3DERR_UNSUPPORTEDALPHAARG
D3DERR_UNSUPPORTEDALPHAOPERATION
D3DERR_UNSUPPORTEDCOLORARG
D3DERR_UNSUPPORTEDCOLOROPERATION
D3DERR_UNSUPPORTEDFACTORVALUE
D3DERR_UNSUPPORTEDTEXTUREFILTER
D3DERR_WRONGTEXTUREFORMAT

Remarks

Current hardware does not necessarily implement all possible combinations of operations and arguments. You can determine whether a particular blending operation can be performed with given arguments by setting-up the desired blending operation, then calling the ValidateDevice method.

The ValidateDevice method uses the currently set render states, textures, and, texture stage states to perform validation at the time of the call. Any changes to these factors after the call invalidate the previous result, and the method must be called again before rendering a scene.

Using diffuse iterated values, either as an argument or as an operation (D3DTA_DIFFUSE or D3DTOP_BLENDDIFFUSEALPHA) is sparsely supported on current hardware. Most hardware can only introduce iterated color data at the last texture operation stage.

Try to specify the texture (D3DTA_TEXTURE) for each stage as the first argument, in preference to the second argument.

Many cards do not support use of diffuse or scalar values at arbitrary texture stages. Often, these are only available at the first or last texture blending stage.

Many cards do not actually have a blending unit associated with the first texture that is capable of more than replicating alpha to color channels, or inverting the input. As a result, your application might need to use only the second texture stage if possible. On such hardware, the first unit is presumed to be in its default state, which has the first color argument set to D3DTA_TEXTURE with the D3DTOP_SELECTARG1 operation.

Operations on the output alpha that are more intricate than or substantially different from the color operations are less likely to be supported.

Some hardware does not support simultaneous use of both D3DTA_TFACTOR and D3DTA_DIFFUSE.

Many cards do not support simultaneous use of multiple textures and mipmapped trilinear filtering. If trilinear filtering has been requested for a texture involved in multi-texture blending operations and validation fails, turn off trilinear filtering and revalidate. In this case, it might be best to perform multipass rendering instead.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.

See Also

IDirect3DDevice3::GetTextureStageState, IDirect3DDevice3::SetTextureStageState


IDirect3DDevice3::Vertex

The IDirect3DDevice3::Vertex method adds a new Direct3D vertex to the primitive sequence started with a previous call to the IDirect3DDevice3::Begin method.

HRESULT Vertex(
  LPVOID lpVertex
);

Parameters

lpVertex
Pointer to the next Direct3D vertex to be added to the currently started primitive sequence. This can be any of the Direct3D vertex types (D3DLVERTEX, D3DTLVERTEX, or D3DVERTEX) or a vertex specified in flexible vertex format. The vertex format must match the description specified in the preceding call to IDirect3DDevice3::Begin.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value may be one of the following values:

D3DERR_INVALIDRAMPTEXTURE | Ramp mode is being used and the texture handle in the current material does not match the current texture handle that is set as a render state.
DDERR_INVALIDPARAMS | One of the arguments is invalid.

Remarks

This method was introduced with the IDirect3DDevice2 interface.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.

See Also

IDirect3DDevice3::Begin, IDirect3DDevice3::End


IDirect3DExecuteBuffer

Applications use the methods of the IDirect3DExecuteBuffer interface to set up and control Direct3D execute buffers. This section is a reference to the methods of this interface. For a conceptual overview, see Execute Buffers.

The methods of the IDirect3DExecuteBuffer interface can be organized into the following groups:

Execute data | GetExecuteData
 | SetExecuteData
Lock and unlock | Lock
 | Unlock
Miscellaneous | Initialize
 | Optimize
 | Validate

The IDirect3DExecuteBuffer interface, like all COM interfaces, inherits the IUnknown interface methods. The IUnknown interface supports the following three methods:

IUnknown | AddRef
 | QueryInterface
 | Release

The LPDIRECT3DEXECUTEBUFFER type is defined as a pointer to the IDirect3DExecuteBuffer interface:

typedef struct IDirect3DExecuteBuffer    *LPDIRECT3DEXECUTEBUFFER;

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.

See Also

Execute Buffers


IDirect3DExecuteBuffer::GetExecuteData

The IDirect3DExecuteBuffer::GetExecuteData method retrieves the execute data state of the Direct3DExecuteBuffer object. The execute data is used to describe the contents of the Direct3DExecuteBuffer object.

HRESULT GetExecuteData(
  LPD3DEXECUTEDATA lpData
);

Parameters

lpData
Address of a D3DEXECUTEDATA structure that will be filled with the current execute data state of the Direct3DExecuteBuffer object.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value may be one of the following values:

D3DERR_EXECUTE_LOCKED
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS

Remarks

This call fails if the Direct3DExecuteBuffer object is locked.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.

See Also

IDirect3DExecuteBuffer::SetExecuteData


IDirect3DExecuteBuffer::Initialize

The IDirect3DExecuteBuffer::Initialize method is provided for compliance with the COM protocol.

HRESULT Initialize(
  LPDIRECT3DDEVICE lpDirect3DDevice,
  LPD3DEXECUTEBUFFERDESC lpDesc
);

Parameters

lpDirect3DDevice
Address of the device representing the Direct3D object.
lpDesc
Address of a D3DEXECUTEBUFFERDESC structure that describes the Direct3DExecuteBuffer object to be created. The call fails if a buffer of at least the specified size cannot be created.

Return Values

The method returns DDERR_ALREADYINITIALIZED because the Direct3DExecuteBuffer object is initialized when it is created.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.


IDirect3DExecuteBuffer::Lock

The IDirect3DExecuteBuffer::Lock method obtains a direct pointer to the commands in the execute buffer.

HRESULT Lock(
  LPD3DEXECUTEBUFFERDESC lpDesc
);

Parameters

lpDesc
Address of a D3DEXECUTEBUFFERDESC structure. When the method returns, the lpData member will be set to point to the actual data to which the application has access. This data may reside in system or video memory, and is specified by the dwCaps member. The application may use the IDirect3DExecuteBuffer::Lock method to request that Direct3D move the data between system or video memory.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value may be one of the following values:

D3DERR_EXECUTE_LOCKED
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_WASSTILLDRAWING

Remarks

This call fails if the Direct3DExecuteBuffer object is locked—that is, if another thread is accessing the buffer, or if a IDirect3DDevice::Execute method that was issued on this buffer has not yet completed.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.

See Also

IDirect3DExecuteBuffer::Unlock


IDirect3DExecuteBuffer::Optimize

The IDirect3DExecuteBuffer::Optimize method is not currently supported.

HRESULT Optimize();

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.


IDirect3DExecuteBuffer::SetExecuteData

The IDirect3DExecuteBuffer::SetExecuteData method sets the execute data state of the Direct3DExecuteBuffer object. The execute data is used to describe the contents of the Direct3DExecuteBuffer object.

HRESULT SetExecuteData(
  LPD3DEXECUTEDATA lpData
);

Parameters

lpData
Address of a D3DEXECUTEDATA structure that describes the execute buffer layout.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value may be one of the following values:

D3DERR_EXECUTE_LOCKED
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS

Remarks

This call fails if the Direct3DExecuteBuffer object is locked.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.

See Also

IDirect3DExecuteBuffer::GetExecuteData


IDirect3DExecuteBuffer::Unlock

The IDirect3DExecuteBuffer::Unlock method releases the direct pointer to the commands in the execute buffer. This must be done prior to calling the IDirect3DDevice::Execute method for the buffer.

HRESULT Unlock();

Parameters

None.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value may be one of the following values:

D3DERR_EXECUTE_NOT_LOCKED
DDERR_INVALIDOBJECT

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.

See Also

IDirect3DExecuteBuffer::Lock


IDirect3DExecuteBuffer::Validate

The IDirect3DExecuteBuffer::Validate method is not currently implemented.

HRESULT Validate(
  LPDWORD lpdwOffset,
  LPD3DVALIDATECALLBACK lpFunc,
  LPVOID lpUserArg,
  DWORD dwReserved
);

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.


IDirect3DLight

Applications use the methods of the IDirect3DLight interface to retrieve and set the capabilities of lights. This section is a reference to the methods of this interface. For a conceptual overview, see Lights.

The IDirect3DLight interface is obtained by calling the IDirect3D3::CreateLight method.

The methods of the IDirect3DLight interface can be organized into the following groups:

Get and set | GetLight
 | SetLight
Initialization | Initialize

The IDirect3DLight interface, like all COM interfaces, inherits the IUnknown interface methods. The IUnknown interface supports the following three methods:

IUnknown | AddRef
 | QueryInterface
 | Release

The LPDIRECT3DLIGHT type is defined as a pointer to the IDirect3DLight interface:

typedef struct IDirect3DLight    *LPDIRECT3DLIGHT;

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.


IDirect3DLight::GetLight

The IDirect3DLight::GetLight method retrieves the light information for the Direct3DLight object.

HRESULT GetLight(
  LPD3DLIGHT lpLight
);

Parameters

lpLight
Address of a D3DLIGHT2 structure that will be filled with the current light data.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value may be one of the following values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS

Remarks

Although this method's declaration specifies the lpLight parameter as being the address of a D3DLIGHT structure, that structure is not normally used. Rather, the D3DLIGHT2 structure is recommended to achieve the best lighting effects.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.

See Also

IDirect3DLight::SetLight


IDirect3DLight::Initialize

The IDirect3DLight::Initialize method is provided for compliance with the COM protocol.

HRESULT Initialize(
  LPDIRECT3D lpDirect3D
);

Parameters

lpDirect3D
Address of the IDirect3D interface for the Direct3D object.

Return Values

The method returns DDERR_ALREADYINITIALIZED because the Direct3DLight object is initialized when it is created.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.


IDirect3DLight::SetLight

The IDirect3DLight::SetLight method sets the light information for the Direct3DLight object.

HRESULT SetLight(
  LPD3DLIGHT lpLight
);

Parameters

lpLight
Address of a D3DLIGHT2 structure that will be used to set the current light data.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value may be one of the following values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS

Remarks

Although this method's declaration specifies the lpLight parameter as being the address of a D3DLIGHT structure, that structure is not normally used. Rather, the D3DLIGHT2 structure is recommended to achieve the best lighting effects.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in ddraw.h.
Import Library: Use ddraw.lib.

See Also

IDirect3DLight::GetLight


IDirect3DMaterial3

Applications use the methods of the IDirect3DMaterial3 interface to retrieve and set the properties of materials. This section is a reference to the methods of this interface. For a conceptual overview, see Materials.

You create this interface by calling the IDirect3D3::CreateMaterial method. The IDirect3DMaterial3 interface provides identical services to its predecessor, the IDirect3DMaterial2 interface, but binds materials to the latest iteration of the Direct3DDevice interface, IDirect3DDevice3.

The methods of the IDirect3DMaterial3 interface can be organized into the following groups:

Handles | GetHandle
Materials | GetMaterial
 | SetMaterial

The IDirect3DMaterial3 interface, like all COM interfaces, inherits the IUnknown interface methods. The IUnknown interface supports the following three methods:

IUnknown | AddRef
 | QueryInterface
 | Release

The LPDIRECT3DMATERIAL3, LPDIRECT3DMATERIAL2, and LPDIRECT3DMATERIAL types are defined as pointers to the IDirect3DMaterial3, IDirect3DMaterial2 and IDirect3DMaterial interfaces:

typedef struct IDirect3DMaterial3    *LPDIRECT3DMATERIAL3;
typedef struct IDirect3DMaterial2    *LPDIRECT3DMATERIAL2;
typedef struct IDirect3DMaterial     *LPDIRECT3DMATERIAL;

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.

See Also

Materials, Lighting and Materials


IDirect3DMaterial3::GetHandle

The IDirect3DMaterial3::GetHandle method binds a material to a device, retrieving a handle that represents the association between the two. This handle is used in all Direct3D methods in which a material is to be referenced. A material can be used by only one device at a time.

If the device is destroyed, the material is disassociated from the device.

HRESULT GetHandle(
  LPDIRECT3DDEVICE3 lpDirect3DDevice,
  LPD3DMATERIALHANDLE lpHandle
);

Parameters

lpDirect3DDevice
Address of the IDirect3DDevice3 interface for the rendering device to which the material is being bound.
lpHandle
Address of a variable that will be filled with the material handle corresponding to the Direct3DMaterial object.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value is DDERR_INVALIDOBJECT.

Remarks

In the IDirect3DMaterial2 interface, this method accepts a pointer to an IDirect3DDevice2 interface instead of an IDirect3DDevice3 interface.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.

See Also

Retrieving Material Handles


IDirect3DMaterial3::GetMaterial

The IDirect3DMaterial3::GetMaterial method retrieves the material data for the Direct3DMaterial object.

HRESULT GetMaterial(
  LPD3DMATERIAL lpMat
);

Parameters

lpMat
Address of a D3DMATERIAL structure that will be filled with the current material properties.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value may be one of the following values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS

Remarks

This method is unchanged from its implementation in the IDirect3DMaterial2 interface.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.

See Also

IDirect3DMaterial3::SetMaterial, Retrieving Material Properties, Setting Material Properties


IDirect3DMaterial3::SetMaterial

The IDirect3DMaterial3::SetMaterial method sets the material data for a material object.

HRESULT SetMaterial(
  LPD3DMATERIAL lpMat
);

Parameters

lpMat
Address of a D3DMATERIAL structure that contains the material properties.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value may be one of the following values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.

See Also

IDirect3DMaterial3::GetMaterial, Retrieving Material Properties, Setting Material Properties


IDirect3DTexture2

Applications use the methods of the IDirect3DTexture2 interface to retrieve and set the properties of textures. This section is a reference to the methods of this interface. For a conceptual overview, see Textures.

You create the IDirect3DTexture2 interface by calling the IDirectDrawSurface::QueryInterface method from the DirectDrawSurface object that was created as a texture map.

The methods of the IDirect3DTexture2 interface can be organized into the following groups:

Handles | GetHandle
Loading | Load
Palette information | PaletteChanged

The IDirect3DTexture2 interface, like all COM interfaces, inherits the IUnknown interface methods. The IUnknown interface supports the following three methods:

IUnknown | AddRef
 | QueryInterface
 | Release

The LPDIRECT3DTEXTURE2 and LPDIRECT3DTEXTURE types are defined as pointers to the IDirect3DTexture2 and IDirect3DTexture interfaces:

typedef struct IDirect3DTexture2    *LPDIRECT3DTEXTURE2;
typedef struct IDirect3DTexture     *LPDIRECT3DTEXTURE;

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.

See Also

Textures


IDirect3DTexture2::GetHandle

The IDirect3DTexture2::GetHandle method obtains the texture handle to be used when rendering with the IDirect3DDevice2 or IDirect3DDevice interfaces.

HRESULT GetHandle(
  LPDIRECT3DDEVICE2 lpDirect3DDevice2,
  LPD3DTEXTUREHANDLE lpHandle
);

Parameters

lpDirect3DDevice2
Address of the Direct3DDevice2 object into which the texture is to be loaded.
lpHandle
Address that will contain the texture handle corresponding to the Direct3DTexture2 object.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value may be one of the following values:

DDERR_INVALIDPARAMS

Remarks

In the IDirect3DTexture interface, this method uses a pointer to a Direct3DDevice object instead of a Direct3DDevice2 object.

Texture handles are used only device interfaces earlier than IDirect3DDevice3. The IDirect3DDevice3 interface references textures using texture interface pointers, set through the IDirect3DDevice3::SetTexture method.

You cannot use this method to retrieve the handle of a texture that is managed by Direct3D. For more information, see Automatic Texture Management .

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.


IDirect3DTexture2::Load

The IDirect3DTexture2::Load method loads a texture that was created with the DDSCAPS_ALLOCONLOAD flag, which indicates that memory for the DirectDraw surface is not allocated until this method loads the surface.

HRESULT Load(
  LPDIRECT3DTEXTURE2 lpD3DTexture2
);

Parameters

lpD3DTexture2
Address of the texture to load.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value is an error. For a list of possible return values, see Direct3D Immediate Mode Return Values.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.


IDirect3DTexture2::PaletteChanged

The IDirect3DTexture2::PaletteChanged method informs the driver that the palette has changed on a texture surface.

HRESULT PaletteChanged(
  DWORD dwStart,
  DWORD dwCount
);

Parameters

dwStart
Index of first palette entry that has changed.
dwCount
Total number of palette entries that have changed.

Return Values

This method returns D3D_OK.

If the method fails, the return value is an error. For a list of possible return values, see Direct3D Immediate Mode Return Values.

Remarks

This method is particularly useful for applications that play video clips and therefore require palette-changing capabilities.

This method only affects the legacy ramp device. For all other devices, this method takes no action and returns D3D_OK.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.


IDirect3DVertexBuffer

Applications use the methods of the IDirect3DVertexBuffer interface to manipulate a collection of vertices for use with the IDirect3DDevice3::DrawPrimitiveVB and IDirect3DDevice3::DrawIndexedPrimitiveVB rendering methods. This section is a reference to the methods of this interface. For a conceptual overview, see Vertex Buffers.

This methods of the IDirect3DVertexBuffer interface can be organized into the following groups:

Information | GetVertexBufferDesc
Vertex data | Lock
 | Optimize
 | ProcessVertices
 | Unlock

The IDirect3DVertexBuffer interface, like all COM interfaces, inherits the IUnknown interface methods. The IUnknown interface supports the following three methods:

IUnknown | AddRef
 | QueryInterface
 | Release

The LPDIRECT3DVERTEXBUFFER data type is defined as a pointer to the IDirect3DVertexBuffer interface:

typedef struct IDirect3DVertexBuffer *LPDIRECT3DVERTEXBUFFER

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.

See Also

Vertex Buffers


IDirect3DVertexBuffer::GetVertexBufferDesc

The IDirect3DVertexBuffer::GetVertexBufferDesc method retrieves a description of the vertex buffer.

HRESULT GetVertexBufferDesc(
  LPD3DVERTEXBUFFERDESC lpVBDesc,
);

Parameters

lpVBDesc
Address of a D3DVERTEXBUFFERDESC structure that will be filled with a description of the vertex buffer.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value may be DDERR_INVALIDPARAMS or another error code.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.


IDirect3DVertexBuffer::Lock

The IDirect3DVertexBuffer::Lock methods locks a vertex buffer and obtains a pointer to the vertex buffer memory.

HRESULT Lock(
  DWORD   dwFlags,
  LPVOID* lplpData,
  LPDWORD lpdwSize
);

Parameters

dwFlags
Flags indicating how the vertex buffer memory should be locked.
DDLOCK_EVENT
This flag is not currently implemented.
DDLOCK_NOSYSLOCK
If possible, do not take the Win16Mutex (also known as Win16Lock).
DDLOCK_READONLY
Indicates that the memory being locked will only be read from.
DDLOCK_SURFACEMEMORYPTR
Indicates that a valid memory pointer to the vertex buffer should be returned; this is the default.
DDLOCK_WAIT
If a lock cannot be obtained immediately, the method retries until a lock is obtained or another error occurs.
DDLOCK_WRITEONLY
Indicates that the memory being locked will only be written to.
lplpData
Address of a variable that will contain the address of the vertex buffer memory if the call succeeds.
lpdwSize
Address of a variable that will contain the size of the vertex buffer memory at lplpData. Set to NULL if the buffer size is unneeded.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value may be one of the following values:

D3DERR_VERTEXBUFFEROPTIMIZED
DDERR_INVALIDPARAMS
DDERR_OUTOFMEMORY
DDERR_SURFACEBUSY
DDERR_SURFACELOST

Remarks

After locking the vertex buffer, you can access the memory until a corresponding call to IDirect3DVertexBuffer::Unlock.

You cannot render from a locked vertex buffer; calls to the IDirect3DDevice3::DrawIndexedPrimitiveVB or IDirect3DDevice3::DrawPrimitiveVB method using a locked buffer will fail, returning D3DERR_VERTEXBUFFERLOCKED.

This method often causes the system to hold the Win16Mutex until you call the IDirect3DVertexBuffer::Unlock method. GUI debuggers cannot operate while the Win16Mutex is held.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.

See Also

IDirect3DVertexBuffer::Unlock, Accessing Vertex Buffer Memory


IDirect3DVertexBuffer::Optimize

The IDirect3DVertexBuffer::Optimize method converts an unoptimized vertex buffer into an optimized vertex buffer.

HRESULT Optimize (
  LPDIRECT3DDEVICE3 lpD3DDevice,
  DWORD dwFlags
);

Parameters

lpD3DDevice
Address of the IDirect3DDevice3 interface of the device for which this vertex buffer will be optimized.
dwFlags
Not currently used; set to zero.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value may be one of the following values:

D3DERR_VERTEXBUFFEROPTIMIZED
D3DERR_VERTEXBUFFERLOCKED
DDERR_INVALIDPARAMS
DDERR_OUTOFMEMORY

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.

See Also

Optimizing a Vertex Buffer, Vertex Buffers


IDirect3DVertexBuffer::ProcessVertices

The IDirect3DVertexBuffer::ProcessVertices method processes untransformed vertices into a transformed or optimized vertex buffer.

HRESULT ProcessVertices(
  DWORD dwVertexOp,
  DWORD dwDestIndex,
  DWORD dwCount,
  LPDIRECT3DVERTEXBUFFER lpSrcBuffer,
  DWORD dwSrcIndex,
  LPDIRECT3DDEVICE3      lpD3DDevice,
  DWORD dwFlags
);

Parameters

dwVertexOp
Flags defining how the method processes the vertices as they are transferred from the source buffer. You can specify any combination of the following flags:
D3DVOP_CLIP
Transform the vertices and clip any vertices that exist outside the viewing frustum. This flag cannot be used with vertex buffers that do not contain clipping information (for example, created with the D3DDP_DONOTCLIP flag).
D3DVOP_EXTENTS
Transform the vertices, then update the extents of the screen rectangle when the vertices are rendered. Using this flag can potentially help performance, but the extents returned by IDirect3DDevice3::GetClipStatus will not have been updated to account for the vertices when they are rendered.
D3DVOP_LIGHT
Light the vertices.
D3DVOP_TRANSFORM
Transform the vertices using the world, view, and projection matrices. This flag must always be set.
dwDestIndex
Index into the destination vertex buffer (this buffer) where the vertices will be placed after processing.
dwCount
Number of vertices in the source buffer to process.
lpSrcBuffer
Address of the IDirect3DVertexBuffer interface for the source vertex buffer.
dwSrcIndex
Index of the first vertex in the source buffer to be processed.
lpD3DDevice
Address of the IDirect3DDevice3 interface for the device that will be used to transform the vertices.
dwFlags
Reserved for future use; set to zero. Failing to set this parameter to 0 causes the method to fail and return DDERR_INVALIDPARAMS.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value may be one of the following values:

D3DERR_INVALIDVERTEXFORMAT
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_OUTOFMEMORY
DDERR_SURFACEBUSY
DDERR_SURFACELOST

Remarks

You must always include the D3DVOP_TRANSFORMED flag in the dwVertexOp parameter. If you fail to include this flag, the method will fail, returning DDERR_INVALIDPARAMS.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.

See Also

Processing Vertices, Vertex Buffers


IDirect3DVertexBuffer::Unlock

The IDirect3DVertexBuffer::Unlock method unlocks a previously locked vertex buffer.

HRESULT Unlock();

Parameters

None.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value may be one of the following values:

DDERR_GENERIC
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_SURFACEBUSY
DDERR_SURFACELOST

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.

See Also

IDirect3DVertexBuffer::Lock, Accessing Vertex Buffer Memory


IDirect3DViewport3

Applications use the methods of the IDirect3DViewport3 interface to retrieve and set the properties of viewports. This section is a reference to the methods of this interface. For a conceptual overview, see Viewports and Clipping.

The IDirect3DViewport3 interface offers the same services as the IDirect3DViewport2 interface, but adds the Clear2 method, which simultaneously clears the viewport, depth-buffer, and stencil buffer.

You create the IDirect3DViewport3 interface by calling the IDirect3D3::CreateViewport method.

The methods of the IDirect3DViewport3 interface can be organized into the following groups:

Backgrounds | GetBackground
 | GetBackgroundDepth
 | GetBackgroundDepth2
 | SetBackground
 | SetBackgroundDepth
 | SetBackgroundDepth2
Lights | AddLight
 | DeleteLight
 | LightElements
 | NextLight
Materials and viewports | Clear
 | Clear2
 | GetViewport
 | GetViewport2
 | SetViewport
 | SetViewport2
Miscellaneous | Initialize
Transformation | TransformVertices

The IDirect3DViewport3 interface, like all COM interfaces, inherits the IUnknown interface methods. The IUnknown interface supports the following three methods:

IUnknown | AddRef
 | QueryInterface
 | Release

The LPDIRECT3DVIEWPORT3, LPDIRECT3DVIEWPORT2 and LPDIRECT3DVIEWPORT types are defined as pointers to the IDirect3DViewport3, IDirect3DViewport2, and IDirect3DViewport interfaces:

typedef struct IDirect3DViewport3    *LPDIRECT3DVIEWPORT3;
typedef struct IDirect3DViewport2    *LPDIRECT3DVIEWPORT2;
typedef struct IDirect3DViewport     *LPDIRECT3DVIEWPORT;

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.

See Also

Viewports and Clipping


IDirect3DViewport3::AddLight

The IDirect3DViewport3::AddLight method adds the specified light to the list of Direct3DLight objects associated with this viewport and increments the reference count of the light object.

HRESULT AddLight(
  LPDIRECT3DLIGHT lpDirect3DLight
);

Parameters

lpDirect3DLight
Address of the IDirect3DLight interface for the light that should be associated with this viewport.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value may be one of the following values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS

Remarks

This method is unchanged from its implementation in the IDirect3DViewport2 interface.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.


IDirect3DViewport3::Clear

The IDirect3DViewport3::Clear method clears the viewport or a set of rectangles in the viewport to the current background material.

HRESULT Clear(
  DWORD     dwCount,
  LPD3DRECT lpRects,
  DWORD     dwFlags
);

Parameters

dwCount
Number of rectangles pointed to by lpRects.
lpRects
Address of an array of D3DRECT structures. Each rectangle uses screen coordinates that correspond to points on the render target surface. Coordinates are clipped to the bounds of the viewport rectangle.
dwFlags
Flags indicating what to clear: the rendering target, the depth-buffer, or both.
D3DCLEAR_TARGET
Clear the rendering target to the background material (if set).
D3DCLEAR_ZBUFFER
Clear the depth-buffer or set it to the current background depth field (if set).

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value may be one of the following values:

D3DERR_VIEWPORTHASNODEVICE
D3DERR_ZBUFFER_NOTPRESENT
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS

Remarks

This method is unchanged from its implementation in the IDirect3DViewport2 interface.

The behavior of this method is undefined for depth buffers that include stencil bits, and using this method on such a depth buffer can cause the stencil bits to be arbitrarily overwritten or the depth values to be incorrect. Always use the use the IDirect3DViewport3::Clear2 method to clear depth buffers that contain stencil bits.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.

See Also

IDirect3DViewport3::Clear2


IDirect3DViewport3::Clear2

The IDirect3DViewport3::Clear2 method clears the viewport (or a set of rectangles in the viewport) to a specified RGBA color, clears the depth-buffer, and erases the stencil buffer.

HRESULT Clear2(
  DWORD     dwCount,
  LPD3DRECT lpRects,
  DWORD     dwFlags,
  DWORD     dwColor,
  D3DVALUE  dvZ,
  DWORD     dwStencil
);

Parameters

dwCount
Number of rectangles in the array at lpRects.
lpRects
Array of D3DRECT structures that describe the rectangles to be cleared. Set a rectangle to the dimensions of the rendering target to clear the entire surface. Each rectangle uses screen coordinates that correspond to points on the render target surface. Coordinates are clipped to the bounds of the viewport rectangle.
dwFlags
Flags indicating which surfaces should be cleared. This parameter can be any combination of the following flags, but at least one flag must be used:
D3DCLEAR_TARGET
Clear the rendering target to the color in the dwColor parameter.
D3DCLEAR_STENCIL
Clear the stencil buffer to the value in the dwStencil parameter.
D3DCLEAR_ZBUFFER
Clear the depth-buffer to the value in the dvZ parameter.
dwColor
32-bit RGBA color value to which the render target surface will be cleared.
dvZ
New z value that this method stores in the depth-buffer. This parameter can range from 0.0 to 1.0, inclusive. The value of 0.0 represents the nearest distance to the viewer, and 1.0 the farthest distance.
dwStencil
Integer value to store in each stencil buffer entry. This parameter can range from 0 to 2n-1 inclusive, where n is the bit depth of the stencil buffer.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value may be one of the following values:

D3DERR_STENCILBUFFER_NOTPRESENT
D3DERR_VIEWPORTHASNODEVICE
D3DERR_ZBUFFER_NOTPRESENT
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS

Remarks

This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the render target does not have an attached depth-buffer. This behavior differs from the IDirect3DViewport3::Clear method, which will succeed if under these circumstances.

If you specify the D3DCLEAR_STENCIL flag when the depth-buffer format doesn't contain stencil buffer information, this method fails.

This method ignores the current background material for the viewport; to clear a viewport using the background material, use the IDirect3DViewport3::Clear method.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.

See Also

IDirect3DViewport3::Clear


IDirect3DViewport3::DeleteLight

The IDirect3DViewport3::DeleteLight method removes the specified light from the list of Direct3DLight objects associated with this viewport, and decrements the reference count for the light object.

HRESULT DeleteLight(
  LPDIRECT3DLIGHT lpDirect3DLight
);

Parameters

lpDirect3DLight
Address of the IDirect3DLight interface for the light that should be disassociated with this viewport.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value may be one of the following values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS

Remarks

This method is unchanged from its implementation in the IDirect3DViewport2 interface.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.


IDirect3DViewport3::GetBackground

The IDirect3DViewport3::GetBackground method retrieves the handle to a material that represents the current background associated with the viewport.

HRESULT GetBackground(
  LPD3DMATERIALHANDLE lphMat,
  LPBOOL lpValid
);

Parameters

lphMat
Address that will contain the handle to the material being used as the background.
lpValid
Address of a variable that will be filled to indicate whether a background is associated with the viewport. If this parameter is FALSE, no background is associated with the viewport.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value may be one of the following values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS

Remarks

This method is unchanged from its implementation in the IDirect3DViewport2 interface.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.

See Also

IDirect3DViewport3::SetBackground


IDirect3DViewport3::GetBackgroundDepth

The IDirect3DViewport3::GetBackgroundDepth method retrieves a DirectDraw surface that represents the current background-depth field associated with the viewport.

HRESULT GetBackgroundDepth(
  LPDIRECTDRAWSURFACE* lplpDDSurface,
  LPBOOL lpValid
);

Parameters

lplpDDSurface
Address of a variable that will be filled with the IDirectDrawSurface interface for the surface object that represents the background depth.
lpValid
Address of a variable that is set to FALSE if no background depth is associated with the viewport.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value may be one of the following values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS

Remarks

This method is unchanged from its implementation in the IDirect3DViewport2 interface.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.

See Also

IDirect3DViewport3::SetBackgroundDepth


IDirect3DViewport3::GetBackgroundDepth2

The IDirect3DViewport3::GetBackgroundDepth2 method retrieves a DirectDraw surface that represents the current background-depth field associated with the viewport.

HRESULT GetBackgroundDepth2(
  LPDIRECTDRAWSURFACE4* lplpDDS,
  LPBOOL lpValid
);

Parameters

lplpDDS
Address of a variable that will be filled with the IDirectDrawSurface4 interface for the surface object that represents the background depth.
lpValid
Address of a variable that is set to FALSE if no background depth is associated with the viewport.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value may be one of the following values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.

See Also

IDirect3DViewport3::SetBackgroundDepth2


IDirect3DViewport3::GetViewport

The IDirect3DViewport3::GetViewport method retrieves the viewport registers of the viewport. This method is provided for backward compatibility. It has been superseded by the IDirect3DViewport3::GetViewport2 method.

HRESULT GetViewport(
  LPD3DVIEWPORT lpData
);

Parameters

lpData
Address of a D3DVIEWPORT structure representing the viewport.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value may be one of the following values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS

Remarks

This method is unchanged from its implementation in the IDirect3DViewport2 interface.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.

See Also

IDirect3DViewport3::GetViewport2, IDirect3DViewport3::SetViewport


IDirect3DViewport3::GetViewport2

The IDirect3DViewport3::GetViewport2 method retrieves the viewport registers of the viewport.

HRESULT GetViewport2(
  LPD3DVIEWPORT2 lpData
);

Parameters

lpData
Address of a D3DVIEWPORT2 structure representing the viewport.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value may be one of the following values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.

See Also

IDirect3DViewport3::SetViewport2


IDirect3DViewport3::Initialize

The IDirect3DViewport3::Initialize method is not implemented.

HRESULT Initialize(
  LPDIRECT3D lpDirect3D
);

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.


IDirect3DViewport3::LightElements

The IDirect3DViewport3::LightElements method is not currently implemented.

HRESULT LightElements(
  DWORD dwElementCount,
  LPD3DLIGHTDATA lpData
);

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.


IDirect3DViewport3::NextLight

The IDirect3DViewport3::NextLight method enumerates the Direct3DLight objects associated with the viewport.

HRESULT NextLight(
  LPDIRECT3DLIGHT lpDirect3DLight,
  LPDIRECT3DLIGHT* lplpDirect3DLight,
  DWORD dwFlags
);

Parameters

lpDirect3DLight
Address of a light in the list of lights associated with this viewport object.
lplpDirect3DLight
Address of a pointer that will contain the requested light in the list of lights associated with this viewport object. The requested light is specified in the dwFlags parameter.
dwFlags
Flags specifying which light to retrieve from the list of lights. This must be set to one of the following flags:
D3DNEXT_HEAD
Retrieve the item at the beginning of the list.
D3DNEXT_NEXT
Retrieve the next item in the list.
D3DNEXT_TAIL
Retrieve the item at the end of the list.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value may be one of the following values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS

Remarks

This method is unchanged from its implementation in the IDirect3DViewport2 interface.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.


IDirect3DViewport3::SetBackground

The IDirect3DViewport3::SetBackground method sets the background material associated with the viewport.

HRESULT SetBackground(
  D3DMATERIALHANDLE hMat
);

Parameters

hMat
Material handle that will be used as the background.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value may be one of the following values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS

Remarks

This method is unchanged from its implementation in the IDirect3DViewport2 interface.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.

See Also

IDirect3DViewport3::GetBackground


IDirect3DViewport3::SetBackgroundDepth

The IDirect3DViewport3::SetBackgroundDepth method sets the background-depth field for the viewport.

HRESULT SetBackgroundDepth(
  LPDIRECTDRAWSURFACE lpDDSurface
);

Parameters

lpDDSurface
Address of the DirectDrawSurface object representing the background depth.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value may be one of the following values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS

Remarks

The depth-buffer is filled with the specified depth field when the IDirect3DViewport3::Clear method is called and the D3DCLEAR_ZBUFFER flag is specified. The bit depth must be 16 bits.

This method is unchanged from its implementation in the IDirect3DViewport2 interface.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.

See Also

IDirect3DViewport3::GetBackgroundDepth


IDirect3DViewport3::SetBackgroundDepth2

The IDirect3DViewport3::SetBackgroundDepth2 method sets the background-depth field for the viewport.

HRESULT SetBackgroundDepth2(
  LPDIRECTDRAWSURFACE4 lpDDS
);

Parameters

lpDDS
Address of the IDirectDrawSurface4 interface for the surface object that represents the new background depth.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value may be one of the following values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS

Remarks

The depth-buffer is filled with the specified depth field when the IDirect3DViewport3::Clear or IDirect3DViewport3::Clear2 methods are called with the D3DCLEAR_ZBUFFER flag is specified.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.

See Also

IDirect3DViewport3::GetBackgroundDepth2


IDirect3DViewport3::SetViewport

The IDirect3DViewport3::SetViewport method sets the viewport registers of the viewport. This method is provided for backward compatibility. It has been superseded by the IDirect3DViewport3::SetViewport2 method.

HRESULT SetViewport(
  LPD3DVIEWPORT lpData
);

Parameters

lpData
Address of a D3DVIEWPORT structure that describces the new viewport properties. The method ignores the values in the dvMaxX, dvMaxY, dvMinZ, and dvMaxZ members.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value may be one of the following values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS

Remarks

This method is unchanged from its implementation in the IDirect3DViewport2 interface.

You cannot set viewport parameters unless the viewport is associated with a rendering device (by calling the IDirect3DDevice3::AddViewport method). For details, see Preparing to Use a Viewport.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.

See Also

IDirect3DViewport3::GetViewport, IDirect3DViewport3::SetViewport2, Using Viewports, Viewports and Clipping


IDirect3DViewport3::SetViewport2

The IDirect3DViewport3::SetViewport2 method sets the viewport registers of the viewport.

HRESULT SetViewport2(
  LPD3DVIEWPORT2 lpData
);

Parameters

lpData
Address of a D3DVIEWPORT2 structure that contains the new viewport.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value may be one of the following values:

D3DERR_VIEWPORTHASNODEVICE
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS

Remarks

You cannot set viewport parameters unless the viewport is associated with a rendering device (by calling the IDirect3DDevice3::AddViewport method). For details, see Preparing to Use a Viewport.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.

See Also

IDirect3DViewport3::GetViewport2, Using Viewports, Viewports and Clipping


IDirect3DViewport3::TransformVertices

The IDirect3DViewport3::TransformVertices method transforms a set of vertices by the transformation matrix.

HRESULT TransformVertices(
  DWORD dwVertexCount,
  LPD3DTRANSFORMDATA lpData,
  DWORD dwFlags,
  LPDWORD lpOffscreen
);

Parameters

dwVertexCount
Number of vertices in the lpData parameter to be transformed.
lpData
Address of a D3DTRANSFORMDATA structure that contains the vertices to be transformed. See Remarks.
dwFlags
One of the following flags. See the comments section following the parameter description for a discussion of how to use these flags.

D3DTRANSFORM_CLIPPED
D3DTRANSFORM_UNCLIPPED

lpOffscreen
Address of a variable that is set to a nonzero value if the resulting vertices are all off-screen.

Return Values

If the method succeeds, the return value is D3D_OK.

If the method fails, the return value may be one of the following values:

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS

Remarks

This method has often be used to perform visibility checking, as it returns clipping information in the D3DTRANSFORMDATA structure after the call completes. Although the clipping information is accurate, visibility checking is best performed by calling the IDirect3DDevice3::ComputeSphereVisibility method, which was specially designed and optimized for this purpose.

If the dwFlags parameter is set to D3DTRANSFORM_CLIPPED, this method uses the current transformation matrix to transform a set of vertices, checking the resulting vertices to see if they are within the viewing frustum. The homogeneous part of the D3DTLVERTEX structure within lpData will be set if the vertex is clipped; otherwise only the screen coordinates will be set. The clip intersection of all the vertices transformed is returned in lpOffscreen. That is, if lpOffscreen is nonzero, all the vertices were off-screen and not straddling the viewport.

Initialize the drExtent member of the D3DTRANSFORMDATA structure to a D3DRECT structure that describes a 2-D bounding rectangle (extents) that the method will "grow" if the transformed vertices do not fit within it. If the transformed vertices are outside the provided extents, the method adjusts the extents to fit the vertices, otherwise no changes are made. If the dwFlags parameter is set to D3DTRANSFORM_UNCLIPPED, this method transforms the vertices assuming that the resulting coordinates will be within the viewing frustum. If clipping is requested by setting the dwFlags parameter to D3DTRANSFORM_CLIPPED, the method adjusts the extents to fit only the transformed vertices that are within the viewing area.

The dwClip member of D3DTRANSFORMDATA can help the transformation module determine whether the geometry will need clipping against the viewing volume. Before transforming a geometry, high-level software often can test whether bounding boxes or bounding spheres are wholly within the viewing volume, allowing clipping tests to be skipped, or wholly outside the viewing volume, allowing the geometry to be skipped entirely.

This method is unchanged from its implementation in the IDirect3DViewport2 interface.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.
Import Library: Use ddraw.lib.


Unimplemented Methods

The following methods were stubs in previous versions of DirectX, but are not implemented in the most recent versions of their interfaces.

IDirect3D::Initialize

IDirect3DMaterial::Initialize

IDirect3DMaterial::Reserve

IDirect3DMaterial::Unreserve

IDirect3DTexture::Initialize

IDirect3DTexture::Unload


D3D_OVERLOADS

C++ programmers who define D3D_OVERLOADS can use the extensions documented here to simplify their code in Direct3D Immediate Mode applications. The use of D3D_OVERLOADS was introduced with DirectX® 5.0. This section is a reference to the D3D_OVERLOADS extensions.

These extensions must be defined with C++ linkage. If D3D_OVERLOADS is defined and the inclusion of D3dtypes.h or D3d.h is surrounded by extern "C", link errors will result. For example, the following syntax would generate link errors because of C linkage of D3D_OVERLOADS functionality:

#define D3D_OVERLOADS
extern "C" {
#include <d3d.h>
};

The D3D_OVERLOADS extensions can be organized into the following groups:

Constructors | D3DLVERTEX
 | D3DTLVERTEX
 | D3DVECTOR
 | D3DVERTEX
Operators | Access Grant Operators
 | Addition Operator
 | Assignment Operators
 | Bitwise Equality Operator
 | D3DMATRIX
 | Division Operator
 | Multiplication Operator
 | Subtraction Operator
 | Unary Operators
 | Vector Dominance Operators
Helper functions | CrossProduct
 | DotProduct
 | Magnitude
 | Max
 | Maximize
 | Min
 | Minimize
 | Normalize
 | SquareMagnitude


D3D_OVERLOADS Constructors

This section contains reference information for the constructors provided by the D3D_OVERLOADS C++ extensions.

  • D3DLVERTEX
  • D3DTLVERTEX
  • D3DVECTOR
  • D3DVERTEX

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.


D3DLVERTEX Constructors

The D3D_OVERLOADS constructors for the D3DLVERTEX structure offer a convenient way for C++ programmers to create lit vertices.

_D3DLVERTEX() { }
_D3DLVERTEX(const D3DVECTOR& v,
            D3DCOLOR _color, D3DCOLOR _specular,
            float _tu, float _tv)
    { x = v.x; y = v.y; z = v.z; dwReserved = 0;
      color = _color; specular = _specular;
      tu = _tu; tv = _tv;
    }

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.


D3DTLVERTEX Constructors

The D3D_OVERLOADS constructors for the D3DTLVERTEX structure offer a convenient way for C++ programmers to create transformed and lit vertices.

_D3DTLVERTEX() { }
_D3DTLVERTEX(const D3DVECTOR& v, float _rhw,
             D3DCOLOR _color, D3DCOLOR _specular,
             float _tu, float _tv)
    { sx = v.x; sy = v.y; sz = v.z; rhw = _rhw;
      color = _color; specular = _specular;
      tu = _tu; tv = _tv;
    }

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.


D3DVECTOR Constructors

The D3D_OVERLOADS constructors for the D3DVECTOR structure offer a convenient way for C++ programmers to create vectors.

_D3DVECTOR() { }
_D3DVECTOR(D3DVALUE f);
_D3DVECTOR(D3DVALUE _x, D3DVALUE _y, D3DVALUE _z);
_D3DVECTOR(const D3DVALUE f[3]);

These constructors are defined as follows:

inline _D3DVECTOR::_D3DVECTOR(D3DVALUE f)
    {    x = y = z = f; }

inline _D3DVECTOR::_D3DVECTOR(D3DVALUE _x, D3DVALUE _y, D3DVALUE _z)
    {     x = _x; y = _y; z = _z; }

inline _D3DVECTOR::_D3DVECTOR(const D3DVALUE f[3])
    {     x = f[0]; y = f[1]; z = f[2]; }

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.


D3DVERTEX Constructors

The D3D_OVERLOADS constructors for the D3DVERTEX structure offer a convenient way for C++ programmers to create lit vertices.

_D3DVERTEX() { }
_D3DVERTEX(const D3DVECTOR& v, const D3DVECTOR& n, float _tu, float _tv)
    { x = v.x; y = v.y; z = v.z;
      nx = n.x; ny = n.y; nz = n.z;
      tu = _tu; tv = _tv;
    }

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.


D3D_OVERLOADS Operators

This section contains reference information for the operators provided by the D3D_OVERLOADS C++ extensions.

  • Access Grant Operators
  • Addition Operator
  • Assignment Operators
  • Bitwise Equality Operator
  • D3DMATRIX
  • Division Operator
  • Multiplication Operator
  • Subtraction Operator
  • Unary Operators
  • Vector Dominance Operators

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.


Access Grant Operators (D3D_OVERLOADS)

The bracket ("[ ]") operators are overloaded operators for the D3D_OVERLOADS extensions. You can use empty brackets ("[ ]") for access grants, "v[0]" to access the x component of a vector, "v[1]" to access the y component, and "v[2]" to access the z component. These operators are defined as follows:

const D3DVALUE&operator[ ](int i) const;
D3DVALUE&operator[ ](int i);

inline const D3DVALUE&
_D3DVECTOR::operator[ ](int i) const
{
    return (&x)[i];
}

inline D3DVALUE&
_D3DVECTOR::operator[ ](int i)
{
    return (&x)[i];
}

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.


Addition Operator (D3D_OVERLOADS)

This binary operator is an overloaded operator for the D3D_OVERLOADS extensions. The addition operator is defined as follows:

_D3DVECTOR operator + (const _D3DVECTOR& v1, const _D3DVECTOR& v2);

inline _D3DVECTOR
operator + (const _D3DVECTOR& v1, const _D3DVECTOR& v2)
{
   return _D3DVECTOR(v1.x+v2.x, v1.y+v2.y, v1.z+v2.z);
}

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.


Assignment Operators (D3D_OVERLOADS)

The assignment operators are overloaded operators for the D3D_OVERLOADS extensions. Both scalar and vector forms of the "*=" and "/=" operators have been implemented. (In the vector form, multiplication and division are memberwise.)

_D3DVECTOR& operator += (const _D3DVECTOR& v);
_D3DVECTOR& operator -= (const _D3DVECTOR& v);
_D3DVECTOR& operator *= (const _D3DVECTOR& v);
_D3DVECTOR& operator /= (const _D3DVECTOR& v);
_D3DVECTOR& operator *= (D3DVALUE s);
_D3DVECTOR& operator /= (D3DVALUE s);

The assignment operators are defined as follows:

inline _D3DVECTOR&
_D3DVECTOR::operator += (const _D3DVECTOR& v)
{
   x += v.x;   y += v.y;   z += v.z;
   return *this;
}

inline _D3DVECTOR&
_D3DVECTOR::operator -= (const _D3DVECTOR& v)
{
   x -= v.x;   y -= v.y;   z -= v.z;
   return *this;
}

inline _D3DVECTOR&
_D3DVECTOR::operator *= (const _D3DVECTOR& v)
{
   x *= v.x;   y *= v.y;   z *= v.z;
   return *this;
}

inline _D3DVECTOR&
_D3DVECTOR::operator /= (const _D3DVECTOR& v)
{
   x /= v.x;   y /= v.y;   z /= v.z;
   return *this;
}

inline _D3DVECTOR&
_D3DVECTOR::operator *= (D3DVALUE s)
{
   x *= s;   y *= s;   z *= s;
   return *this;
}

inline _D3DVECTOR&
_D3DVECTOR::operator /= (D3DVALUE s)
{
   x /= s;   y /= s;   z /= s;
   return *this;
}

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.


Bitwise Equality Operator (D3D_OVERLOADS)

This binary operator is an overloaded operator for the D3D_OVERLOADS extensions. The bitwise-equality operator is defined as follows:

int operator == (const _D3DVECTOR& v1, const _D3DVECTOR& v2);

inline int
operator == (const _D3DVECTOR& v1, const _D3DVECTOR& v2)
{
   return v1.x==v2.x && v1.y==v2.y && v1.z == v2.z;
}

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.


D3DMATRIX (D3D_OVERLOADS)

The D3D_OVERLOADS implementation of the D3DMATRIX structure implements a parentheses ("()") operator. This operator offers convenient access to values in the matrix for C++ programmers. Instead of having to refer to the structure members by name, C++ programmers can refer to them by row and column number, and simply index these numbers as needed.

typedef struct _D3DMATRIX {
#if (defined __cplusplus) && (defined D3D_OVERLOADS)
    union {
        struct {
#endif

            D3DVALUE        _11, _12, _13, _14;
            D3DVALUE        _21, _22, _23, _24;
            D3DVALUE        _31, _32, _33, _34;
            D3DVALUE        _41, _42, _43, _44;

#if (defined __cplusplus) && (defined D3D_OVERLOADS)
        };
        D3DVALUE m[4][4];
    };
    _D3DMATRIX() { }

    D3DVALUE& operator()(int iRow, int iColumn) { return m[iRow][iColumn]; }
    const D3DVALUE& operator()(int iRow, int iColumn) const { return m[iRow][iColumn]; }
#endif
} D3DMATRIX, *LPD3DMATRIX;

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.

See Also

D3DMATRIX


Division Operator (D3D_OVERLOADS)

This binary operator is an overloaded operator for the D3D_OVERLOADS extensions. Both scalar and vector forms of this operator have been implemented. The division operator is defined as follows:

_D3DVECTOR operator / (const _D3DVECTOR& v, D3DVALUE s);
_D3DVECTOR operator / (const _D3DVECTOR& v1, const _D3DVECTOR& v2);

inline _D3DVECTOR
operator / (const _D3DVECTOR& v1, const _D3DVECTOR& v2)
{
   return _D3DVECTOR(v1.x/v2.x, v1.y/v2.y, v1.z/v2.z);
}

inline _D3DVECTOR
operator / (const _D3DVECTOR& v, D3DVALUE s)
{
   return _D3DVECTOR(v.x/s, v.y/s, v.z/s);
}

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.


Multiplication Operator (D3D_OVERLOADS)

This binary operator is an overloaded operator for the D3D_OVERLOADS extensions. Both scalar and vector forms of this operator have been implemented. The multiplication operator is defined as follows:

_D3DVECTOR operator * (const _D3DVECTOR& v, D3DVALUE s);
_D3DVECTOR operator * (D3DVALUE s, const _D3DVECTOR& v);
_D3DVECTOR operator * (const _D3DVECTOR& v1, const _D3DVECTOR& v2);

inline _D3DVECTOR
operator * (const _D3DVECTOR& v1, const _D3DVECTOR& v2)
{
   return _D3DVECTOR(v1.x*v2.x, v1.y*v2.y, v1.z*v2.z);
}

inline _D3DVECTOR
operator * (const _D3DVECTOR& v, D3DVALUE s)
{
   return _D3DVECTOR(s*v.x, s*v.y, s*v.z);
}

inline _D3DVECTOR
operator * (D3DVALUE s, const _D3DVECTOR& v)
{
   return _D3DVECTOR(s*v.x, s*v.y, s*v.z);
}

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.


Subtraction Operator (D3D_OVERLOADS)

This binary operator is an overloaded operator for the D3D_OVERLOADS extensions. The subtraction operator is defined as follows:

_D3DVECTOR operator - (const _D3DVECTOR& v1, const _D3DVECTOR& v2);

inline _D3DVECTOR
operator - (const _D3DVECTOR& v1, const _D3DVECTOR& v2)
{
   return _D3DVECTOR(v1.x-v2.x, v1.y-v2.y, v1.z-v2.z);
}

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.


Unary Operators (D3D_OVERLOADS)

The unary operators are overloaded operators for the D3D_OVERLOADS extensions. The unary operators are defined as follows:

_D3DVECTOR operator + (const _D3DVECTOR& v);
_D3DVECTOR operator - (const _D3DVECTOR& v);

inline _D3DVECTOR
operator + (const _D3DVECTOR& v)
{
   return v;
}

inline _D3DVECTOR
operator - (const _D3DVECTOR& v)
{
   return _D3DVECTOR(-v.x, -v.y, -v.z);
}

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.


Vector Dominance Operators (D3D_OVERLOADS)

These binary operators are overloaded operators for the D3D_OVERLOADS extensions. Vector v1 dominates vector v2 if any component of v1 is greater than the corresponding component of v2. Therefore, it is possible for neither of the two specified vectors to dominate the other.

int operator < (const _D3DVECTOR& v1, const _D3DVECTOR& v2);
int operator <= (const _D3DVECTOR& v1, const _D3DVECTOR& v2);

The vector-dominance operators are defined as follows:

inline int
operator < (const _D3DVECTOR& v1, const _D3DVECTOR& v2)
{
   return v1[0] < v2[0] && v1[1] < v2[1] && v1[2] < v2[2];
}

inline int
operator <= (const _D3DVECTOR& v1, const _D3DVECTOR& v2)
{
   return v1[0] <= v2[0] && v1[1] <= v2[1] && v1[2] <= v2[2];
}

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.


D3D_OVERLOADS Helper Functions

This section contains reference information for the helper functions provided by the D3D_OVERLOADS C++ extensions.

  • CrossProduct
  • DotProduct
  • Magnitude
  • Max
  • Maximize
  • Min
  • Minimize
  • Normalize
  • SquareMagnitude

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.


CrossProduct

This helper function returns the cross product of the specified vectors. CrossProduct is part of the suite of extra functionality that is available to C++ programmers who define D3D_OVERLOADS.

_D3DVECTOR CrossProduct (const _D3DVECTOR& v1, const _D3DVECTOR& v2);

This function is defined as follows:

inline _D3DVECTOR
CrossProduct (const _D3DVECTOR& v1, const _D3DVECTOR& v2)
{
    _D3DVECTOR result;

    result[0] = v1[1] * v2[2] - v1[2] * v2[1];
    result[1] = v1[2] * v2[0] - v1[0] * v2[2];
    result[2] = v1[0] * v2[1] - v1[1] * v2[0];

    return result;
}

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.

See Also

DotProduct


DotProduct

This helper function returns the dot product of the specified vectors. DotProduct is part of the suite of extra functionality that is available to C++ programmers who define D3D_OVERLOADS.

D3DVALUE DotProduct (const _D3DVECTOR& v1, const _D3DVECTOR& v2);

This function is defined as follows:

inline D3DVALUE
DotProduct (const _D3DVECTOR& v1, const _D3DVECTOR& v2)
{
   return v1.x*v2.x + v1.y * v2.y + v1.z*v2.z;
}

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.

See Also

CrossProduct


Magnitude

This helper function returns the absolute value of the specified vector. Magnitude is part of the suite of extra functionality that is available to C++ programmers who define D3D_OVERLOADS.

D3DVALUE Magnitude (const _D3DVECTOR& v);

This function is defined as follows:

inline D3DVALUE
Magnitude (const _D3DVECTOR& v)
{
   return (D3DVALUE) sqrt(SquareMagnitude(v));
}

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.

See Also

SquareMagnitude


Max

This helper function returns the maximum component of the specified vector. Max is part of the suite of extra functionality that is available to C++ programmers who define D3D_OVERLOADS.

D3DVALUE Max (const _D3DVECTOR& v);

This function is defined as follows:

inline D3DVALUE
Max (const _D3DVECTOR& v)
{
   D3DVALUE ret = v.x;
   if (ret < v.y) ret = v.y;
   if (ret < v.z) ret = v.z;
   return ret;
}

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.

See Also

Min


Maximize

This helper function returns a vector that is made up of the largest components of the two specified vectors. Maximize is part of the suite of extra functionality that is available to C++ programmers who define D3D_OVERLOADS.

_D3DVECTOR Maximize (const _D3DVECTOR& v1, const _D3DVECTOR& v2);

This function is defined as follows:

inline _D3DVECTOR
Maximize (const _D3DVECTOR& v1, const _D3DVECTOR& v2)
{
   return _D3DVECTOR( v1[0] > v2[0] ? v1[0] : v2[0],
                      v1[1] > v2[1] ? v1[1] : v2[1],
                      v1[2] > v2[2] ? v1[2] : v2[2]);
}

Remarks

You could use the Maximize and Minimize functions to compute the bounding box for a set of points, in a function that looks like this:

    void
    ComputeBoundingBox(const D3DVECTOR *pts, int N, D3DVECTOR *min, D3DVECTOR *max)
    {
        int i;
        *min = *max = pts[0];
        for (i = 1; i < N; i += 1)
        {
            *min = Minimize(*min, pts[i]);
            *max = Maximize(*max, pts[i]);
        }
    }

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.

See Also

Minimize


Min

This helper function returns the minimum component of the specified vector. Min is part of the suite of extra functionality that is available to C++ programmers who define D3D_OVERLOADS.

D3DVALUE Min (const _D3DVECTOR& v);

This function is defined as follows:

inline D3DVALUE
Min (const _D3DVECTOR& v)
{
   D3DVALUE ret = v.x;
   if (v.y < ret) ret = v.y;
   if (v.z < ret) ret = v.z;
   return ret;
}

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.

See Also

Max


Minimize

This helper function returns a vector that is made up of the smallest components of the two specified vectors. Minimize is part of the suite of extra functionality that is available to C++ programmers who define D3D_OVERLOADS.

_D3DVECTOR Minimize (const _D3DVECTOR& v1, const _D3DVECTOR& v2);

This function is defined as follows:

inline _D3DVECTOR
Minimize (const _D3DVECTOR& v1, const _D3DVECTOR& v2)
{
   return _D3DVECTOR( v1[0] < v2[0] ? v1[0] : v2[0],
                      v1[1] < v2[1] ? v1[1] : v2[1],
                      v1[2] < v2[2] ? v1[2] : v2[2]);
}

Remarks

You could use the Maximize and Minimize functions to compute the bounding box for a set of points, in a function that looks like this:

    void
    ComputeBoundingBox(const D3DVECTOR *pts, int N, D3DVECTOR *min, D3DVECTOR *max)
    {
        int i;
        *min = *max = pts[0];
        for (i = 1; i < N; i += 1)
        {
            *min = Minimize(*min, pts[i]);
            *max = Maximize(*max, pts[i]);
        }
    }

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.

See Also

Maximize


Normalize

This helper function returns the normalized version of the specified vector (that is, a unit-length vector with the same direction as the source). Normalize is part of the suite of extra functionality that is available to C++ programmers who define D3D_OVERLOADS.

_D3DVECTOR Normalize (const _D3DVECTOR& v);

This function is defined as follows:

inline _D3DVECTOR
Normalize (const _D3DVECTOR& v)
{
   return v / Magnitude(v);
}

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.


SquareMagnitude

This helper function returns the square of the absolute value of the specified vector. SquareMagnitude is part of the suite of extra functionality that is available to C++ programmers who define D3D_OVERLOADS.

D3DVALUE SquareMagnitude (const _D3DVECTOR& v);

This function is defined as follows:

inline D3DVALUE
SquareMagnitude (const _D3DVECTOR& v)
{
   return v.x*v.x + v.y*v.y + v.z*v.z;
}

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3d.h.

See Also

Magnitude


Callback Functions

This section contains reference information for the callback functions you may need to implement when you work with Direct3D Immediate Mode.

  • D3DEnumDevicesCallback
  • D3DEnumPixelFormatsCallback
  • D3DEnumTextureFormatsCallback
  • D3DValidateCallback


D3DEnumDevicesCallback

The D3DEnumDevicesCallback is an application-defined callback function for the IDirect3D3::EnumDevices method.

HRESULT CALLBACK D3DEnumDevicesCallback(
  GUID FAR* lpGuid,
  LPSTR lpDeviceDescription,
  LPSTR lpDeviceName,
  LPD3DDEVICEDESC lpD3DHWDeviceDesc,
  LPD3DDEVICEDESC lpD3DHELDeviceDesc,
  LPVOID lpContext
);

Parameters

lpGuid
Address of a globally unique identifier (GUID) that identifies a Direct3D device.
lpDeviceDescription
Address of a textual description of the device.
lpDeviceName
Address of the device name.
lpD3DHWDeviceDesc
Address of a D3DDEVICEDESC structure that contains the hardware capabilities of the Direct3D device.
lpD3DHELDeviceDesc
Address of a D3DDEVICEDESC structure that contains the emulated capabilities of the Direct3D device.
lpContext
Address of application-defined data passed to this callback function.

Return Values

Applications should return D3DENUMRET_OK to continue the enumeration, or D3DENUMRET_CANCEL to cancel it.

Remarks

When determining the order in which to call callback functions, the system searches the objects highest in the hierarchy first, and then calls their callback functions in the order in which they were created.

The LPD3DENUMDEVICESCALLBACK data type is defined as a pointer to this callback function:

typedef HRESULT (FAR PASCAL * LPD3DENUMDEVICESCALLBACK)(
  GUID FAR *lpGuid, LPSTR lpDeviceDescription, LPSTR lpDeviceName,
  LPD3DDEVICEDESC, LPD3DDEVICEDESC, LPVOID);

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dcaps.h.
Import Library: User-defined.


D3DEnumPixelFormatsCallback

The D3DEnumPixelFormatsCallback is an application-defined callback function for the IDirect3D3::EnumZBufferFormats, and IDirect3DDevice3::EnumTextureFormats methods.

HRESULT CALLBACK D3DEnumPixelFormatsCallback(
  LPDDPIXELFORMAT lpDDPixFmt,
  LPVOID          lpContext
);

Parameters

lpDDPixFmt
Address of a DDPIXELFORMAT structure that describes the enumerated pixel format.
lpContext
Address of application-defined data passed to the function by the caller.

Return Values

Applications should return D3DENUMRET_OK to continue the enumeration, or D3DENUMRET_CANCEL to cancel it.

Remarks

The LPD3DENUMPIXELFORMATSCALLBACK data type is defined as a pointer to this callback function:

typedef HRESULT (WINAPI* LPD3DENUMPIXELFORMATSCALLBACK)(LPDDPIXELFORMAT lpDDPixFmt, LPVOID lpContext);

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dcaps.h.
Import Library: User-defined.


D3DEnumTextureFormatsCallback

The D3DEnumTextureFormatsCallback function is an application-defined callback function for the IDirect3DDevice::EnumTextureFormats and IDirect3DDevice2::EnumTextureFormats methods.

HRESULT CALLBACK D3DEnumTextureFormatsCallback(
  LPDDSURFACEDESC lpDdsd,
  LPVOID lpUserArg
);

Parameters

lpDdsd
Address of a DDSURFACEDESC structure containing the texture information.
lpUserArg
Address of application-defined data passed to this callback function.

Return Values

Applications should return D3DENUMRET_OK to continue the enumeration, or D3DENUMRET_CANCEL to cancel it.

Remarks

When determining the order in which to call callback functions, the system searches the objects highest in the hierarchy first, and then calls their callback functions in the order in which they were created.

The LPD3DENUMTEXTUREFORMATSCALLBACK data type is defined as a pointer to this callback function:

typedef HRESULT (WINAPI* LPD3DENUMTEXTUREFORMATSCALLBACK)(LPDDSURFACEDESC lpDdsd, LPVOID lpContext);

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.
Import Library: User-defined.


D3DValidateCallback

The D3DValidateCallback function is an application-defined callback function for the IDirect3DExecuteBuffer::Validate method. The IDirect3DExecuteBuffer::Validate method is not currently implemented.

IDirect3DExecuteBuffer::Validate is a debugging routine that checks the execute buffer and returns an offset into the buffer when any errors are encountered.

HRESULT CALLBACK D3DValidateCallback(
  LPVOID lpUserArg,
  DWORD dwOffset
);

Parameters

lpUserArg
Address of application-defined data passed to this callback function.
dwOffset
Offset into the execute buffer at which the system found an error.

Return Values

Applications should return D3DENUMRET_OK to continue the enumeration, or D3DENUMRET_CANCEL to cancel it.

Remarks

When determining the order in which to call callback functions, the system searches the objects highest in the hierarchy first, and then calls their callback functions in the order in which they were created.

The LPD3DVALIDATECALLBACK data type is defined as a pointer to this callback function:

typedef HRESULT (WINAPI* LPD3DVALIDATECALLBACK)(LPVOID lpUserArg, DWORD dwOffset);

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.
Import Library: User-defined.


Macros

This section contains reference information for the macros provided by Direct3D Immediate Mode.

  • D3DDivide
  • D3DMultiply
  • D3DRGB
  • D3DRGBA
  • D3DSTATE_OVERRIDE
  • D3DVAL
  • D3DVALP
  • RGB_GETBLUE
  • RGB_GETGREEN
  • RGB_GETRED
  • RGB_MAKE
  • RGB_TORGBA
  • RGBA_GETALPHA
  • RGBA_GETBLUE
  • RGBA_GETGREEN
  • RGBA_GETRED
  • RGBA_MAKE
  • RGBA_SETALPHA
  • RGBA_TORGB


D3DDivide

The D3DDivide macro divides two values.

D3DDivide(a, b)    (float)((double) (a) / (double) (b))

Parameters

a and b
Dividend and divisor in the expression, respectively.

Return Values

The macros returns the quotient of the division.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.

See Also

D3DMultiply


D3DMultiply

The D3DMultiply macro multiplies two values.

D3DMultiply(a, b)    ((a) * (b))

Parameters

a and b
Values to be multiplied.

Return Values

The macros returns the product of the multiplication.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.

See Also

D3DDivide


D3DRGB

The D3DRGB macro initializes a color with the supplied RGB values.

D3DRGB(r, g, b) \
    (0xff000000L | ( ((long)((r) * 255)) << 16) | \
    (((long)((g) * 255)) << 8) | (long)((b) * 255))

Parameters

r, g, and b
Red, green, and blue components of the color. These should be floating-point values in the range 0 through 1.

Return Values

The macros returns the D3DCOLOR value corresponding to the supplied RGB values.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.

See Also

D3DRGBA


D3DRGBA

The D3DRGBA macro initializes a color with the supplied RGBA values.

D3DRGBA(r, g, b, a) \
    ((((long)((a) * 255)) << 24) | (((long)((r) * 255)) << 16) |
    (((long)((g) * 255)) << 8) | (long)((b) * 255))

Parameters

r, g, b, and a
Red, green, blue, and alpha components of the color.

Return Values

The macros returns the D3DCOLOR value corresponding to the supplied RGBA values.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.

See Also

D3DRGB


D3DSTATE_OVERRIDE

The D3DSTATE_OVERRIDE macro overrides the state of the rasterization, lighting, or transformation module. Applications can use this macro to lock and unlock a state.

D3DSTATE_OVERRIDE(type) (D3DRENDERSTATETYPE)(((DWORD) (type) + D3DSTATE_OVERRIDE_BIAS))

Parameters

type
State to override. This parameter should be one of the members of the D3DTRANSFORMSTATETYPE, D3DLIGHTSTATETYPE, or D3DRENDERSTATETYPE enumerated types.

Return Values

No return value.

Remarks

An application might, for example, use the STATE_DATA helper macro (defined in the D3dmacs.h header file in the Misc directory of the DirectX Programmer's Reference sample code) and D3DSTATE_OVERRIDE to lock and unlock the D3DRENDERSTATE_SHADEMODE render state:

//  Lock the shade mode.

STATE_DATA(D3DSTATE_OVERRIDE(D3DRENDERSTATE_SHADEMODE), TRUE, lpBuffer);

//  Work with the shade mode and unlock it when read-only status is not required.

STATE_DATA(D3DSTATE_OVERRIDE(D3DRENDERSTATE_SHADEMODE), FALSE, lpBuffer);

For more information about overriding rendering states, see States and State Overrides.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.


D3DVAL

The D3DVAL macro creates a value whose type is D3DVALUE.

D3DVAL(val)    ((float)val)

Parameters

val
Value to be converted.

Return Values

The macros returns the converted value.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.

See Also

D3DVALP


D3DVALP

The D3DVALP macro creates a value of the specified precision.

D3DVALP(val, prec)    ((float)val)

Parameters

val
Value to be converted.
prec
Ignored.

Return Values

The macros returns the converted value.

Remarks

The precision, as implemented by the D3DVAL macro, is 16 bits for the fractional part of the value.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.

See Also

D3DVAL


RGB_GETBLUE

The RGB_GETBLUE macro retrieves the blue component of a D3DCOLOR value.

RGB_GETBLUE(rgb)    ((rgb) & 0xff)

Parameters

rgb
Color index from which the blue component is retrieved.

Return Values

Returns the blue component.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.


RGB_GETGREEN

The RGB_GETGREEN macro retrieves the green component of a D3DCOLOR value.

RGB_GETGREEN(rgb)    (((rgb) >> 8) & 0xff)

Parameters

rgb
Color index from which the green component is retrieved.

Return Values

The macros returns the green component.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.


RGB_GETRED

The RGB_GETRED macro retrieves the red component of a D3DCOLOR value.

RGB_GETRED(rgb)    (((rgb) >> 16) & 0xff)

Parameters

rgb
Color index from which the red component is retrieved.

Return Values

The macros returns the red component.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.


RGB_MAKE

The RGB_MAKE macro creates an RGB color from supplied values.

RGB_MAKE(r, g, b)    ((D3DCOLOR) (((r) << 16) | ((g) << 8) | (b)))

Parameters

r, g, and b
Red, green, and blue components of the color to be created. These should be integer values in the range zero through 255.

Return Values

The macros returns the color.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.


RGB_TORGBA

The RGB_TORGBA macro creates an RGBA color from a supplied RGB color.

RGB_TORGBA(rgb)    ((D3DCOLOR) ((rgb) | 0xff000000))

Parameters

rgb
RGB color to be converted to an RGBA color.

Return Values

Returns the RGBA color.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.

See Also

RGBA_TORGB


RGBA_GETALPHA

The RGBA_GETALPHA macro retrieves the alpha component of an RGBA D3DCOLOR value.

RGBA_GETALPHA(rgb)    ((rgb) >> 24)

Parameters

rgb
Color index from which the alpha component is retrieved.

Return Values

The macros returns the alpha component.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.


RGBA_GETBLUE

The RGBA_GETBLUE macro retrieves the blue component of an RGBA D3DCOLOR value.

RGBA_GETBLUE(rgb)    ((rgb) & 0xff)

Parameters

rgb
Color index from which the blue component is retrieved.

Return Values

The macros returns the blue component.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.


RGBA_GETGREEN

The RGBA_GETGREEN macro retrieves the green component of an RGBA D3DCOLOR value.

RGBA_GETGREEN(rgb)    (((rgb) >> 8) & 0xff)

Parameters

rgb
Color index from which the green component is retrieved.

Return Values

The macros returns the green component.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.


RGBA_GETRED

The RGBA_GETRED macro retrieves the red component of an RGBA D3DCOLOR value.

RGBA_GETRED(rgb)    (((rgb) >> 16) & 0xff)

Parameters

rgb
Color index from which the red component is retrieved.

Return Values

The macros returns the red component.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.


RGBA_MAKE

The RGBA_MAKE macro creates an RGBA D3DCOLOR value from supplied red, green, blue, and alpha components.

RGBA_MAKE(r, g, b, a)   \
    ((D3DCOLOR) (((a) << 24) | ((r) << 16) | ((g) << 8) | (b)))

Parameters

r, g, b, and a
Red, green, blue, and alpha components of the RGBA color to be created.

Return Values

The macros returns the color.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.


RGBA_SETALPHA

The RGBA_SETALPHA macro sets the alpha component of an RGBA D3DCOLOR value.

RGBA_SETALPHA(rgba, x)    (((x) << 24) | ((rgba) & 0x00ffffff))

Parameters

rgba
RGBA color for which the alpha component will be set.
x
Value of alpha component to be set.

Return Values

The macros returns the RGBA color whose alpha component has been set.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.


RGBA_TORGB

The RGBA_TORGB macro creates an RGB D3DCOLOR value from a supplied RGBA D3DCOLOR value by stripping off the alpha component of the color.

RGBA_TORGB(rgba)    ((D3DCOLOR) ((rgba) & 0xffffff))

Parameters

rgba
RGBA color to be converted to an RGB color.

Return Values

The macros returns the RGB color.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.

See Also

RGB_TORGBA


Structures

This section contains information about the following structures used with Direct3D Immediate Mode.

  • D3DBRANCH
  • D3DCLIPSTATUS
  • D3DCOLORVALUE
  • D3DDEVICEDESC
  • D3DDP_PTRSTRIDE
  • D3DDRAWPRIMITIVESTRIDEDDATA
  • D3DEXECUTEBUFFERDESC
  • D3DEXECUTEDATA
  • D3DFINDDEVICERESULT
  • D3DFINDDEVICESEARCH
  • D3DHVERTEX
  • D3DINSTRUCTION
  • D3DLIGHT
  • D3DLIGHT2
  • D3DLIGHTDATA
  • D3DLIGHTINGCAPS
  • D3DLIGHTINGELEMENT
  • D3DLINE
  • D3DLINEPATTERN
  • D3DLVERTEX
  • D3DMATERIAL
  • D3DMATRIX
  • D3DMATRIXLOAD
  • D3DMATRIXMULTIPLY
  • D3DPICKRECORD
  • D3DPOINT
  • D3DPRIMCAPS
  • D3DPROCESSVERTICES
  • D3DRECT
  • D3DSPAN
  • D3DSTATE
  • D3DSTATS
  • D3DSTATUS
  • D3DTEXTURELOAD
  • D3DTLVERTEX
  • D3DTRANSFORMCAPS
  • D3DTRANSFORMDATA
  • D3DTRIANGLE
  • D3DVECTOR
  • D3DVERTEX
  • D3DVERTEXBUFFERDESC
  • D3DVIEWPORT
  • D3DVIEWPORT2

Note The memory for all DirectX structures must be initialized to zero before use. In addition, all structures that contain a dwSize member must set the member to the size of the structure, in bytes, before use. The following example performs these tasks on a common structure, DDCAPS:

DDCAPS ddcaps; // Can't use this yet.

ZeroMemory(&ddcaps, sizeof(ddcaps));
ddcaps.dwSize = sizeof(ddcaps);

// Now the structure can be used.
.
.


D3DBRANCH

The D3DBRANCH structure performs conditional operations inside an execute buffer. This structure is a forward-branch structure.

typedef struct _D3DBRANCH {
    DWORD dwMask;
    DWORD dwValue;
    BOOL  bNegate;
    DWORD dwOffset;
} D3DBRANCH, *LPD3DBRANCH;

Members

dwMask
Bitmask for the branch. This mask is combined with the driver-status mask by using the bitwise AND operator. If the result equals the value specified in the dwValue member and the bNegate member is FALSE, the branch is taken.

For a list of the available driver-status masks, see the dwStatus member of the D3DSTATUS structure.

dwValue
Application-defined value to compare against the operation described in the dwMask member.
bNegate
TRUE to negate comparison.
dwOffset
How far to branch forward. Specify zero to exit.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.


D3DCLIPSTATUS

The D3DCLIPSTATUS structure describes the current clip status and extents of the clipping region. This structure was introduced in DirectX 5.0.

typedef struct _D3DCLIPSTATUS {
    DWORD dwFlags;
    DWORD dwStatus;
    float minx, maxx;
    float miny, maxy;
    float minz, maxz;
} D3DCLIPSTATUS, *LPD3DCLIPSTATUS;

Members

dwFlags
Flags describing whether this structure describes 2-D extents, 3-D extents, or the clip status. This member can be a combination of the following flags:
D3DCLIPSTATUS_STATUS
The structure describes the current clip status.
D3DCLIPSTATUS_EXTENTS2
The structure describes the current 2-D extents. This flag cannot be combined with D3DCLIPSTATUS_EXTENTS3.
D3DCLIPSTATUS_EXTENTS3
Not currently implemented.
dwStatus
Describes the current clip status. For a list of the available driver-status masks, see the dwStatus member of the D3DSTATUS structure.
minx, maxx, miny, maxy, minz, maxz
x, y, and z extents of the current clipping region.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.

See Also

IDirect3DDevice3::GetClipStatus, IDirect3DDevice3::SetClipStatus


D3DCOLORVALUE

The D3DCOLORVALUE structure describes color values for the D3DLIGHT2 and D3DMATERIAL structures.

typedef struct _D3DCOLORVALUE {
    union {
        D3DVALUE r;
        D3DVALUE dvR;
    };
    union {
        D3DVALUE g;
        D3DVALUE dvG;
    };
    union {
        D3DVALUE b;
        D3DVALUE dvB;
    };
    union {
        D3DVALUE a;
        D3DVALUE dvA;
    };
} D3DCOLORVALUE;

Members

dvR, dvG, dvB, and dvA
Values of the D3DVALUE type specifying the red, green, blue, and alpha components of a color. These values generally range from 0 to 1, with 0 being black.

Remarks

You can set the members of this structure to values outside the range of 0 to 1 to implement some unusual effects. Values greater than 1 produce strong lights that tend to wash out a scene. Negative values produce dark lights, which actually remove light from a scene. For more information, see Colored Lights.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.


D3DDEVICEDESC

The D3DDEVICEDESC structure contains a description of the current device. This structure is used to query the current device by such methods as IDirect3DDevice3::GetCaps.

typedef struct _D3DDeviceDesc {
    DWORD            dwSize;
    DWORD            dwFlags;
    D3DCOLORMODEL    dcmColorModel;
    DWORD            dwDevCaps;
    D3DTRANSFORMCAPS dtcTransformCaps;
    BOOL             bClipping;
    D3DLIGHTINGCAPS  dlcLightingCaps;
    D3DPRIMCAPS      dpcLineCaps;
    D3DPRIMCAPS      dpcTriCaps;
    DWORD            dwDeviceRenderBitDepth;
    DWORD            dwDeviceZBufferBitDepth;
    DWORD            dwMaxBufferSize;
    DWORD            dwMaxVertexCount;
    DWORD            dwMinTextureWidth, dwMinTextureHeight;
    DWORD            dwMaxTextureWidth, dwMaxTextureHeight;
    DWORD            dwMinStippleWidth, dwMaxStippleWidth;
    DWORD            dwMinStippleHeight, dwMaxStippleHeight;
    DWORD            dwMaxTextureRepeat;
    DWORD            dwMaxTextureAspectRatio;
    DWORD            dwMaxAnisotropy;
    D3DVALUE         dvGuardBandLeft;
    D3DVALUE         dvGuardBandTop;
    D3DVALUE         dvGuardBandRight;
    D3DVALUE         dvGuardBandBottom;
    D3DVALUE         dvExtentsAdjust;
    DWORD            dwStencilCaps;
    DWORD            dwFVFCaps;
    DWORD            dwTextureOpCaps;
    WORD             wMaxTextureBlendStages;
    WORD             wMaxSimultaneousTextures;
} D3DDEVICEDESC, *LPD3DDEVICEDESC;

Members

dwSize
Size, in bytes, of this structure. You can use the D3DDEVICEDESCSIZE constant for this value. This member must be initialized before the structure is used.
dwFlags
Flags identifying the members of this structure that contain valid data.
D3DDD_BCLIPPING
The bClipping member is valid.
D3DDD_COLORMODEL
The dcmColorModel member is valid.
D3DDD_DEVCAPS
The dwDevCaps member is valid.
D3DDD_DEVICERENDERBITDEPTH
The dwDeviceRenderBitDepth member is valid.
D3DDD_DEVICEZBUFFERBITDEPTH
The dwDeviceZBufferBitDepth member is valid.
D3DDD_LIGHTINGCAPS
The dlcLightingCaps member is valid.
D3DDD_LINECAPS
The dpcLineCaps member is valid.
D3DDD_MAXBUFFERSIZE
The dwMaxBufferSize member is valid.
D3DDD_MAXVERTEXCOUNT
The dwMaxVertexCount member is valid.
D3DDD_TRANSFORMCAPS
The dtcTransformCaps member is valid.
D3DDD_TRICAPS
The dpcTriCaps member is valid.
dcmColorModel
One of the values of the D3DCOLORMODEL data type, specifying the color model for the device.
dwDevCaps
Flags identifying the capabilities of the device.
D3DDEVCAPS_CANRENDERAFTERFLIP
Device can queue rendering commands after a page flip. Applications should not change their behavior if this flag is set; this capability simply means that the device is relatively fast.

This flag was introduced in DirectX 5.0.

D3DDEVCAPS_DRAWPRIMTLVERTEX
Device exports a DrawPrimitive-aware HAL.

This flag was introduced in DirectX 5.0.

D3DDEVCAPS_EXECUTESYSTEMMEMORY
Device can use execute buffers from system memory.
D3DDEVCAPS_EXECUTEVIDEOMEMORY
Device can use execute buffer from video memory.
D3DDEVCAPS_FLOATTLVERTEX
Device accepts floating point for post-transform vertex data.
D3DDEVCAPS_SEPARATETEXTUREMEMORIES
Device uses discrete texture memory pools for each stage. Textures must be assigned to texture stages explicitly at creation-time by setting the dwTextureStage member of the DDSURFACEDESC2 structure to the appropriate stage identifier.
D3DDEVCAPS_SORTDECREASINGZ
Device needs data sorted for decreasing depth.
D3DDEVCAPS_SORTEXACT
Device needs data sorted exactly.
D3DDEVCAPS_SORTINCREASINGZ
Device needs data sorted for increasing depth.
D3DDEVCAPS_TEXREPEATNOTSCALEDBYSIZE
Device defers scaling of texture indices by the texture size until after the texture address mode is applied.
D3DDEVCAPS_TEXTURENONLOCALVIDMEM
Device can retrieve textures from non-local video (AGP) memory.

This flag was introduced in DirectX 5.0. For more information about AGP memory, see Using Non-local Video Memory Surfaces in the DirectDraw documentation.

D3DDEVCAPS_TEXTURESYSTEMMEMORY
Device can retrieve textures from system memory.
D3DDEVCAPS_TEXTUREVIDEOMEMORY
Device can retrieve textures from device memory.
D3DDEVCAPS_TLVERTEXSYSTEMMEMORY
Device can use buffers from system memory for transformed and lit vertices.
D3DDEVCAPS_TLVERTEXVIDEOMEMORY
Device can use buffers from video memory for transformed and lit vertices.
dtcTransformCaps
One of the members of the D3DTRANSFORMCAPS structure, specifying the transformation capabilities of the device.
bClipping
TRUE if the device can perform 3-D clipping.
dlcLightingCaps
One of the members of the D3DLIGHTINGCAPS structure, specifying the lighting capabilities of the device.
dpcLineCaps and dpcTriCaps
D3DPRIMCAPS structures defining the device's support for line-drawing and triangle primitives.
dwDeviceRenderBitDepth
Device's rendering bit-depth. This can be one or more of the following DirectDraw bit-depth constants: DDBD_8, DDBD_16, DDBD_24, or DDBD_32.
dwDeviceZBufferBitDepth
Device's depth-buffer bit-depth. This can be one of the following DirectDraw bit-depth constants: DDBD_8, DDBD_16, DDBD_24, or DDBD_32.
dwMaxBufferSize
Maximum size of the execute buffer for this device. If this member is 0, the application can use any size.
dwMaxVertexCount
Maximum number of vertices supported by an execute buffer for this device. (The DrawPrimitive rendering methods support up to 65,536 vertices.)
dwMinTextureWidth, dwMinTextureHeight
Minimum texture width and height for this device.
dwMaxTextureWidth, dwMaxTextureHeight
Maximum texture width and height for this device.
dwMinStippleWidth, dwMaxStippleWidth
Minimum and maximum width of the stipple pattern for this device.
dwMinStippleHeight, dwMaxStippleHeight
Minimum and maximum height of the stipple pattern for this device.
dwMaxTextureRepeat
Full range of the integer (non-fractional) bits of the post-normalized texture indices. If the D3DDEVCAPS_TEXREPEATNOTSCALEDBYSIZE bit is set, the device defers scaling by the texture size until after the texture address mode is applied. If it isn't set, the device scales the texture indices by the texture size (largest level-of-detail) prior to interpolation.
dwMaxTextureAspectRatio
Maximum texture aspect ratio supported by the hardware; this will typically be a power of 2.
dwMaxAnisotropy
Maximum valid value for the D3DRENDERSTATE_ANISOTROPY render state.
dvGuardBandLeft, dvGuardBandTop, dvGuardBandRight, and dvGuardBandBottom
The screen-space coordinates of the guard-band clipping region. Coordinates inside this rectangle but outside the viewport rectangle will automatically be clipped.
dvExtentsAdjust
Number of pixels to adjust the extents rectangle outward to accommodate antialiasing kernels.
dwStencilCaps
Flags specifying supported stencil-buffer operations. Stencil operations are assumed to be valid for all three stencil-buffer operation render states (D3DRENDERSTATE_STENCILFAIL, D3DRENDERSTATE_STENCILPASS, and D3DRENDERSTATE_STENCILFAILZFAIL).
D3DSTENCILCAPS_DECR
The D3DSTENCILOP_DECR operation is supported.
D3DSTENCILCAPS_DECRSAT
The D3DSTENCILOP_DECRSAT operation is supported.
D3DSTENCILCAPS_INCR
The D3DSTENCILOP_INCR operation is supported.
D3DSTENCILCAPS_INCRSAT
The D3DSTENCILOP_INCRSAT operation is supported.
D3DSTENCILCAPS_INVERT
The D3DSTENCILOP_INVERT operation is supported.
D3DSTENCILCAPS_KEEP
The D3DSTENCILOP_KEEP operation is supported.
D3DSTENCILCAPS_REPLACE
The D3DSTENCILOP_REPLACE operation is supported.
D3DSTENCILCAPS_ZERO
The D3DSTENCILOP_ZERO operation is supported.
dwFVFCaps
Flexible vertex format capabilities:
D3DFVFCAPS_DONOTSTRIPELEMENTS
Device prefers that vertex elements not be stripped. That is, if the vertex format contains elements that will not be used with the current render states, there is no need to regenerate the vertices. If this capability flag is not present, stripping extraneous elements from the vertex format will provide better performance.
D3DFVFCAPS_TEXCOORDCOUNTMASK
Masks the low WORD of dwFVFCaps. These bits, cast to the WORD data type, describe the total number of texture coordinate sets that the device can simultaneously use for multiple texture blending. (You can use up to eight texture coordinate sets for any vertex, but the device can only blend using the specified number of texture coordinate sets.)
dwTextureOpCaps
Combination of flags describing the texture operations supported by this device. The following flags are defined:
D3DTEXOPCAPS_ADD
The D3DTOP_ADD texture blending operation is supported by this device.
D3DTEXOPCAPS_ADDSIGNED
The D3DTOP_ADDSIGNED texture blending operation is supported by this device.
D3DTEXOPCAPS_ADDSIGNED2X
The D3DTOP_ADDSIGNED2X texture blending operation is supported by this device.
D3DTEXOPCAPS_ADDSMOOTH
The D3DTOP_ADDSMOOTH texture blending operation is supported by this device.
D3DTEXOPCAPS_BLENDCURRENTALPHA
The D3DTOP_BLENDCURRENTALPHA texture blending operation is supported by this device.
D3DTEXOPCAPS_BLENDDIFFUSEALPHA
The D3DTOP_BLENDDIFFUSEALPHA texture blending operation is supported by this device.
D3DTEXOPCAPS_BLENDFACTORALPHA
The D3DTOP_BLENDFACTORALPHA texture blending operation is supported by this device.
D3DTEXOPCAPS_BLENDTEXTUREALPHA
The D3DTOP_BLENDTEXTUREALPHA texture blending operation is supported by this device.
D3DTEXOPCAPS_BLENDTEXTUREALPHAPM
The D3DTOP_BLENDTEXTUREALPHAPM texture blending operation is supported by this device.
D3DTEXOPCAPS_BUMPENVMAP
The D3DTOP_BUMPENVMAP texture blending operation is supported by this device.
D3DTEXOPCAPS_BUMPENVMAPLUMINANCE
The D3DTOP_BUMPENVMAPLUMINANCE texture blending operation is supported by this device.
D3DTEXOPCAPS_DISABLE
The D3DTOP_DISABLE texture blending operation is supported by this device.
D3DTEXOPCAPS_DOTPRODUCT3
The D3DTOP_DOTPRODUCT3 texture blending operation is supported by this device.
D3DTEXOPCAPS_MODULATE
The D3DTOP_MODULATE texture blending operation is supported by this device.
D3DTEXOPCAPS_MODULATE2X
The D3DTOP_MODULATE2X texture blending operation is supported by this device.
D3DTEXOPCAPS_MODULATE4X
The D3DTOP_MODULATE4X texture blending operation is supported by this device.
D3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR
The D3DTOP_MODULATEALPHA_ADDCOLOR texture blending operation is supported by this device.
D3DTEXOPCAPS_MODULATECOLOR_ADDALPHA
The D3DTOP_MODULATEALPHA_ADDCOLOR texture blending operation is supported by this device.
D3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR
The D3DTOP_MODULATEINVALPHA_ADDCOLOR texture blending operation is supported by this device.
D3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA
The D3DTOP_MODULATEINVCOLOR_ADDALPHA texture blending operation is supported by this device.
D3DTEXOPCAPS_PREMODULATE
The D3DTOP_PREMODULATE texture blending operation is supported by this device.
D3DTEXOPCAPS_SELECTARG1
The D3DTOP_SELECTARG1 texture blending operation is supported by this device.
D3DTEXOPCAPS_SELECTARG2
The D3DTOP_SELECTARG2 texture blending operation is supported by this device.
D3DTEXOPCAPS_SUBTRACT
The D3DTOP_SUBTRACT texture blending operation is supported by this device.
wMaxTextureBlendStages
Maximum number of texture blending stages supported by this device.
wMaxSimultaneousTextures
Maximum number of textures that can be simultaneously bound to the texture blending stages for this device. See remarks.

Remarks

The wMaxTextureBlendStages and wMaxSimultaneousTextures members might seem very similar at first glance, but they contain different information. The wMaxTextureBlendStages member contains the total number of texture-blending stages supported by the current device, and the wMaxSimultaneousTextures member describes how many of those stages can have textures bound to them by using the IDirect3DDevice3::SetTexture method.

When the driver fills this structure, it can set values for execute buffer capabilities even when the interface being used to retrieve the capabilities (such as IDirect3DDevice3) doesn't support execute buffers.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dcaps.h.

See Also

D3DCOLORMODEL, D3DFINDDEVICERESULT, D3DLIGHTINGCAPS, D3DPRIMCAPS, D3DTRANSFORMCAPS


D3DDP_PTRSTRIDE

The D3DDP_PTRSTRIDE structure contains the address of an array of flexible vertex format components and the stride to the next element in the array. This structure is contained by the D3DDRAWPRIMITIVESTRIDEDDATA structure.

typedef struct _D3DDP_PTRSTRIDE {
    LPVOID lpvData;
    DWORD  dwStride;
} D3DDP_PTRSTRIDE;

Members

lpvData
Address of an array of data.
dwStride
Memory stride to between elements in the array.

Remarks

This structure can be used with a composite vertex format (like the D3DLVERTEX structure) or a distinct array of vertex components. In a composite vertex format, the lpvData points to a particular component, and the dwStride member is the stride, in bytes, of the composite format. In an array that contains only one vertex component, the dwStride member should be the stride of each element in the array.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.

See Also

D3DDRAWPRIMITIVESTRIDEDDATA, Strided Vertex Format


D3DDRAWPRIMITIVESTRIDEDDATA

The D3DDRAWPRIMITIVESTRIDEDDATA structure contains flexible vertex format components.

typedef struct D3DDRAWPRIMITIVESTRIDEDDATA  {
    D3DDP_PTRSTRIDE position;
    D3DDP_PTRSTRIDE normal;
    D3DDP_PTRSTRIDE diffuse;
    D3DDP_PTRSTRIDE specular;
    D3DDP_PTRSTRIDE textureCoords[D3DDP_MAXTEXCOORD];
} D3DDRAWPRIMITIVESTRIDEDDATA , *LPD3DDRAWPRIMITIVESTRIDEDDATA;

Members

position and normal
D3DDP_PTRSTRIDE structures that point to arrays of position and normal vectors for a collection of vertices (each vector is a 3-element array of float values).
diffuse and specular
D3DDP_PTRSTRIDE structures that point to diffuse and specular color information for a collection of vertices. Each color component is an 8-8-8-8 RGBA value.
textureCoords
An 8-element array of D3DDP_PTRSTRIDE structures. Each element in the array is an array of texture coordinates for the collection of vertices. Your application determines which array of texture coordinates is used for a given texture stage by calling the IDirect3DDevice3::SetTextureStageState method with the D3DTSS_TEXCOORDINDEX stage state value.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.

See Also

D3DDP_PTRSTRIDE, Strided Vertex Format, Vertex Formats


D3DEXECUTEBUFFERDESC

The D3DEXECUTEBUFFERDESC structure describes the execute buffer for such methods as IDirect3DDevice::CreateExecuteBuffer and IDirect3DExecuteBuffer::Lock.

typedef struct _D3DExecuteBufferDesc {
    DWORD  dwSize;
    DWORD  dwFlags;
    DWORD  dwCaps;
    DWORD  dwBufferSize;
    LPVOID lpData;
} D3DEXECUTEBUFFERDESC, *LPD3DEXECUTEBUFFERDESC;

Members

dwSize
Size of this structure, in bytes. This member must be initialized before the structure is used.
dwFlags
Flags identifying the members of this structure that contain valid data.
D3DDEB_BUFSIZE
The dwBufferSize member is valid.
D3DDEB_CAPS
The dwCaps member is valid.
D3DDEB_LPDATA
The lpData member is valid.
dwCaps
Location in memory of the execute buffer.
D3DDEBCAPS_MEM
A logical OR of D3DDEBCAPS_SYSTEMMEMORY and D3DDEBCAPS_VIDEOMEMORY.
D3DDEBCAPS_SYSTEMMEMORY
The execute buffer data resides in system memory.
D3DDEBCAPS_VIDEOMEMORY
The execute buffer data resides in device memory.
dwBufferSize
Size of the execute buffer, in bytes.
lpData
Address of the buffer data.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dcaps.h.


D3DEXECUTEDATA

The D3DEXECUTEDATA structure specifies data for the IDirect3DDevice::Execute method. When this method is called and the transformation has been done, the instruction list starting at the value specified in the dwInstructionOffset member is parsed and rendered.

typedef struct _D3DEXECUTEDATA {
    DWORD     dwSize;
    DWORD     dwVertexOffset;
    DWORD     dwVertexCount;
    DWORD     dwInstructionOffset;
    DWORD     dwInstructionLength;
    DWORD     dwHVertexOffset;
    D3DSTATUS dsStatus;
} D3DEXECUTEDATA, *LPD3DEXECUTEDATA;

Members

dwSize
Size of this structure, in bytes. This member must be initialized before the structure is used.
dwVertexOffset
Offset into the list of vertices.
dwVertexCount
Number of vertices to execute.
dwInstructionOffset
Offset into the list of instructions to execute.
dwInstructionLength
Length of the instructions to execute.
dwHVertexOffset
Offset into the list of vertices for the homogeneous vertex used when the application is supplying screen coordinate data that needs clipping.
dsStatus
Value storing the screen extent of the rendered geometry for use after the transformation is complete. This value is a D3DSTATUS structure.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.

See Also

D3DSTATUS


D3DFINDDEVICERESULT

The D3DFINDDEVICERESULT structure identifies a device an application has found by calling the IDirect3D3::FindDevice method.

typedef struct _D3DFINDDEVICERESULT {
    DWORD         dwSize;
    GUID          guid;
    D3DDEVICEDESC ddHwDesc;
    D3DDEVICEDESC ddSwDesc;
} D3DFINDDEVICERESULT, *LPD3DFINDDEVICERESULT;

Members

dwSize
Size, in bytes, of the structure. This member must be initialized before the structure is used.
guid
Globally unique identifier (GUID) of the device that was found.
ddHwDesc and ddSwDesc
D3DDEVICEDESC structures describing the hardware and software devices that were found.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dcaps.h.

See Also

D3DFINDDEVICESEARCH


D3DFINDDEVICESEARCH

The D3DFINDDEVICESEARCH structure specifies the characteristics of a device an application wants to find. This structure is used in calls to the IDirect3D3::FindDevice method.

typedef struct _D3DFINDDEVICESEARCH {
    DWORD         dwSize;
    DWORD         dwFlags;
    BOOL          bHardware;
    D3DCOLORMODEL dcmColorModel;
    GUID          guid;
    DWORD         dwCaps;
    D3DPRIMCAPS   dpcPrimCaps;
} D3DFINDDEVICESEARCH, *LPD3DFINDDEVICESEARCH;

Members

dwSize
Size, in bytes, of this structure. This member must be initialized before the structure is used.
dwFlags
Flags defining the type of device the application wants to find. This member can be one or more of the following values:
D3DFDS_ALPHACMPCAPS
Match the dwAlphaCmpCaps member of the D3DPRIMCAPS structure specified as the dpcPrimCaps member of this structure.
D3DFDS_COLORMODEL
Match the color model specified in the dcmColorModel member of this structure.
D3DFDS_DSTBLENDCAPS
Match the dwDestBlendCaps member of the D3DPRIMCAPS structure specified as the dpcPrimCaps member of this structure.
D3DFDS_GUID
Match the globally unique identifier (GUID) specified in the guid member of this structure.
D3DFDS_HARDWARE
Match the hardware or software search specification given in the bHardware member of this structure.
D3DFDS_LINES
Match the D3DPRIMCAPS structure specified by the dpcLineCaps member of the D3DDEVICEDESC structure.
D3DFDS_MISCCAPS
Match the dwMiscCaps member of the D3DPRIMCAPS structure specified as the dpcPrimCaps member of this structure.
D3DFDS_RASTERCAPS
Match the dwRasterCaps member of the D3DPRIMCAPS structure specified as the dpcPrimCaps member of this structure.
D3DFDS_SHADECAPS
Match the dwShadeCaps member of the D3DPRIMCAPS structure specified as the dpcPrimCaps member of this structure.
D3DFDS_SRCBLENDCAPS
Match the dwSrcBlendCaps member of the D3DPRIMCAPS structure specified as the dpcPrimCaps member of this structure.
D3DFDS_TEXTUREBLENDCAPS
Match the dwTextureBlendCaps member of the D3DPRIMCAPS structure specified as the dpcPrimCaps member of this structure.
D3DFDS_TEXTURECAPS
Match the dwTextureCaps member of the D3DPRIMCAPS structure specified as the dpcPrimCaps member of this structure.
D3DFDS_TEXTUREFILTERCAPS
Match the dwTextureFilterCaps member of the D3DPRIMCAPS structure specified as the dpcPrimCaps member of this structure.
D3DFDS_TRIANGLES
Match the D3DPRIMCAPS structure specified by the dpcTriCaps member of the D3DDEVICEDESC structure.
D3DFDS_ZCMPCAPS
Match the dwZCmpCaps member of the D3DPRIMCAPS structure specified as the dpcPrimCaps member of this structure.
bHardware
Flag specifying whether the device to find is implemented as hardware or software. If this member is TRUE, the device to search for has hardware rasterization and may also provide other hardware acceleration. Applications that use this flag should set the D3DFDS_HARDWARE bit in the dwFlags member.
dcmColorModel
One of the values of the D3DCOLORMODEL data type, specifying whether the device to find should use the ramp or RGB color model.
guid
Globally unique identifier (GUID) of the device to find.
dwCaps
Reserved.
dpcPrimCaps
Specifies a D3DPRIMCAPS structure defining the device's capabilities for each primitive type.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dcaps.h.

See Also

D3DFINDDEVICERESULT


D3DHVERTEX

The D3DHVERTEX structure defines a homogeneous vertex used when the application is supplying screen coordinate data that needs clipping. This structure is part of the D3DTRANSFORMDATA structure.

typedef struct _D3DHVERTEX {
    DWORD        dwFlags;
    union {
        D3DVALUE hx;
        D3DVALUE dvHX;
    };
    union {
        D3DVALUE hy;
        D3DVALUE dvHY;
    };
    union {
        D3DVALUE hz;
        D3DVALUE dvHZ;
    };
} D3DHVERTEX, *LPD3DHVERTEX;

Members

dwFlags
Flags defining the clip status of the homogeneous vertex. This member can be one or more of the flags described in the dwClip member of the D3DTRANSFORMDATA structure.
dvHX, dvHY, and dvHZ
Values of the D3DVALUE type describing transformed homogeneous coordinates. These coordinates define the vertex.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.


D3DINSTRUCTION

The D3DINSTRUCTION structure defines an instruction in an execute buffer. A display list is made up from a list of variable length instructions. Each instruction begins with a common instruction header and is followed by the data required for that instruction.

typedef struct _D3DINSTRUCTION {
    BYTE bOpcode;
    BYTE bSize;
    WORD wCount;
} D3DINSTRUCTION, *LPD3DINSTRUCTION;

Members

bOpcode
Rendering operation, specified as a member of the D3DOPCODE enumerated type.
bSize
Size of each instruction data unit. This member can be used to skip to the next instruction in the sequence.
wCount
Number of data units of instructions that follow. This member allows efficient processing of large batches of similar instructions, such as triangles that make up a triangle mesh.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.


D3DLIGHT

For DirectX 5.0 and later, this structure is superseded by the D3DLIGHT2 structure. The D3DLIGHT2 structure adds a dwFlags member. In addition, the dvAttenuation members are interpreted differently in D3DLIGHT2 than they were for D3DLIGHT.

typedef struct _D3DLIGHT {
    DWORD           dwSize;
    D3DLIGHTTYPE    dltType;
    D3DCOLORVALUE   dcvColor;
    D3DVECTOR       dvPosition;
    D3DVECTOR       dvDirection;
    D3DVALUE        dvRange;
    D3DVALUE        dvFalloff;
    D3DVALUE        dvAttenuation0;
    D3DVALUE        dvAttenuation1;
    D3DVALUE        dvAttenuation2;
    D3DVALUE        dvTheta;
    D3DVALUE        dvPhi;
} D3DLIGHT, *LPD3DLIGHT;

Remarks

When light properties are defined with this structure, per-vertex color (enabled through D3DLIGHTSTATE_COLORVERTEX) is not supported. You must define and set light properties in a D3DLIGHT2 structure to use per-vertex color.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.


D3DLIGHT2

The D3DLIGHT2 structure defines the light type in calls to methods such as IDirect3DLight::SetLight and IDirect3DLight::GetLight.

For DirectX 5.0 and newer, this structure supersedes the D3DLIGHT structure. The D3DLIGHT2 structure is identical to D3DLIGHT except for the addition of the dwFlags member. In addition, the dvAttenuation members are interpreted differently in D3DLIGHT2 than they were for D3DLIGHT.

typedef struct _D3DLIGHT2 {
    DWORD         dwSize;
    D3DLIGHTTYPE  dltType;
    D3DCOLORVALUE dcvColor;
    D3DVECTOR     dvPosition;
    D3DVECTOR     dvDirection;
    D3DVALUE      dvRange;
    D3DVALUE      dvFalloff;
    D3DVALUE      dvAttenuation0;
    D3DVALUE      dvAttenuation1;
    D3DVALUE      dvAttenuation2;
    D3DVALUE      dvTheta;
    D3DVALUE      dvPhi;
    DWORD         dwFlags;
} D3DLIGHT2, *LPD3DLIGHT2;

Members

dwSize
Size, in bytes, of this structure. You must specify a value for this member. Direct3D uses the specified size to determine whether this is a D3DLIGHT or a D3DLIGHT2 structure.
dltType
Type of the light source. This value is one of the members of the D3DLIGHTTYPE enumerated type.
dcvColor
Color of the light. This member is a D3DCOLORVALUE structure. In ramp mode, the color is converted to a gray scale.
dvPosition
Position of the light in world space. This member has no meaning for directional lights and is ignored in that case.
dvDirection
Direction the light is pointing in world space. This member only has meaning for directional and spotlights. This vector need not be normalized but it should have a nonzero length.
dvRange
Distance beyond which the light has no effect. The maximum allowable value for this member is D3DLIGHT_RANGE_MAX, which is defined as the square root of FLT_MAX. This member does not affect directional lights.
dvFalloff
Decrease in illumination between a spotlight's inner cone (the angle specified by the dvTheta member) and the outer edge of the outer cone (the angle specified by the dvPhi member). This feature was implemented for DirectX 5.0. For details on how dvFalloff values affect a spotlight, see Spotlight Falloff Model.

The effect of falloff on the lighting is subtle. Furthermore, a small performance penalty is incurred by shaping the falloff curve. For these reasons, most developers set this value to 1.0.

dvAttenuation0 through dvAttenuation2
Values specifying how a light's intensity changes over distance. (Attenuation does not affect directional lights.) In the D3DLIGHT2 structure these values are interpreted differently than they were for the D3DLIGHT structure. For information about how these attenuation values affect lighting in a scene, see Light Attenuation Over Distance.
dvTheta
Angle, in radians, of the spotlight's inner cone—that is, the fully illuminated spotlight cone. This value must be between 0 and the value specified by the dvPhi member.
dvPhi
Angle, in radians, defining the outer edge of the spotlight's outer cone. Points outside this cone are not lit by the spotlight. This value must be between 0 and pi.
dwFlags
A combination of the following performance-related flags. This member is new for DirectX 5.0.
D3DLIGHT_ACTIVE
Enables the light. This flag must be set to enable the light; if it is not set, the light is ignored.
D3DLIGHT_NO_SPECULAR
Turns off specular highlights for the light.

Remarks

In the D3DLIGHT structure, the affects of the attenuation settings were difficult to predict; developers were encouraged to experiment with the settings until they achieved the desired result. For D3DLIGHT2, it is much easier to work with lighting attenuation.

When you use this structure with the IDirect3DLight::GetLight or IDirect3DLight::SetLight, cast the pointer to this structure to the LPD3DLIGHT data type.

For more information about lights, see Lights and IDirect3DLight.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.

See Also

D3DLIGHTTYPE


D3DLIGHTDATA

The D3DLIGHTDATA structure describes the points to be lit and resulting colors in calls to the IDirect3DViewport3::LightElements method.

typedef struct _D3DLIGHTDATA {
    DWORD                dwSize;
    LPD3DLIGHTINGELEMENT lpIn;
    DWORD                dwInSize;
    LPD3DTLVERTEX        lpOut;
    DWORD                dwOutSize;
} D3DLIGHTDATA, *LPD3DLIGHTDATA;

Members

dwSize
Size, in bytes, of this structure. This member must be initialized before the structure is used.
lpIn
Address of a D3DLIGHTINGELEMENT structure specifying the input positions and normal vectors.
dwInSize
Amount to skip from one input element to the next. This allows the application to store extra data inline with the element.
lpOut
Address of a D3DTLVERTEX structure specifying the output colors.
dwOutSize
Amount to skip from one output color to the next. This allows the application to store extra data inline with the color.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.


D3DLIGHTINGCAPS

The D3DLIGHTINGCAPS structure describes the lighting capabilities of a device. This structure is a member of the D3DDEVICEDESC structure.

typedef struct _D3DLIGHTINGCAPS {
    DWORD dwSize;
    DWORD dwCaps;
    DWORD dwLightingModel;
    DWORD dwNumLights;
} D3DLIGHTINGCAPS, *LPD3DLIGHTINGCAPS;

Members

dwSize
Size, in bytes, of this structure. This member must be initialized before the structure is used.
dwCaps
Flags describing the capabilities of the lighting module. The following flags are defined:
D3DLIGHTCAPS_DIRECTIONAL
Supports directional lights.
D3DLIGHTCAPS_GLSPOT
Not used.
D3DLIGHTCAPS_PARALLELPOINT
Supports parallel point lights.
D3DLIGHTCAPS_POINT
Supports point lights.
D3DLIGHTCAPS_SPOT
Supports spotlights.
dwLightingModel
Flags defining whether the lighting model is RGB or monochrome. The following flags are defined:
D3DLIGHTINGMODEL_MONO
Monochromatic lighting model.
D3DLIGHTINGMODEL_RGB
RGB lighting model.
dwNumLights
Number of lights that can be handled.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dcaps.h.


D3DLIGHTINGELEMENT

The D3DLIGHTINGELEMENT structure describes the points in model space that will be lit. This structure is part of the D3DLIGHTDATA structure.

typedef struct _D3DLIGHTINGELEMENT {
    D3DVECTOR dvPosition;
    D3DVECTOR dvNormal;
} D3DLIGHTINGELEMENT, *LPD3DLIGHTINGELEMENT;

Members

dvPosition
Value specifying the lightable point in model space. This value is a D3DVECTOR structure.
dvNormal
Value specifying the normalized unit vector. This value is a D3DVECTOR structure.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.

See Also

D3DLIGHTDATA, IDirect3DViewport3::LightElements


D3DLINE

The D3DLINE structure describes a line for the D3DOP_LINE opcode in the D3DOPCODE enumerated type.

typedef struct _D3DLINE {
    union {
        WORD v1;
        WORD wV1;
    };
    union {
        WORD v2;
        WORD wV2;
    };
} D3DLINE, *LPD3DLINE;

Members

wV1 and wV2
Vertex indices.

Remarks

The instruction count defines the number of line segments.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.


D3DLINEPATTERN

The D3DLINEPATTERN structure describes a line pattern. These values are used by the D3DRENDERSTATE_LINEPATTERN render state in the D3DRENDERSTATETYPE enumerated type.

typedef struct _D3DLINEPATTERN {
    WORD wRepeatFactor;
    WORD wLinePattern;
} D3DLINEPATTERN;

Members

wRepeatFactor
Number of times to duplicate each series of 1s and 0s specified in the wLinePattern member. This repeat factor allows an application to "stretch" the line pattern.
wLinePattern
Bits specifying the line pattern. For example, the following value would produce a dotted line: 1100110011001100.

Remarks

A line pattern specifies how a line is drawn. The line pattern is always the same, no matter where it is started. (This is as opposed to stippling, which affects how objects are rendered; that is, to imitate transparency.)

The line pattern specifies up to a 16-pixel pattern of on and off pixels along the line. The wRepeatFactor member specifies how many pixels are repeated for each entry in wLinePattern.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.


D3DLVERTEX

The D3DLVERTEX structure defines an untransformed and lit vertex (model coordinates with color). An application should use this structure when the vertex transformations will be handled by Direct3D. This structure contains only data and a color that would be filled by software lighting.

typedef struct _D3DLVERTEX {
    union {
        D3DVALUE x;
        D3DVALUE dvX;
    };
    union {
        D3DVALUE y;
        D3DVALUE dvY;
    };
    union {
        D3DVALUE z;
        D3DVALUE dvZ;
    };
    DWORD        dwReserved;
    union {
        D3DCOLOR color;
        D3DCOLOR dcColor;
    };
    union {
        D3DCOLOR specular;
        D3DCOLOR dcSpecular;
    };
    union {
        D3DVALUE tu;
        D3DVALUE dvTU;
    };
    union {
        D3DVALUE tv;
        D3DVALUE dvTV;
    };
} D3DLVERTEX, *LPD3DLVERTEX;

Members

dvX, dvY, and dvZ
Values of the D3DVALUE type specifying the model coordinates of the vertex.
dwReserved
Reserved; must be zero.
dcColor and dcSpecular
Values of the D3DCOLOR type specifying the color and specular component of the vertex.
dvTU and dvTV
Values of the D3DVALUE type specifying the texture coordinates of the vertex.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.

See Also

D3DTLVERTEX, D3DVERTEX


D3DMATERIAL

The D3DMATERIAL structure specifies material properties in calls to the IDirect3DMaterial3::GetMaterial and IDirect3DMaterial3::SetMaterial methods.

typedef struct _D3DMATERIAL {
    DWORD             dwSize;
    union {
        D3DCOLORVALUE diffuse;
        D3DCOLORVALUE dcvDiffuse;
    };
    union {
        D3DCOLORVALUE ambient;
        D3DCOLORVALUE dcvAmbient;
    };
    union {
        D3DCOLORVALUE specular;
        D3DCOLORVALUE dcvSpecular;
    };
    union {
        D3DCOLORVALUE emissive;
        D3DCOLORVALUE dcvEmissive;
    };
    union {
        D3DVALUE      power;
        D3DVALUE      dvPower;
    };
    D3DTEXTUREHANDLE  hTexture;     // Used only by Ramp devices.
    DWORD             dwRampSize;
} D3DMATERIAL, *LPD3DMATERIAL;

Members

dwSize
Size, in bytes, of this structure. This member must be initialized before the structure is used.
dcvDiffuse, dcvAmbient, dcvSpecular, and dcvEmissive
Values specifying the diffuse color, ambient color, specular color, and emissive color of the material, respectively. These values are D3DCOLORVALUE structures.
dvPower
Value of the D3DVALUE type specifying the sharpness of specular highlights.
hTexture
Handle to the texture map for use by a ramp device. This member can be zero to indicate that the material does not use a texture or when the material is being used with a device other than the ramp device.
dwRampSize
Size of the color ramp. For the monochromatic (ramp) driver, this value should be 1 for materials assigned to the background.

Remarks

The texture handle specified by the hTexture member is acquired from Direct3D by loading a texture into the device. The texture handle may be used only when it has been loaded into the device. This texture handle is only used by the legacy ramp device, which is not supported by interfaces introduced in DirectX 6.0, such as the new IDirect3DDevice3 interface. For more information, see Ramp Device.

To turn off specular highlights for a material, you must set the dvPower member to 0—simply setting the specular color components to 0 is not enough.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.

See Also

IDirect3DMaterial3::GetMaterial, IDirect3DMaterial3::SetMaterial


D3DMATRIX

The D3DMATRIX structure describes a matrix for such methods as IDirect3DDevice::GetMatrix and IDirect3DDevice::SetMatrix.

C++ programmers can use an extended version of this structure that includes a parentheses ("()") operator. For more information, see D3DMATRIX (D3D_OVERLOADS)

typedef struct _D3DMATRIX {
    D3DVALUE _11, _12, _13, _14;
    D3DVALUE _21, _22, _23, _24;
    D3DVALUE _31, _32, _33, _34;
    D3DVALUE _41, _42, _43, _44;
} D3DMATRIX, *LPD3DMATRIX;

Remarks

In Direct3D, the _34 element of a projection matrix cannot be a negative number. If your application needs to use a negative value in this location, it should scale the entire projection matrix by -1, instead.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.

See Also

IDirect3DDevice::GetMatrix, IDirect3DDevice::SetMatrix


D3DMATRIXLOAD

The D3DMATRIXLOAD structure describes the operand data for the D3DOP_MATRIXLOAD opcode in the D3DOPCODE enumerated type.

typedef struct _D3DMATRIXLOAD {
    D3DMATRIXHANDLE hDestMatrix;
    D3DMATRIXHANDLE hSrcMatrix;
} D3DMATRIXLOAD, *LPD3DMATRIXLOAD;

Members

hDestMatrix and hSrcMatrix
Handles to the destination and source matrices. These values are D3DMATRIX structures.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.

See Also

D3DOPCODE


D3DMATRIXMULTIPLY

The D3DMATRIXMULTIPLY structure describes the operand data for the D3DOP_MATRIXMULTIPLY opcode in the D3DOPCODE enumerated type.

typedef struct _D3DMATRIXMULTIPLY {
    D3DMATRIXHANDLE hDestMatrix;
    D3DMATRIXHANDLE hSrcMatrix1;
    D3DMATRIXHANDLE hSrcMatrix2;
} D3DMATRIXMULTIPLY, *LPD3DMATRIXMULTIPLY;

Members

hDestMatrix
Handle to the matrix that stores the product of the source matrices. This value is a D3DMATRIX structure.
hSrcMatrix1 and hSrcMatrix2
Handles of the first and second source matrices. These values are D3DMATRIX structures.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.

See Also

D3DOPCODE


D3DPICKRECORD

The D3DPICKRECORD structure returns information about picked primitives in an execute buffer for the IDirect3DDevice::GetPickRecords method.

typedef struct _D3DPICKRECORD {
    BYTE     bOpcode;
    BYTE     bPad;
    DWORD    dwOffset;
    D3DVALUE dvZ;
} D3DPICKRECORD, *LPD3DPICKRECORD;

Members

bOpcode
Opcode of the picked primitive.
bPad
Pad byte.
dwOffset
Offset from the start of the instruction segment portion of the execute buffer in which the picked primitive was found. (The instruction segment portion of the execute buffer is the part of the execute buffer that follows the vertex list.)
dvZ
Depth of the picked primitive.

Remarks

The x- and y-coordinates of the picked primitive are specified in the call to the IDirect3DDevice::Pick method that created the pick records.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.

See Also

IDirect3DDevice::GetPickRecords, IDirect3DDevice::Pick


D3DPOINT

The D3DPOINT structure describes operand data for the D3DOP_POINT opcode in the in D3DOPCODE enumerated type.

typedef struct _D3DPOINT {
    WORD wCount;
    WORD wFirst;
} D3DPOINT, *LPD3DPOINT;

Members

wCount
Number of points.
wFirst
Index of the first vertex.

Remarks

Points are rendered by using a list of vertices.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.

See Also

D3DOPCODE


D3DPRIMCAPS

The D3DPRIMCAPS structure defines the capabilities for each primitive type. This structure is used when creating a device and when querying the capabilities of a device. This structure defines several members in the D3DDEVICEDESC structure.

typedef struct _D3DPrimCaps {
    DWORD dwSize;                // size of structure
    DWORD dwMiscCaps;            // miscellaneous caps
    DWORD dwRasterCaps;          // raster caps
    DWORD dwZCmpCaps;            // z-comparison caps
    DWORD dwSrcBlendCaps;        // source blending caps
    DWORD dwDestBlendCaps;       // destination blending caps
    DWORD dwAlphaCmpCaps;        // alpha-test comparison caps
    DWORD dwShadeCaps;           // shading caps
    DWORD dwTextureCaps;         // texture caps
    DWORD dwTextureFilterCaps;   // texture filtering caps
    DWORD dwTextureBlendCaps;    // texture blending caps
    DWORD dwTextureAddressCaps;  // texture addressing caps
    DWORD dwStippleWidth;        // stipple width
    DWORD dwStippleHeight;       // stipple height
} D3DPRIMCAPS, *LPD3DPRIMCAPS;

Members

dwSize
Size, in bytes, of this structure. This member must be initialized before the structure is used.
dwMiscCaps
General capabilities for this primitive. This member can be one or more of the following:
D3DPMISCCAPS_CONFORMANT
The device conforms to the OpenGL standard.
D3DPMISCCAPS_CULLCCW
The driver supports counterclockwise culling through the D3DRENDERSTATE_CULLMODE state. (This applies only to triangle primitives.) This corresponds to the D3DCULL_CCW member of the D3DCULL enumerated type.
D3DPMISCCAPS_CULLCW
The driver supports clockwise triangle culling through the D3DRENDERSTATE_CULLMODE state. (This applies only to triangle primitives.) This corresponds to the D3DCULL_CW member of the D3DCULL enumerated type.
D3DPMISCCAPS_CULLNONE
The driver does not perform triangle culling. This corresponds to the D3DCULL_NONE member of the D3DCULL enumerated type.
D3DPMISCCAPS_LINEPATTERNREP
The driver can handle values other than 1 in the wRepeatFactor member of the D3DLINEPATTERN structure. (This applies only to line-drawing primitives.)
D3DPMISCCAPS_MASKPLANES
The device can perform a bitmask of color planes.
D3DPMISCCAPS_MASKZ
The device can enable and disable modification of the depth-buffer on pixel operations.
dwRasterCaps
Information on raster-drawing capabilities. This member can be one or more of the following:
D3DPRASTERCAPS_ANISOTROPY
The device supports anisotropic filtering. For more information, see D3DRENDERSTATE_ANISOTROPY in the D3DRENDERSTATETYPE structure.

This flag was introduced in DirectX 5.0.

D3DPRASTERCAPS_ANTIALIASEDGES
The device can antialias lines forming the convex outline of objects. For more information, see D3DRENDERSTATE_EDGEANTIALIAS in the D3DRENDERSTATETYPE structure.

This flag was introduced in DirectX 5.0.

D3DPRASTERCAPS_ANTIALIASSORTDEPENDENT
The device supports antialiasing that is dependent on the sort order of the polygons (back-to-front or front-to-back). The application must draw polygons in the right order for antialiasing to occur. For more information, see the D3DANTIALIASMODE enumerated type.

This flag was introduced in DirectX 5.0.

D3DPRASTERCAPS_ANTIALIASSORTINDEPENDENT
The device supports antialiasing that is not dependent on the sort order of the polygons. For more information, see the D3DANTIALIASMODE enumerated type.

This flag was introduced in DirectX 5.0.

D3DPRASTERCAPS_DITHER
The device can dither to improve color resolution.
D3DPRASTERCAPS_FOGRANGE
The device supports range-based fog. In range-based fog, the distance of an object from the viewer is used to compute fog effects, not the depth of the object (that is, the z-coordinate) in the scene. For more information, see Range-based Fog.

This flag was introduced in DirectX 5.0.

D3DPRASTERCAPS_FOGTABLE
The device calculates the fog value by referring to a lookup table containing fog values that are indexed to the depth of a given pixel.
D3DPRASTERCAPS_FOGVERTEX
The device calculates the fog value during the lighting operation, places the value into the alpha component of the D3DCOLOR value given for the specular member of the D3DTLVERTEX structure, and interpolates the fog value during rasterization.
D3DPRASTERCAPS_MIPMAPLODBIAS
The device supports level-of-detail (LOD) bias adjustments. These bias adjustments enable an application to make a mipmap appear crisper or less sharp than it normally would. For more information about LOD bias in mipmaps, see D3DRENDERSTATE_MIPMAPLODBIAS .

This flag was introduced in DirectX 5.0.

D3DPRASTERCAPS_PAT
The driver can perform patterned drawing (lines or fills with D3DRENDERSTATE_LINEPATTERN or one of the D3DRENDERSTATE_STIPPLEPATTERN render states) for the primitive being queried.
D3DPRASTERCAPS_ROP2
The device can support raster operations other than R2_COPYPEN.
D3DPRASTERCAPS_STIPPLE
The device can stipple polygons to simulate translucency.
D3DPRASTERCAPS_SUBPIXEL
The device performs subpixel placement of z, color, and texture data, rather than working with the nearest integer pixel coordinate. This helps avoid bleed-through due to z imprecision, and jitter of color and texture values for pixels. Note that there is no corresponding state that can be enabled and disabled; the device either performs subpixel placement or it does not, and this bit is present only so that the Direct3D client will be better able to determine what the rendering quality will be.
D3DPRASTERCAPS_SUBPIXELX
The device is subpixel accurate along the x-axis only and is clamped to an integer y-axis scan line. For information about subpixel accuracy, see D3DPRASTERCAPS_SUBPIXEL.
D3DPRASTERCAPS_TRANSLUCENTSORTINDEPENDENT
The device supports translucency that is not dependent on the sort order of the polygons. For more information, see the D3DRENDERSTATE_TRANSLUCENTSORTINDEPENDENT.
D3DPRASTERCAPS_WBUFFER
The device supports depth buffering using w. For more information, see Depth Buffers.
D3DPRASTERCAPS_WFOG
The device supports w-based fog. W-based fog is used when a perspective projection matrix is specified, but affine projections will still use z-based fog. The system considers a projection matrix that contains a non-zero value in the [3][4] element to be a perspective projection matrix.
D3DPRASTERCAPS_XOR
The device can support XOR operations. If this flag is not set but D3DPRIM_RASTER_ROP2 is set, then XOR operations must still be supported.
D3DPRASTERCAPS_ZBIAS
The device supports z-bias values. These are integer values assigned to polygons that allow physically coplanar polygons to appear separate. For more information, see D3DRENDERSTATE_ZBIAS in the D3DRENDERSTATETYPE enumerated type.

This flag was introduced in DirectX 5.0.

D3DPRASTERCAPS_ZBUFFERLESSHSR
The device can perform hidden-surface removal (HSR) without requiring the application to sort polygons, and without requiring the allocation of a depth-buffer. This leaves more video memory for textures. The method used to perform hidden-surface removal is hardware-dependent and is transparent to the application.

Z-bufferless HSR is performed if no depth-buffer surface is attached to the rendering-target surface and the depth-buffer comparison test is enabled (that is, when the state value associated with the D3DRENDERSTATE_ZENABLE enumeration constant is set to TRUE).

This flag was introduced in DirectX 5.0.

D3DPRASTERCAPS_ZTEST
The device can perform z-test operations. This effectively renders a primitive and indicates whether any z pixels would have been rendered.
dwZCmpCaps
Z-buffer comparison functions that the driver can perform. This member can be one or more of the following:
D3DPCMPCAPS_ALWAYS
Always pass the z test.
D3DPCMPCAPS_EQUAL
Pass the z test if the new z equals the current z.
D3DPCMPCAPS_GREATER
Pass the z test if the new z is greater than the current z.
D3DPCMPCAPS_GREATEREQUAL
Pass the z test if the new z is greater than or equal to the current z.
D3DPCMPCAPS_LESS
Pass the z test if the new z is less than the current z.
D3DPCMPCAPS_LESSEQUAL
Pass the z test if the new z is less than or equal to the current z.
D3DPCMPCAPS_NEVER
Always fail the z test.
D3DPCMPCAPS_NOTEQUAL
Pass the z test if the new z does not equal the current z.
dwSrcBlendCaps
Source blending capabilities. This member can be one or more of the following. (The RGBA values of the source and destination are indicated with the subscripts s and d.)
D3DPBLENDCAPS_BOTHINVSRCALPHA
Source blend factor is (1-As, 1-As, 1-As, 1-As) and destination blend factor is (As, As, As, As); the destination blend selection is overridden.
D3DPBLENDCAPS_BOTHSRCALPHA
The driver supports the D3DBLEND_BOTHSRCALPHA blend mode. (This blend mode is obsolete for DirectX 6.0 and later. For more information, see D3DBLEND.)
D3DPBLENDCAPS_DESTALPHA
Blend factor is (Ad, Ad, Ad, Ad).
D3DPBLENDCAPS_DESTCOLOR
Blend factor is (Rd, Gd, Bd, Ad).
D3DPBLENDCAPS_INVDESTALPHA
Blend factor is (1-Ad, 1-Ad, 1-Ad, 1-Ad).
D3DPBLENDCAPS_INVDESTCOLOR
Blend factor is (1-Rd, 1-Gd, 1-Bd, 1-Ad).
D3DPBLENDCAPS_INVSRCALPHA
Blend factor is (1-As, 1-As, 1-As, 1-As).
D3DPBLENDCAPS_INVSRCCOLOR
Blend factor is (1-Rd, 1-Gd, 1-Bd, 1-Ad).
D3DPBLENDCAPS_ONE
Blend factor is (1, 1, 1, 1).
D3DPBLENDCAPS_SRCALPHA
Blend factor is (As, As, As, As).
D3DPBLENDCAPS_SRCALPHASAT
Blend factor is (f, f, f, 1); f = min(As, 1-Ad).
D3DPBLENDCAPS_SRCCOLOR
Blend factor is (Rs, Gs, Bs, As).
D3DPBLENDCAPS_ZERO
Blend factor is (0, 0, 0, 0).
dwDestBlendCaps
Destination blending capabilities. This member can be the same capabilities that are defined for the dwSrcBlendCaps member.
dwAlphaCmpCaps
Alpha-test comparison functions that the driver can perform. This member can include the same capability flags defined for the dwZCmpCaps member. If this member contains only the D3DPCMPCAPS_ALWAYS capability or only the D3DPCMPCAPS_NEVER capability, the driver does not support alpha tests. Otherwise, the flags identify the individual comparisons that are supported for alpha testing.
dwShadeCaps
Shading operations that the device can perform. It is assumed, in general, that if a device supports a given command (such as D3DOP_TRIANGLE) at all, it supports the D3DSHADE_FLAT mode (as specified in the D3DSHADEMODE enumerated type). This flag specifies whether the driver can also support Gouraud and Phong shading and whether alpha color components are supported for each of the three color-generation modes. When alpha components are not supported in a given mode, the alpha value of colors generated in that mode is implicitly 255. This is the maximum possible alpha (that is, the alpha component is at full intensity).

With the monochromatic shade modes, the blue channel of the specular component is interpreted as a white intensity. (This is controlled by the D3DRENDERSTATE_MONOENABLE render state.)

The color, specular highlights, fog, and alpha interpolants of a triangle each have capability flags that an application can use to find out how they are implemented by the device driver. These are modified by the shade mode, color model, and by whether the alpha component of a color is blended or stippled. For more information, see 3-D Primitives.

This member can be one or more of the following:

D3DPSHADECAPS_ALPHAFLATBLEND
D3DPSHADECAPS_ALPHAFLATSTIPPLED
Device can support an alpha component for flat blended and stippled transparency, respectively (the D3DSHADE_FLAT state for the D3DSHADEMODE enumerated type). In these modes, the alpha color component for a primitive is provided as part of the color for the first vertex of the primitive.
D3DPSHADECAPS_ALPHAGOURAUDBLEND
D3DPSHADECAPS_ALPHAGOURAUDSTIPPLED
Device can support an alpha component for Gouraud blended and stippled transparency, respectively (the D3DSHADE_GOURAUD state for the D3DSHADEMODE enumerated type). In these modes, the alpha color component for a primitive is provided at vertices and interpolated across a face along with the other color components.
D3DPSHADECAPS_ALPHAPHONGBLEND
D3DPSHADECAPS_ALPHAPHONGSTIPPLED
Device can support an alpha component for Phong blended and stippled transparency, respectively (the D3DSHADE_PHONG state for the D3DSHADEMODE enumerated type). In these modes, vertex parameters are reevaluated on a per-pixel basis, applying lighting effects for the red, green, and blue color components. Phong shading is not currently supported.
D3DPSHADECAPS_COLORFLATMONO
D3DPSHADECAPS_COLORFLATRGB
Device can support colored flat shading in the D3DCOLOR_MONO and D3DCOLOR_RGB color models, respectively. In these modes, the color component for a primitive is provided as part of the color for the first vertex of the primitive. In monochromatic lighting modes, only the blue component of the color is interpolated; in RGB lighting modes, the red, green, and blue components are interpolated.
D3DPSHADECAPS_COLORGOURAUDMONO
D3DPSHADECAPS_COLORGOURAUDRGB
Device can support colored Gouraud shading in the D3DCOLOR_MONO and D3DCOLOR_RGB color models, respectively. In these modes, the color component for a primitive is provided at vertices and interpolated across a face along with the other color components. In monochromatic lighting modes, only the blue component of the color is interpolated; in RGB lighting modes, the red, green, and blue components are interpolated.
D3DPSHADECAPS_COLORPHONGMONO
D3DPSHADECAPS_COLORPHONGRGB
Device can support colored Phong shading in the D3DCOLOR_MONO and D3DCOLOR_RGB color models, respectively. In these modes, vertex parameters are reevaluated on a per-pixel basis. Lighting effects are applied for the red, green, and blue color components in RGB mode, and for the blue component only for monochromatic mode. Phong shading is not currently supported.
D3DPSHADECAPS_FOGFLAT
D3DPSHADECAPS_FOGGOURAUD
D3DPSHADECAPS_FOGPHONG
Device can support fog in the flat, Gouraud, and Phong shading models, respectively. Phong shading is not currently supported.
D3DPSHADECAPS_SPECULARFLATMONO
D3DPSHADECAPS_SPECULARFLATRGB
Device can support specular highlights in flat shading in the D3DCOLOR_MONO and D3DCOLOR_RGB color models, respectively.
D3DPSHADECAPS_SPECULARGOURAUDMONO
D3DPSHADECAPS_SPECULARGOURAUDRGB
Device can support specular highlights in Gouraud shading in the D3DCOLOR_MONO and D3DCOLOR_RGB color models, respectively.
D3DPSHADECAPS_SPECULARPHONGMONO
D3DPSHADECAPS_SPECULARPHONGRGB
Device can support specular highlights in Phong shading in the D3DCOLOR_MONO and D3DCOLOR_RGB color models, respectively. Phong shading is not currently supported.
dwTextureCaps
Miscellaneous texture-mapping capabilities. This member can be one or more of the following:
D3DPTEXTURECAPS_ALPHA
Supports RGBA textures in the D3DTBLEND_DECAL and D3DTBLEND_MODULATE texture filtering modes. If this capability is not set, then only RGB textures are supported in those modes. Regardless of the setting of this flag, alpha must always be supported in D3DTBLEND_DECALMASK, D3DTBLEND_DECALALPHA, and D3DTBLEND_MODULATEALPHA filtering modes whenever those filtering modes are available.
D3DPTEXTURECAPS_ALPHAPALETTE
Supports palettized texture surfaces whose palettes contain alpha information (see DDPCAPS_ALPHA in the DDCAPS structure).
D3DPTEXTURECAPS_BORDER
Superseded by D3DPTADDRESSCAPS_BORDER.
D3DPTEXTURECAPS_NONPOW2CONDITIONAL
Conditionally supports the use of textures with dimensions that are not powers of two. A device that exposes this capability can use such a texture if all of the following requirements are met.
  • The texture addressing mode for the texture stage is set to D3DTADDRESS_CLAMP.
  • Texture wrapping for the texture stage is disabled (D3DRENDERSTATE_WRAPn set to zero).
  • Mipmapping is not in use. (Mipmapped textures must have dimensions that are powers of two.)
  • Anisotropic texture filtering is disabled.
D3DPTEXTURECAPS_PERSPECTIVE
Perspective correction is supported.
D3DPTEXTURECAPS_POW2
All nonmipmapped textures must have widths and heights specified as powers of two if this flag is set. (Note that all mipmapped textures must always have dimensions that are powers of two.)
D3DPTEXTURECAPS_SQUAREONLY
All textures must be square.
D3DPTEXTURECAPS_TEXREPEATNOTSCALEDBYSIZE
Texture indices are not scaled by the texture size prior to interpolation.
D3DPTEXTURECAPS_TRANSPARENCY
Texture transparency is supported. (Only those texels that are not the current transparent color are drawn.)
dwTextureFilterCaps
Texture-map filtering capabilities. General texture filtering flags reflect which texture filtering modes you can set for the D3DRENDERSTATE_TEXTUREMAG, D3DRENDERSTATE_TEXTUREMIN render states. Per-stage filtering capabilities reflect which filtering modes are supported for texture stages when performing multiple texture blending with the IDirect3DDevice3 interface. This member be can any combination of the following general and per-stage texture filtering flags:
General texture filtering flags
D3DPTFILTERCAPS_LINEAR
Bilinear filtering. Chooses the texel that has nearest coordinates, then performs a weighted average with the four surrounding texels to determine the final color. This applies to both zooming in and zooming out. If either zooming in or zooming out is supported, then both must be supported.
D3DPTFILTERCAPS_LINEARMIPLINEAR
Trilinear interpolation between mipmaps. Performs bilinear filtering on the two nearest mipmaps, then interpolates linearly between the two colors to determine a final color.
D3DPTFILTERCAPS_LINEARMIPNEAREST
Linear interpolation between two point sampled mipmaps. Chooses the nearest texel from the two closest mipmap levels, then performs linear interpolation between them.
D3DPTFILTERCAPS_MIPLINEAR
Nearest mipmapping, with bilinear filtering applied to the result. Chooses the texel from the appropriate mipmap that has nearest coordinates, then performs a weighted average with the four surrounding texels to determine the final color.
D3DPTFILTERCAPS_MIPNEAREST
Nearest mipmapping. Chooses the texel from the appropriate mipmap with coordinates nearest to the desired pixel value.
D3DPTFILTERCAPS_NEAREST
Point sampling. The texel with coordinates nearest to the desired pixel value is used. This applies to both zooming in and zooming out. If either zooming in or zooming out is supported, then both must be supported.
Per-stage texture filtering flags
D3DPTFILTERCAPS_MAGFAFLATCUBIC
The device supports per-stage flat-cubic filtering for magnifying textures. The flat-cubic magnification filter is represented by the D3DTFG_FLATCUBIC member of the D3DTEXTUREMAGFILTER enumerated type.
D3DPTFILTERCAPS_MAGFANISOTROPIC
The device supports per-stage anisotropic filtering for magnifying textures. The anisotropic magnification filter is represented by the D3DTFG_ANISOTROPIC member of the D3DTEXTUREMAGFILTER enumerated type.
D3DPTFILTERCAPS_MAGFGAUSSIANCUBIC
The device supports the per-stage Gaussian-cubic filtering for magnifying textures. The Gaussian-cubic magnification filter is represented by the D3DTFG_GAUSSIANCUBIC member of the D3DTEXTUREMAGFILTER enumerated type.
D3DPTFILTERCAPS_MAGFLINEAR
The device supports per-stage bilinear-interpolation filtering for magnifying textures. The bilinear-interpolation magnification filter is represented by the D3DTFG_LINEAR member of the D3DTEXTUREMAGFILTER enumerated type.
D3DPTFILTERCAPS_MAGFPOINT
The device supports per-stage point-sampled filtering for magnifying textures. The point-sample magnification filter is represented by the D3DTFG_POINT member of the D3DTEXTUREMAGFILTER enumerated type.
D3DPTFILTERCAPS_MINFANISOTROPIC
The device supports per-stage anisotropic filtering for minifying textures. The anisotropic minification filter is represented by the D3DTFN_ANISOTROPIC member of the D3DTEXTUREMINFILTER enumerated type.
D3DPTFILTERCAPS_MINFLINEAR
The device supports per-stage bilinear-interpolation filtering for minifying textures. The bilinear minification filter is represented by the D3DTFN_LINEAR member of the D3DTEXTUREMINFILTER enumerated type.
D3DPTFILTERCAPS_MINFPOINT
The device supports per-stage point-sampled filtering for minifying textures. The point-sample minification filter is represented by the D3DTFN_POINT member of the D3DTEXTUREMINFILTER enumerated type.
D3DPTFILTERCAPS_MIPFLINEAR
The device supports per-stage trilinear-interpolation filtering for mipmaps. The trilinear-interpolation mipmapping filter is represented by the D3DTFP_LINEAR member of the D3DTEXTUREMIPFILTER enumerated type.
D3DPTFILTERCAPS_MIPFPOINT
The device supports per-stage point-sampled filtering for mipmaps. The point-sample mipmapping filter is represented by the D3DTFP_POINT member of the D3DTEXTUREMIPFILTER enumerated type.
dwTextureBlendCaps
Texture-blending capabilities. See the D3DTEXTUREBLEND enumerated type for discussions of the various texture-blending modes. This member can be one or more of the following:
D3DPTBLENDCAPS_ADD
Supports the additive texture-blending mode, in which the Gouraud interpolants are added to the texture lookup with saturation semantics. This capability corresponds to the D3DTBLEND_ADD member of the D3DTEXTUREBLEND enumerated type.

This flag was introduced in DirectX 5.0.

D3DPTBLENDCAPS_COPY
Copy mode texture-blending (D3DTBLEND_COPY from the D3DTEXTUREBLEND enumerated type) is supported.
D3DPTBLENDCAPS_DECAL
Decal texture-blending mode (D3DTBLEND_DECAL from the D3DTEXTUREBLEND enumerated type) is supported.
D3DPTBLENDCAPS_DECALALPHA
Decal-alpha texture-blending mode (D3DTBLEND_DECALALPHA from the D3DTEXTUREBLEND enumerated type) is supported.
D3DPTBLENDCAPS_DECALMASK
Decal-mask texture-blending mode (D3DTBLEND_DECALMASK from the D3DTEXTUREBLEND enumerated type) is supported.
D3DPTBLENDCAPS_MODULATE
Modulate texture-blending mode (D3DTBLEND_MODULATE from the D3DTEXTUREBLEND enumerated type) is supported.
D3DPTBLENDCAPS_MODULATEALPHA
Modulate-alpha texture-blending mode (D3DTBLEND_MODULATEALPHA from the D3DTEXTUREBLEND enumerated type) is supported.
D3DPTBLENDCAPS_MODULATEMASK
Modulate-mask texture-blending mode (D3DTBLEND_MODULATEMASK from the D3DTEXTUREBLEND enumerated type) is supported.
dwTextureAddressCaps
Texture-addressing capabilities. This member can be one or more of the following:
D3DPTADDRESSCAPS_BORDER
Device supports setting coordinates outside the range [0.0, 1.0] to the border color, as specified by the D3DRENDERSTATE_BORDERCOLOR render state. This ability corresponds to the D3DTADDRESS_BORDER texture-addressing mode.

This flag was introduced in DirectX 5.0.

D3DPTADDRESSCAPS_CLAMP
Device can clamp textures to addresses.
D3DPTADDRESSCAPS_INDEPENDENTUV
Device can separate the texture-addressing modes of the u and v coordinates of the texture. This ability corresponds to the D3DRENDERSTATE_TEXTUREADDRESSU and D3DRENDERSTATE_TEXTUREADDRESSV render-state values.

This flag was introduced in DirectX 5.0.

D3DPTADDRESSCAPS_MIRROR
Device can mirror textures to addresses.
D3DPTADDRESSCAPS_WRAP
Device can wrap textures to addresses.
dwStippleWidth and dwStippleHeight
Maximum width and height of the supported stipple (up to 32×32).

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dcaps.h.


D3DPROCESSVERTICES

The D3DPROCESSVERTICES structure describes how vertices in the execute buffer should be handled by the driver. This is used by the D3DOP_PROCESSVERTICES opcode in the D3DOPCODE enumerated type.

typedef struct _D3DPROCESSVERTICES {
    DWORD dwFlags;
    WORD  wStart;
    WORD  wDest;
    DWORD dwCount;
    DWORD dwReserved;
} D3DPROCESSVERTICES, *LPD3DPROCESSVERTICES;

Members

dwFlags
One or more of the following flags indicating how the driver should process the vertices:
D3DPROCESSVERTICES_COPY
Vertices should simply be copied to the driver, because they have always been transformed and lit. If all the vertices in the execute buffer can be copied, the driver does not need to do the work of processing the vertices, and a performance improvement results.
D3DPROCESSVERTICES_NOCOLOR
Vertices should not be colored.
D3DPROCESSVERTICES_OPMASK
Specifies a bitmask of the other flags in the dwFlags member, exclusive of D3DPROCESSVERTICES_NOCOLOR and D3DPROCESSVERTICES_UPDATEEXTENTS.
D3DPROCESSVERTICES_TRANSFORM
Vertices should be transformed.
D3DPROCESSVERTICES_TRANSFORMLIGHT
Vertices should be transformed and lit.
D3DPROCESSVERTICES_UPDATEEXTENTS
Extents of all transformed vertices should be updated. This information is returned in the drExtent member of the D3DSTATUS structure.
wStart
Index of the first vertex in the source.
wDest
Index of the first vertex in the local buffer.
dwCount
Number of vertices to be processed.
dwReserved
Reserved; must be zero.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.

See Also

D3DOPCODE


D3DRECT

The D3DRECT structure is a rectangle definition.

typedef struct _D3DRECT {
    union {
        LONG x1;
        LONG lX1;
    };
    union {
        LONG y1;
        LONG lY1;
    };
    union {
        LONG x2;
        LONG lX2;
    };
    union {
        LONG y2;
        LONG lY2;
    };
} D3DRECT, *LPD3DRECT;

Members

lX1 and lY1
Coordinates of the upper-left corner of the rectangle.
lX2 and lY2
Coordinates of the lower-right corner of the rectangle.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.

See Also

IDirect3DDevice::Pick, IDirect3DViewport3::Clear


D3DSPAN

The D3DSPAN structure defines a span for the D3DOP_SPAN opcode in the D3DOPCODE enumerated type. Spans join a list of points with the same y-value. If the y-value changes, a new span is started.

typedef struct _D3DSPAN {
    WORD wCount;
    WORD wFirst;
} D3DSPAN, *LPD3DSPAN;

Members

wCount
Number of spans.
wFirst
Index to first vertex.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.

See Also

D3DOPCODE


D3DSTATE

The D3DSTATE structure describes the render state for the D3DOP_STATETRANSFORM, D3DOP_STATELIGHT, and D3DOP_STATERENDER opcodes in the D3DOPCODE enumerated type. The first member of this structure is the relevant enumerated type and the second is the value for that type.

typedef struct _D3DSTATE {
    union {
        D3DTRANSFORMSTATETYPE dtstTransformStateType;
        D3DLIGHTSTATETYPE     dlstLightStateType;
        D3DRENDERSTATETYPE    drstRenderStateType;
    };
    union {
        DWORD                 dwArg[1];
        D3DVALUE              dvArg[1];
    };
} D3DSTATE, *LPD3DSTATE;

Members

dtstTransformStateType, dlstLightStateType, and drstRenderStateType
One of the members of the D3DTRANSFORMSTATETYPE, D3DLIGHTSTATETYPE, or D3DRENDERSTATETYPE enumerated type specifying the render state.
dvArg
Value of the type specified in the first member of this structure.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.

See Also

D3DLIGHTSTATETYPE, D3DOPCODE, D3DRENDERSTATETYPE, and D3DTRANSFORMSTATETYPE, D3DVALUE


D3DSTATS

The D3DSTATS structure contains statistics used by the IDirect3DDevice3::GetStats method.

typedef struct _D3DSTATS {
    DWORD dwSize;
    DWORD dwTrianglesDrawn;
    DWORD dwLinesDrawn;
    DWORD dwPointsDrawn;
    DWORD dwSpansDrawn;
    DWORD dwVerticesProcessed;
} D3DSTATS, *LPD3DSTATS;

Members

dwSize
Size, in bytes, of this structure. This member must be initialized before the structure is used.
dwTrianglesDrawn, dwLinesDrawn, dwPointsDrawn, and dwSpansDrawn
Number of triangles, lines, points, and spans drawn since the device was created.
dwVerticesProcessed
Number of vertices processed since the device was created.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.

See Also

IDirect3DDevice3::GetStats


D3DSTATUS

The D3DSTATUS structure describes the current status of the execute buffer. This structure is part of the D3DEXECUTEDATA structure and is used with the D3DOP_SETSTATUS opcode in the D3DOPCODE enumerated type.

typedef struct _D3DSTATUS {
    DWORD   dwFlags;
    DWORD   dwStatus;
    D3DRECT drExtent;
} D3DSTATUS, *LPD3DSTATUS;

Members

dwFlags
One of the following flags, specifying whether the status, the extents, or both are being set:
D3DSETSTATUS_STATUS
Set the status.
D3DSETSTATUS_EXTENTS
Set the extents specified in the drExtent member.
D3DSETSTATUS_ALL
Set both the status and the extents.
dwStatus
Clipping flags. This member can be one or more of the following flags:

Combination and General Flags

D3DSTATUS_CLIPINTERSECTIONALL
Combination of all CLIPINTERSECTION flags.
D3DSTATUS_CLIPUNIONALL
Combination of all CLIPUNION flags.
D3DSTATUS_DEFAULT
Combination of D3DSTATUS_CLIPINTERSECTIONALL and D3DSTATUS_ZNOTVISIBLE flags. This value is the default.
D3DSTATUS_ZNOTVISIBLE
Indicates that the rendered primitive is not visible. This flag is set or cleared by the system when rendering with z-checking enabled (see D3DRENDERSTATE_ZVISIBLE).

Clip Intersection Flags

D3DSTATUS_CLIPINTERSECTIONBACK
Logical AND of the clip flags for the vertices compared to the back clipping plane of the viewing frustum.
D3DSTATUS_CLIPINTERSECTIONBOTTOM
Logical AND of the clip flags for the vertices compared to the bottom of the viewing frustum.
D3DSTATUS_CLIPINTERSECTIONFRONT
Logical AND of the clip flags for the vertices compared to the front clipping plane of the viewing frustum.
D3DSTATUS_CLIPINTERSECTIONGEN0 through D3DSTATUS_CLIPINTERSECTIONGEN5
Logical AND of the clip flags for application-defined clipping planes.
D3DSTATUS_CLIPINTERSECTIONLEFT
Logical AND of the clip flags for the vertices compared to the left side of the viewing frustum.
D3DSTATUS_CLIPINTERSECTIONRIGHT
Logical AND of the clip flags for the vertices compared to the right side of the viewing frustum.
D3DSTATUS_CLIPINTERSECTIONTOP
Logical AND of the clip flags for the vertices compared to the top of the viewing frustum.

Clip Union Flags

D3DSTATUS_CLIPUNIONBACK
Equal to D3DCLIP_BACK.
D3DSTATUS_CLIPUNIONBOTTOM
Equal to D3DCLIP_BOTTOM.
D3DSTATUS_CLIPUNIONFRONT
Equal to D3DCLIP_FRONT.
D3DSTATUS_CLIPUNIONGEN0 through D3DSTATUS_CLIPUNIONGEN5
Equal to D3DCLIP_GEN0 through D3DCLIP_GEN5.
D3DSTATUS_CLIPUNIONLEFT
Equal to D3DCLIP_LEFT.
D3DSTATUS_CLIPUNIONRIGHT
Equal to D3DCLIP_RIGHT.
D3DSTATUS_CLIPUNIONTOP
Equal to D3DCLIP_TOP.

Basic Clipping Flags

D3DCLIP_BACK
All vertices are clipped by the back plane of the viewing frustum.
D3DCLIP_BOTTOM
All vertices are clipped by the bottom plane of the viewing frustum.
D3DCLIP_FRONT
All vertices are clipped by the front plane of the viewing frustum.
D3DCLIP_LEFT
All vertices are clipped by the left plane of the viewing frustum.
D3DCLIP_RIGHT
All vertices are clipped by the right plane of the viewing frustum.
D3DCLIP_TOP
All vertices are clipped by the top plane of the viewing frustum.
D3DCLIP_GEN0 through D3DCLIP_GEN5
Application-defined clipping planes.
drExtent
A D3DRECT structure that defines a bounding box for all the relevant vertices. For example, the structure might define the area containing the output of the D3DOP_PROCESSVERTICES opcode, assuming the D3DPROCESSVERTICES_UPDATEEXTENTS flag is set in the D3DPROCESSVERTICES structure.

Remarks

The status is a rolling status and is updated during each execution. The bounding box in the drExtent member can grow with each execution, but it does not shrink; it can be reset only by using the D3DOP_SETSTATUS opcode.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.

See Also

D3DEXECUTEDATA, D3DOPCODE, D3DRECT


D3DTEXTURELOAD

The D3DTEXTURELOAD structure describes operand data for the D3DOP_TEXTURELOAD opcode in the D3DOPCODE enumerated type.

typedef struct _D3DTEXTURELOAD {
    D3DTEXTUREHANDLE hDestTexture;
    D3DTEXTUREHANDLE hSrcTexture;
} D3DTEXTURELOAD, *LPD3DTEXTURELOAD;

Members

hDestTexture
Handle to the destination texture.
hSrcTexture
Handle to the source texture.

Remarks

The textures referred to by the hDestTexture and hSrcTexture members must be the same size.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.


D3DTLVERTEX

The D3DTLVERTEX structure defines a transformed and lit vertex (screen coordinates with color) for the D3DLIGHTDATA structure.

typedef struct _D3DTLVERTEX {
    union {
        D3DVALUE sx;
        D3DVALUE dvSX;
    };
    union {
        D3DVALUE sy;
        D3DVALUE dvSY;
    };
    union {
        D3DVALUE sz;
        D3DVALUE dvSZ;
    };
    union {
        D3DVALUE rhw;
        D3DVALUE dvRHW;
    };
    union {
        D3DCOLOR color;
        D3DCOLOR dcColor;
    };
    union {
        D3DCOLOR specular;
        D3DCOLOR dcSpecular;
    };
    union {
        D3DVALUE tu;
        D3DVALUE dvTU;
    };
    union {
        D3DVALUE tv;
        D3DVALUE dvTV;
    };
} D3DTLVERTEX, *LPD3DTLVERTEX;

Members

dvSX, dvSY, and dvSZ
Values of the D3DVALUE type describing a vertex in screen coordinates. The largest allowable value for dvSZ is 0.99999, if you want the vertex to be within the range of z-values that are displayed.
dvRHW
Value of the D3DVALUE type that is the reciprocal of homogeneous w from homogeneous coordinate (x,y,z,w). This value is often 1 divided by the distance from the origin to the object along the z-axis.
dcColor and dcSpecular
Values of the D3DCOLOR type describing the color and specular component of the vertex.
dvTU and dvTV
Values of the D3DVALUE type describing the texture coordinates of the vertex.

Remarks

Direct3D uses the current viewport parameters (the dwX, dwY, dwWidth, and dwHeight members of the D3DVIEWPORT2 structure) to clip D3DTLVERTEX vertices. The system always clips z-coordinates to [0, 1]. To prevent the system from clipping these vertices, use the D3DDP_DONOTCLIP flag in your call to IDirect3DDevice3::Begin.

Prior to DirectX 5.0, Direct3D did not clip D3DTLVERTEX vertices.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.

See Also

D3DLIGHTDATA, D3DLVERTEX, D3DVERTEX


D3DTRANSFORMCAPS

The D3DTRANSFORMCAPS structure describes the transformation capabilities of a device. This structure is part of the D3DDEVICEDESC structure.

typedef struct _D3DTransformCaps {
    DWORD dwSize;
    DWORD dwCaps;
} D3DTRANSFORMCAPS, *LPD3DTRANSFORMCAPS;

Members

dwSize
Size, in bytes, of this structure. This member must be initialized before the structure is used.
dwCaps
Flag specifying whether the system clips while transforming. This member can be zero or the following flag:
D3DTRANSFORMCAPS_CLIP
The system clips while transforming.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dcaps.h.


D3DTRANSFORMDATA

The D3DTRANSFORMDATA structure contains information about transformations for the IDirect3DViewport3::TransformVertices method.

typedef struct _D3DTRANSFORMDATA {
    DWORD        dwSize;
    LPVOID       lpIn;
    DWORD        dwInSize;
    LPVOID       lpOut;
    DWORD        dwOutSize;
    LPD3DHVERTEX lpHOut;
    DWORD        dwClip;
    DWORD        dwClipIntersection;
    DWORD        dwClipUnion;
    D3DRECT      drExtent;
} D3DTRANSFORMDATA, *LPD3DTRANSFORMDATA;

Members

dwSize
Size of the structure, in bytes. This member must be initialized before the structure is used.
lpIn
Address of the vertices to be transformed. This should be a D3DLVERTEX structure.
dwInSize
Stride of the vertices to be transformed.
lpOut
Address used to store the transformed vertices.
dwOutSize
Stride of output vertices.
lpHOut
Address of a value that contains homogeneous transformed vertices. This value is a D3DHVERTEX structure
dwClip
Flags specifying how the vertices are clipped. This member can be one or more of the following values:
D3DCLIP_BACK
Clipped by the back plane of the viewing frustum.
D3DCLIP_BOTTOM
Clipped by the bottom plane of the viewing frustum.
D3DCLIP_FRONT
Clipped by the front plane of the viewing frustum.
D3DCLIP_GEN0 through D3DCLIP_GEN5
Application-defined clipping planes.
D3DCLIP_LEFT
Clipped by the left plane of the viewing frustum.
D3DCLIP_RIGHT
Clipped by the right plane of the viewing frustum.
D3DCLIP_TOP
Clipped by the top plane of the viewing frustum_dx_viewing_frustum_glos.
dwClipIntersection
Flags denoting the intersection of the clip flags. This member can be one or more of the following values:
D3DSTATUS_CLIPINTERSECTIONBACK
Logical AND of the clip flags for the vertices compared to the back clipping plane of the viewing frustum.
D3DSTATUS_CLIPINTERSECTIONBOTTOM
Logical AND of the clip flags for the vertices compared to the bottom of the viewing frustum.
D3DSTATUS_CLIPINTERSECTIONFRONT
Logical AND of the clip flags for the vertices compared to the front clipping plane of the viewing frustum.
D3DSTATUS_CLIPINTERSECTIONGEN0 through D3DSTATUS_CLIPINTERSECTIONGEN5
Logical AND of the clip flags for application-defined clipping planes.
D3DSTATUS_CLIPINTERSECTIONLEFT
Logical AND of the clip flags for the vertices compared to the left side of the viewing frustum.
D3DSTATUS_CLIPINTERSECTIONRIGHT
Logical AND of the clip flags for the vertices compared to the right side of the viewing frustum.
D3DSTATUS_CLIPINTERSECTIONTOP
Logical AND of the clip flags for the vertices compared to the top of the viewing frustum.
dwClipUnion
Flags denoting the union of the clip flags. This member can be one or more of the following values:
D3DSTATUS_CLIPUNIONBACK
Equal to D3DCLIP_BACK.
D3DSTATUS_CLIPUNIONBOTTOM
Equal to D3DCLIP_BOTTOM.
D3DSTATUS_CLIPUNIONFRONT
Equal to D3DCLIP_FRONT.
D3DSTATUS_CLIPUNIONGEN0 through D3DSTATUS_CLIPUNIONGEN5
Equal to D3DCLIP_GEN0 through D3DCLIP_GEN5.
D3DSTATUS_CLIPUNIONLEFT
Equal to D3DCLIP_LEFT.
D3DSTATUS_CLIPUNIONRIGHT
Equal to D3DCLIP_RIGHT.
D3DSTATUS_CLIPUNIONTOP
Equal to D3DCLIP_TOP.
drExtent
A D3DRECT structure that defines the extents of the transformed vertices. Initialize this structure to initial extents that the IDirect3DViewport3::TransformVertices method will adjust if the transformed vertices do not fit. For geometries that are clipped, extents will only include vertices that are inside the viewing volume.

Remarks

Each input vertex should be a three-vector vertex giving the [x y z] coordinates in model space for the geometry. The dwInSize member gives the amount to skip between vertices, allowing the application to store extra data inline with each vertex.

All values generated by the transformation module are stored as 16-bit precision values. The clip is treated as an integer bitfield that is set to the inclusive OR of the viewing volume planes that clip a given transformed vertex.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.

See Also

IDirect3DViewport3::TransformVertices


D3DTRIANGLE

The D3DTRIANGLE structure describes the base type for all triangles. The triangle is the main rendering primitive.

For related information, see the D3DOP_TRIANGLE member in the D3DOPCODE enumerated type.

typedef struct _D3DTRIANGLE {
    union {
        WORD v1;
        WORD wV1;
    };
    union {
        WORD v2;
        WORD wV2;
    };
    union {
        WORD v3;
        WORD wV3;
    };
    WORD     wFlags;
} D3DTRIANGLE, *LPD3DTRIANGLE;

Members

wV1, wV2, and wV3
Vertices describing the triangle.
wFlags
This value can be a combination of the following flags:

Edge flags

These flags describe which edges of the triangle to enable. (This information is useful only in wireframe mode.)

D3DTRIFLAG_EDGEENABLE1
Edge defined by v1–v2.
D3DTRIFLAG_EDGEENABLE2
Edge defined by v2–v3.
D3DTRIFLAG_EDGEENABLE3
Edge defined by v3–v1.
D3DTRIFLAG_EDGEENABLETRIANGLE
All edges.

Strip and fan flags

D3DTRIFLAG_EVEN
The v1–v2 edge of the current triangle is adjacent to the v3–v1 edge of the previous triangle; that is, v1 is the previous v1, and v2 is the previous v3.
D3DTRIFLAG_ODD
The v1–v2 edge of the current triangle is adjacent to the v2–v3 edge of the previous triangle; that is, v1 is the previous v3, and v2 is the previous v2.
D3DTRIFLAG_START
Begin the strip or fan, loading all three vertices.
D3DTRIFLAG_STARTFLAT(len)
Cull or render the triangles in the strip or fan based on the treatment of this triangle. That is, if this triangle is culled, also cull the specified number of subsequent triangles. If this triangle is rendered, also render the specified number of subsequent triangles.

This length must be greater than zero and less than 30.

Remarks

This structure can be used directly for all triangle fills. For flat shading, the color and specular components are taken from the first vertex. The three vertex indices v1, v2, and v3 are vertex indexes into the vertex list at the start of the execute buffer.

Enabled edges are visible in wireframe mode. When an application displays wireframe triangles that share an edge, it typically enables only one (or neither) edge to avoid drawing the edge twice.

The D3DTRIFLAG_ODD and D3DTRIFLAG_EVEN flags refer to the locations of a triangle in a conventional triangle strip or fan. If a triangle strip had five triangles, the following flags would be used to define the strip:

D3DTRIFLAG_START
D3DTRIFLAG_ODD
D3DTRIFLAG_EVEN
D3DTRIFLAG_ODD
D3DTRIFLAG_EVEN

Similarly, the following flags would define a triangle fan with five triangles:

D3DTRIFLAG_START
D3DTRIFLAG_EVEN
D3DTRIFLAG_EVEN
D3DTRIFLAG_EVEN
D3DTRIFLAG_EVEN

The following flags could define a flat triangle fan with five triangles:

D3DTRIFLAG_STARTFLAT(4)
D3DTRIFLAG_EVEN
D3DTRIFLAG_EVEN
D3DTRIFLAG_EVEN
D3DTRIFLAG_EVEN

For more information, see Triangle Strips and Triangle Fans.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.


D3DVECTOR

The D3DVECTOR structure defines a vector for many Direct3D and Direct3DRM methods and structures.

typedef struct _D3DVECTOR {
    union {
        D3DVALUE x;
        D3DVALUE dvX;
    };
    union {
        D3DVALUE y;
        D3DVALUE dvY;
    };
    union {
        D3DVALUE z;
        D3DVALUE dvZ;
    };
} D3DVECTOR, *LPD3DVECTOR;

Members

dvX, dvY, and dvZ
Values of the D3DVALUE type describing the vector.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.

See Also

D3DLIGHT2, D3DLIGHTINGELEMENT


D3DVERTEX

The D3DVERTEX structure defines an untransformed and unlit vertex (model coordinates with normal direction vector).

For related information, see the D3DOP_TRIANGLE member in the D3DOPCODE enumerated type.

typedef struct _D3DVERTEX {
    union {
        D3DVALUE x;
        D3DVALUE dvX;
    };
    union {
        D3DVALUE y;
        D3DVALUE dvY;
    };
    union {
        D3DVALUE z;
        D3DVALUE dvZ;
    };
    union {
        D3DVALUE nx;
        D3DVALUE dvNX;
    };
    union {
        D3DVALUE ny;
        D3DVALUE dvNY;
    };
    union {
        D3DVALUE nz;
        D3DVALUE dvNZ;
    };
    union {
        D3DVALUE tu;
        D3DVALUE dvTU;
    };
    union {
        D3DVALUE tv;
        D3DVALUE dvTV;
    };
} D3DVERTEX, *LPD3DVERTEX;

Members

dvX, dvY, and dvZ
Values of the D3DVALUE type describing the homogeneous coordinates of the vertex.
dvNX, dvNY, and dvNZ
Values of the D3DVALUE type describing the normal coordinates of the vertex.
dvTU and dvTV
Values of the D3DVALUE type describing the texture coordinates of the vertex.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.

See Also

D3DLVERTEX, D3DTLVERTEX, D3DVALUE


D3DVERTEXBUFFERDESC

The D3DVERTEXBUFFERDESC structure describes the properties of a vertex buffer object. This structure is used with the IDirect3D3::CreateVertexBuffer and IDirect3DVertexBuffer::GetVertexBufferDesc methods.

typedef struct _D3DVERTEXBUFFERDESC {
    DWORD dwSize;
    DWORD dwCaps;
    DWORD dwFVF;
    DWORD dwNumVertices;
} D3DVERTEXBUFFERDESC, *LPD3DVERTEXBUFFERDESC;

Members

dwSize
Size of this structure, in bytes. This member must be initialized before the structure is used.
dwCaps
Capability flags that describe the vertex buffer and identify if the vertex buffer can contain optimized vertex data. This parameter can be any combination of the following flags:
(none)
The vertex buffer should be created in whatever memory the driver chooses to allow efficient read operations.
D3DVBCAPS_OPTIMIZED
The vertex buffer contains optimized vertex data. (This flag is not used when creating a new vertex buffer.)
D3DVBCAPS_SYSTEMMEMORY
The vertex buffer should be created in system memory. Use this capability for vertex buffers that will be rendered by using software devices (MMX and RGB devices).
D3DVBCAPS_WRITEONLY
Hints to the system that the application will only write to the vertex buffer. Using this flag enables the driver to choose the best memory location for efficient write operations and rendering. Attempts to read from a vertex buffer that is created with this capability can result in degraded performance.
dwFVF
A combination of flexible vertex format flags that describes the vertex format of the vertices in this buffer.
dwNumVertices
The maximum number of vertices that this vertex buffer can contain.

Remarks

Software devices—MMX and RGB devices—cannot render from a video memory (local or non-local) vertex buffer. To render a vertex buffer using a software device, the vertex buffer must exist in system memory. Hardware devices can render from system memory or video memory vertex buffers.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.

See Also

Vertex Buffer Descriptions, Vertex Buffers


D3DVIEWPORT

The D3DVIEWPORT structure defines the visible 3-D volume and the 2-D screen area that a 3-D volume projects onto for the IDirect3DViewport3::GetViewport and IDirect3DViewport3::SetViewport methods.

For the IDirect3D2 and IDirect3DDevice2 interfaces, this structure has been superseded by the D3DVIEWPORT2 structure.

typedef struct _D3DVIEWPORT {
    DWORD    dwSize;
    DWORD    dwX;
    DWORD    dwY;
    DWORD    dwWidth;
    DWORD    dwHeight;
    D3DVALUE dvScaleX;
    D3DVALUE dvScaleY;
    D3DVALUE dvMaxX;
    D3DVALUE dvMaxY;
    D3DVALUE dvMinZ;
    D3DVALUE dvMaxZ;
} D3DVIEWPORT, *LPD3DVIEWPORT;

Members

dwSize
Size of this structure, in bytes. This member must be initialized before the structure is used.
dwX and dwY
Coordinates of the top-left corner of the viewport.
dwWidth and dwHeight
Dimensions of the viewport.
dvScaleX and dvScaleY
Values of the D3DVALUE type describing how coordinates are scaled. The relevant coordinates here are the nonhomogeneous coordinates that result from the perspective division that projects the vertices onto the w=1 plane.
dvMaxX, dvMaxY, dvMinZ, and dvMaxZ
Values of the D3DVALUE type describing the maximum and minimum nonhomogeneous coordinates of x, y, and z. Again, the relevant coordinates are the nonhomogeneous coordinates that result from the perspective division.

Remarks

When the viewport is changed, the driver builds a new transformation matrix.

The coordinates and dimensions of the viewport are given relative to the top left of the device.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.

See Also

D3DVALUE, IDirect3DViewport3::GetViewport, IDirect3DViewport3::SetViewport


D3DVIEWPORT2

The D3DVIEWPORT2 structure defines the visible 3-D volume and the window dimensions that a 3-D volume projects onto. This structure is used by the methods of the IDirect3D2 and IDirect3DDevice2 interfaces, and in particular by the IDirect3DViewport3::GetViewport2 and IDirect3DViewport3::SetViewport2 methods. This structure was introduced in DirectX 5.0.

typedef struct _D3DVIEWPORT2 {
    DWORD       dwSize;
    DWORD       dwX;
    DWORD       dwY;
    DWORD       dwWidth;
    DWORD       dwHeight;
    D3DVALUE    dvClipX;
    D3DVALUE    dvClipY;
    D3DVALUE    dvClipWidth;
    D3DVALUE    dvClipHeight;
    D3DVALUE    dvMinZ;
    D3DVALUE    dvMaxZ;
} D3DVIEWPORT2, *LPD3DVIEWPORT2;

Members

dwSize
Size of this structure, in bytes. This member must be initialized before the structure is used.
dwX and dwY
Pixel coordinates of the top-left corner of the viewport on the render target surface. Unless you want to render to a subset of the surface, these members can be set to zero.
dwWidth and dwHeight
Dimensions of the viewport on the render target surface, in pixels. Unless you are rendering only to a subset of the surface, these members should be set to the dimensions of the render target surface.
dvClipX and dvClipY
Coordinates of the top-left corner of the clipping volume.

The relevant coordinates here are the nonhomogeneous coordinates that result from the perspective division that projects the vertices onto the w=1 plane.

dvClipWidth and dvClipHeight
Dimensions of the clipping volume projected onto the w=1 plane. Unless you want to render to a subset of the surface, these members can be set to the width and height of the destination surface.
dvMinZ and dvMaxZ
Values of the D3DVALUE type describing the maximum and minimum nonhomogeneous z-coordinates resulting from the perspective divide and projected onto the w=1 plane.

Remarks

The dwX, dwY, dwWidth and dwHeight members describe the position and dimensions of the viewport on the render target surface. Usually, applications render to the entire target surface; when rendering on a 640x480 surface, these members should be 0, 0, 640, and 480, respectively.

The dvClipX, dvClipY, dvClipWidth, dvClipHeight, dvMinZ, and dvMaxZ members define the non-normalized post-perspective 3-D view volume which is visible to the viewer. In most cases, dvClipX is set to -1.0 and dvClipY is set to the inverse of the viewport's aspect ratio on the target surface, which can be calculated by dividing the dwHeight member by dwWidth. Similarly, the dvClipWidth member is typically 2.0 and dvClipHeight is set to twice the aspect ratio set in dwClipY. The dvMinZ and dvMaxZ are usually set to 0.0 and 1.0.

Unlike the D3DVIEWPORT structure, D3DVIEWPORT2 specifies the relationship between the size of the viewport and the window. The coordinates and dimensions of the viewport are given relative to the top left of the device; values increase in the y-direction as you descend the screen.

When the viewport is changed, the driver builds a new transformation matrix.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.

See Also

D3DVALUE, IDirect3DViewport3::GetViewport2, IDirect3DViewport3::SetViewport2, Clipping Volumes, Viewports and Clipping


Enumerated Types

This section contains information about the following enumerated types used with Direct3D Immediate Mode.

  • D3DANTIALIASMODE
  • D3DBLEND
  • D3DCMPFUNC
  • D3DCULL
  • D3DFILLMODE
  • D3DFOGMODE
  • D3DLIGHTSTATETYPE
  • D3DLIGHTTYPE
  • D3DOPCODE
  • D3DPRIMITIVETYPE
  • D3DRENDERSTATETYPE
  • D3DSHADEMODE
  • D3DSTENCILOP
  • D3DTEXTUREADDRESS
  • D3DTEXTUREBLEND
  • D3DTEXTUREFILTER
  • D3DTEXTUREMAGFILTER
  • D3DTEXTUREMINFILTER
  • D3DTEXTUREMIPFILTER
  • D3DTEXTUREOP
  • D3DTEXTURESTAGESTATETYPE
  • D3DTRANSFORMSTATETYPE
  • D3DVERTEXTYPE
  • D3DZBUFFERTYPE


D3DANTIALIASMODE

The D3DANTIALIASMODE enumerated type defines the supported antialiasing mode for the D3DRENDERSTATE_ANTIALIAS value in the D3DRENDERSTATETYPE enumerated type. These values define the settings only for full-scene antialiasing (for more information, see Antialiasing).

typedef enum _D3DANTIALIASMODE {
    D3DANTIALIAS_NONE          = 0,
    D3DANTIALIAS_SORTDEPENDENT = 1,
    D3DANTIALIAS_SORTINDEPENDENT = 2
    D3DANTIALIAS_FORCE_DWORD     = 0x7fffffff,
} D3DANTIALIASMODE;

Members

D3DANTIALIAS_NONE
No antialiasing is performed. This is the default setting.
D3DANTIALIAS_SORTDEPENDENT
Antialiasing is dependent on the sort order of the polygons (back-to-front or front-to-back). The application must draw polygons in the right order for antialiasing to occur.
D3DANTIALIAS_SORTINDEPENDENT
Antialiasing is not dependent on the sort order of the polygons.
D3DANTIALIAS_FORCE_DWORD
Forces this enumerated type to be 32 bits in size.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.


D3DBLEND

The D3DBLEND enumerated type defines the supported blend mode for the D3DRENDERSTATE_DESTBLEND values in the D3DRENDERSTATETYPE enumerated type. In the member descriptions that follow, the RGBA values of the source and destination are indicated with the subscripts s and d.

typedef enum _D3DBLEND {
    D3DBLEND_ZERO            = 1,
    D3DBLEND_ONE             = 2,
    D3DBLEND_SRCCOLOR        = 3,
    D3DBLEND_INVSRCCOLOR     = 4,
    D3DBLEND_SRCALPHA        = 5,
    D3DBLEND_INVSRCALPHA     = 6,
    D3DBLEND_DESTALPHA       = 7,
    D3DBLEND_INVDESTALPHA    = 8,
    D3DBLEND_DESTCOLOR       = 9,
    D3DBLEND_INVDESTCOLOR    = 10,
    D3DBLEND_SRCALPHASAT     = 11,
    D3DBLEND_BOTHSRCALPHA    = 12,
    D3DBLEND_BOTHINVSRCALPHA = 13,
    D3DBLEND_FORCE_DWORD   = 0x7fffffff,
} D3DBLEND;

Members

D3DBLEND_ZERO
Blend factor is (0, 0, 0, 0).
D3DBLEND_ONE
Blend factor is (1, 1, 1, 1).
D3DBLEND_SRCCOLOR
Blend factor is (Rs, Gs, Bs, As).
D3DBLEND_INVSRCCOLOR
Blend factor is (1-Rs, 1-Gs, 1-Bs, 1-As).
D3DBLEND_SRCALPHA
Blend factor is (As, As, As, As).
D3DBLEND_INVSRCALPHA
Blend factor is (1-As, 1-As, 1-As, 1-As).
D3DBLEND_DESTALPHA
Blend factor is (Ad, Ad, Ad, Ad).
D3DBLEND_INVDESTALPHA
Blend factor is (1-Ad, 1-Ad, 1-Ad, 1-Ad).
D3DBLEND_DESTCOLOR
Blend factor is (Rd, Gd, Bd, Ad).
D3DBLEND_INVDESTCOLOR
Blend factor is (1-Rd, 1-Gd, 1-Bd, 1-Ad).
D3DBLEND_SRCALPHASAT
Blend factor is (f, f, f, 1); f = min(As, 1-Ad).
D3DBLEND_BOTHSRCALPHA
Obsolete. For DirectX 6.0 and later, you can achieve the same affect by setting the source and destination blend factors to D3DBLEND_SRCALPHA and D3DBLEND_INVSRCALPHA in separate calls.
D3DBLEND_BOTHINVSRCALPHA
Source blend factor is (1-As, 1-As, 1-As, 1-As), and destination blend factor is (As, As, As, As); the destination blend selection is overridden. This blend mode is supported only for the D3DRENDERSTATE_SRCBLEND render state.
D3DBLEND_FORCE_DWORD
Forces this enumerated type to be 32 bits in size.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.


D3DCMPFUNC

The D3DCMPFUNC enumerated type defines the supported compare functions for the D3DRENDERSTATE_ZFUNC, D3DRENDERSTATE_ALPHAFUNC, and D3DRENDERSTATE_STENCILFUNC render states.

typedef enum _D3DCMPFUNC {
    D3DCMP_NEVER        = 1,
    D3DCMP_LESS         = 2,
    D3DCMP_EQUAL        = 3,
    D3DCMP_LESSEQUAL    = 4,
    D3DCMP_GREATER      = 5,
    D3DCMP_NOTEQUAL     = 6,
    D3DCMP_GREATEREQUAL = 7,
    D3DCMP_ALWAYS       = 8,
    D3DCMP_FORCE_DWORD   = 0x7fffffff,
} D3DCMPFUNC;

Members

D3DCMP_NEVER
Always fail the test.
D3DCMP_LESS
Accept the new pixel if its value is less than the value of the current pixel.
D3DCMP_EQUAL
Accept the new pixel if its value equals the value of the current pixel.
D3DCMP_LESSEQUAL
Accept the new pixel if its value is less than or equal to the value of the current pixel.
D3DCMP_GREATER
Accept the new pixel if its value is greater than the value of the current pixel.
D3DCMP_NOTEQUAL
Accept the new pixel if its value does not equal the value of the current pixel.
D3DCMP_GREATEREQUAL
Accept the new pixel if its value is greater than or equal to the value of the current pixel.
D3DCMP_ALWAYS
Always pass the test.
D3DCMP_FORCE_DWORD
Forces this enumerated type to be 32 bits in size.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.


D3DCULL

The D3DCULL enumerated type defines the supported cull modes. These define how back faces are culled when rendering a geometry.

typedef enum _D3DCULL {
    D3DCULL_NONE = 1,
    D3DCULL_CW   = 2,
    D3DCULL_CCW  = 3,
    D3DCULL_FORCE_DWORD   = 0x7fffffff,
} D3DCULL;

Members

D3DCULL_NONE
Do not cull back faces.
D3DCULL_CW
Cull back faces with clockwise vertices.
D3DCULL_CCW
Cull back faces with counterclockwise vertices.
D3DCULL_FORCE_DWORD
Forces this enumerated type to be 32 bits in size.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.

See Also

D3DPRIMCAPS, D3DRENDERSTATETYPE


D3DFILLMODE

The D3DFILLMODE enumerated type contains constants describing the fill mode. These values are used by the D3DRENDERSTATE_FILLMODE render state in the D3DRENDERSTATETYPE enumerated type.

typedef enum _D3DFILLMODE {
    D3DFILL_POINT     = 1,
    D3DFILL_WIREFRAME = 2,
    D3DFILL_SOLID     = 3
    D3DFILL_FORCE_DWORD   = 0x7fffffff,
} D3DFILLMODE;

Members

D3DFILL_POINT
Fill points.
D3DFILL_WIREFRAME
Fill wireframes. This fill mode currently does not work for clipped primitives when you are using the DrawPrimitive methods.
D3DFILL_SOLID
Fill solids.
D3DFILL_FORCE_DWORD
Forces this enumerated type to be 32 bits in size.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.


D3DFOGMODE

The D3DFOGMODE enumerated type contains constants describing the fog mode. These values are used by the D3DRENDERSTATE_FOGTABLEMODE render state in the D3DRENDERSTATETYPE enumerated type.

typedef enum _D3DFOGMODE {
    D3DFOG_NONE   = 0,
    D3DFOG_EXP    = 1,
    D3DFOG_EXP2   = 2,
    D3DFOG_LINEAR = 3
    D3DFOG_FORCE_DWORD   = 0x7fffffff,
} D3DFOGMODE;

Members

D3DFOG_NONE
No fog effect.
D3DFOG_EXP
The fog effect intensifies exponentially, according to the following formula:

D3DFOG_EXP2
The fog effect intensifies exponentially with the square of the distance, according to the following formula:

D3DFOG_LINEAR
The fog effect intensifies linearly between the start and end points, according to the following formula:

This is the only fog mode currently supported.

D3DFOG_FORCE_DWORD
Forces this enumerated type to be 32 bits in size.

Remarks

In monochromatic (ramp) lighting mode, fog works properly only when the fog color is black. (If there is no lighting, any fog color will work, since in this case any fog color is effectively black.)

For more information about fog, see Fog.

Note Fog can be considered a measure of visibility—the lower the fog value produced by one of the fog equations, the less visible an object is.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.


D3DLIGHTSTATETYPE

The D3DLIGHTSTATETYPE enumerated type defines the light state for the IDirect3DDevice3::SetLightState method. This enumerated type is part of the D3DSTATE structure.

typedef enum _D3DLIGHTSTATETYPE {
    D3DLIGHTSTATE_MATERIAL   = 1,
    D3DLIGHTSTATE_AMBIENT    = 2,
    D3DLIGHTSTATE_COLORMODEL = 3,
    D3DLIGHTSTATE_FOGMODE    = 4,
    D3DLIGHTSTATE_FOGSTART   = 5,
    D3DLIGHTSTATE_FOGEND     = 6,
    D3DLIGHTSTATE_FOGDENSITY = 7,
    D3DLIGHTSTATE_COLORVERTEX       = 8,
    D3DLIGHTSTATE_FORCE_DWORD     = 0x7fffffff,
} D3DLIGHTSTATETYPE;

Members

D3DLIGHTSTATE_MATERIAL
Defines the material that is lit and used to compute the final color and intensity values during rasterization. The default value is NULL. This value must be set when you use textures in ramp mode. When no material is selected (NULL), the Direct3D lighting engine is disabled.
D3DLIGHTSTATE_AMBIENT
Sets the color and intensity of the current ambient light. If an application specifies this value, it should not specify a light as a parameter. The default value is 0.
D3DLIGHTSTATE_COLORMODEL
One of the values for the D3DCOLORMODEL data type. The default value is D3DCOLOR_RGB.
D3DLIGHTSTATE_FOGMODE
One of the members of the D3DFOGMODE enumerated type. The default value is D3DFOG_NONE.
D3DLIGHTSTATE_FOGSTART
Defines the starting value for fog. The default value is 1.0.
D3DLIGHTSTATE_FOGEND
Defines the ending value for fog. The default value is 100.0.
D3DLIGHTSTATE_FOGDENSITY
Defines the density setting for fog. The default value is 1.0.
D3DLIGHTSTATE_COLORVERTEX
Enables or disables the use of the vertex color in lighting calculations for vertices whose vertex format (specified as a flexible vertex format) includes color information. The default value, TRUE, enables the use of the vertex color in lighting. Set this to FALSE to cause the system to ignore the vertex color. Per-vertex color is supported only by lights for which properties are defined by a D3DLIGHT2 structure.
D3DLIGHTSTATE_FORCE_DWORD
Forces this enumerated type to be 32 bits in size.

Remarks

When programming for execute buffers, this enumerated type is used with the D3DOP_STATELIGHT opcode.

Setting D3DLIGHTSTATE_COLORVERTEX to FALSE instructs the geometry pipeline to ignore part of each vertex (the vertex color). The only reason to use this light state is to change the appearance of the geometry without respecifying it in a different vertex format.

If D3DLIGHTSTATE_COLORVERTEX is set to TRUE and a diffuse vertex color is present, the output alpha is equal to the diffuse alpha for the vertex. Otherwise, output alpha is equal to the alpha component of diffuse material, clamped to the range [0, 255].

You can disable or enable lighting by including or omitting the D3DDP_DONOTLIGHT flag when calling a standard IDirect3DDevice3 rendering method, such as IDirect3DDevice3::DrawPrimitive. If you are using vertex buffers, disable or enable lighting by ommiting or including the D3DVOP_LIGHT flag when you call the IDirect3DVertexBuffer::ProcessVertices method.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.

See Also

D3DOPCODE and D3DSTATE, Light Properties


D3DLIGHTTYPE

The D3DLIGHTTYPE enumerated type defines the light type. This enumerated type is part of the D3DLIGHT2 structure.

typedef enum _D3DLIGHTTYPE {
    D3DLIGHT_POINT         = 1,
    D3DLIGHT_SPOT          = 2,
    D3DLIGHT_DIRECTIONAL   = 3,
    D3DLIGHT_PARALLELPOINT = 4,
    D3DLIGHT_FORCE_DWORD   = 0x7fffffff,
} D3DLIGHTTYPE;

Members

D3DLIGHT_POINT
Light is a point source. The light has a position in space and radiates light in all directions.
D3DLIGHT_SPOT
Light is a spotlight source. This light is something like a point light except that the illumination is limited to a cone. This light type has a direction and several other parameters which determine the shape of the cone it produces. For information about these parameters, see the D3DLIGHT2 structure.
D3DLIGHT_DIRECTIONAL
Light is a directional source. This is equivalent to using a point light source at an infinite distance.
D3DLIGHT_PARALLELPOINT
Light is a parallel point source. This light type acts like a directional light except its direction is the vector going from the light position to the origin of the geometry it is illuminating.
D3DLIGHT_FORCE_DWORD
Forces this enumerated type to be 32 bits in size.

Remarks

Directional and parallel-point lights are slightly faster than point light sources, but point lights look a little better. Spotlights offer interesting visual effects but are computationally expensive.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.


D3DOPCODE

The D3DOPCODE enumerated type contains the opcodes for execute buffer.

typedef enum _D3DOPCODE {
    D3DOP_POINT           = 1,
    D3DOP_LINE            = 2,
    D3DOP_TRIANGLE        = 3,
    D3DOP_MATRIXLOAD      = 4,
    D3DOP_MATRIXMULTIPLY  = 5,
    D3DOP_STATETRANSFORM  = 6,
    D3DOP_STATELIGHT      = 7,
    D3DOP_STATERENDER     = 8,
    D3DOP_PROCESSVERTICES = 9,
    D3DOP_TEXTURELOAD     = 10,
    D3DOP_EXIT            = 11,
    D3DOP_BRANCHFORWARD   = 12,
    D3DOP_SPAN            = 13,
    D3DOP_SETSTATUS       = 14,
    D3DOP_FORCE_DWORD     = 0x7fffffff,
} D3DOPCODE;

Members

D3DOP_POINT
Sends a point to the renderer. Operand data is described by the D3DPOINT structure.
D3DOP_LINE
Sends a line to the renderer. Operand data is described by the D3DLINE structure.
D3DOP_TRIANGLE
Sends a triangle to the renderer. Operand data is described by the D3DTRIANGLE structure.
D3DOP_MATRIXLOAD
Triggers a data transfer in the rendering engine. Operand data is described by the D3DMATRIXLOAD structure.
D3DOP_MATRIXMULTIPLY
Triggers a data transfer in the rendering engine. Operand data is described by the D3DMATRIXMULTIPLY structure.
D3DOP_STATETRANSFORM
Sets the value of internal state variables in the rendering engine for the transformation module. Operand data is a variable token and the new value. The token identifies the internal state variable, and the new value is the value to which that variable should be set. For more information about these variables, see the D3DSTATE structure and the D3DTRANSFORMSTATETYPE enumerated type.
D3DOP_STATELIGHT
Sets the value of internal state variables in the rendering engine for the lighting module. Operand data is a variable token and the new value. The token identifies the internal state variable, and the new value is the value to which that variable should be set. For more information about these variables, see the D3DSTATE structure and the D3DLIGHTSTATETYPE enumerated type.
D3DOP_STATERENDER
Sets the value of internal state variables in the rendering engine for the rendering module. Operand data is a variable token and the new value. The token identifies the internal state variable, and the new value is the value to which that variable should be set. For more information about these variables, see the D3DSTATE structure and the D3DRENDERSTATETYPE enumerated type.
D3DOP_PROCESSVERTICES
Sets both lighting and transformations for vertices. Operand data is described by the D3DPROCESSVERTICES structure.
D3DOP_TEXTURELOAD
Triggers a data transfer in the rendering engine. Operand data is described by the D3DTEXTURELOAD structure.
D3DOP_EXIT
Signals that the end of the list has been reached.
D3DOP_BRANCHFORWARD
Enables a branching mechanism within the execute buffer. For more information, see the D3DBRANCH structure.
D3DOP_SPAN
This opcode is obsolete and is silently ignored. Spans a list of points with the same y value. For more information, see the D3DSPAN structure.
D3DOP_SETSTATUS
Resets the status of the execute buffer. For more information, see the D3DSTATUS structure.
D3DOP_FORCE_DWORD
Forces this enumerated type to be 32 bits in size.

Remarks

An execute buffer has two parts: an array of vertices (each typically with position, normal vector, and texture coordinates) and an array of opcode/operand groups. One opcode can have several operands following it; the system simply performs the relevant operation on each operand.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.

See Also

D3DINSTRUCTION


D3DPRIMITIVETYPE

The D3DPRIMITIVETYPE enumerated type lists the primitives supported by DrawPrimitive methods. This type was introduced in DirectX 5.0.

typedef enum _D3DPRIMITIVETYPE {
    D3DPT_POINTLIST     = 1,
    D3DPT_LINELIST      = 2,
    D3DPT_LINESTRIP     = 3,
    D3DPT_TRIANGLELIST  = 4,
    D3DPT_TRIANGLESTRIP = 5,
    D3DPT_TRIANGLEFAN   = 6
    D3DPT_FORCE_DWORD   = 0x7fffffff,
} D3DPRIMITIVETYPE;

Members

D3DPT_POINTLIST
Renders the vertices as a collection of isolated points.
D3DPT_LINELIST
Renders the vertices as a list of isolated straight line segments. Calls using this primitive type will fail if the count is less than 2, or is odd.
D3DPT_LINESTRIP
Renders the vertices as a single polyline. Calls using this primitive type will fail if the count is less than 2.
D3DPT_TRIANGLELIST
Renders the specified vertices as a sequence of isolated triangles. Each group of 3 vertices defines a separate triangle. Calls using this primitive type will fail if the count is less than 3, or if not evenly divisible by 3.

Backface culling is affected by the current winding order render state.

D3DPT_TRIANGLESTRIP
Renders the vertices as a triangle strip. Calls using this primitive type will fail if the count is less than 3. The backface removal flag is automatically flipped on even numbered triangles.
D3DPT_TRIANGLEFAN
Renders the vertices as a triangle fan. Calls using this primitive type will fail if the count is less than 3.
D3DPT_FORCE_DWORD
Forces this enumerated type to be 32 bits in size.

Remarks

Using triangle strips or fans is often more effecient than using triangle lists, as fewer vertices are duplicated. For a conceptual overview and information about defining triangle strips and fans, see Triangle Strips and Triangle Fans.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.

See Also

IDirect3DDevice3::Begin, IDirect3DDevice3::BeginIndexed, IDirect3DDevice3::DrawIndexedPrimitive, IDirect3DDevice3::DrawPrimitive, Primitive Types


D3DRENDERSTATETYPE

The D3DRENDERSTATETYPE enumerated type describes the render state for the D3DOP_STATERENDER opcode. This enumerated type is part of the D3DSTATE structure. The values mentioned in the following descriptions are set in the second member of this structure.

Values 40 through 49 were introduced with DirectX 5.0.

typedef enum _D3DRENDERSTATETYPE {
    D3DRENDERSTATE_TEXTUREHANDLE      = 1,    // texture handle
    D3DRENDERSTATE_ANTIALIAS          = 2,    // antialiasing mode
    D3DRENDERSTATE_TEXTUREADDRESS     = 3,    // texture address
    D3DRENDERSTATE_TEXTUREPERSPECTIVE = 4,    // perspective correction
    D3DRENDERSTATE_WRAPU              = 5,    // wrap in u direction
    D3DRENDERSTATE_WRAPV              = 6,    // wrap in v direction
    D3DRENDERSTATE_ZENABLE            = 7,    // enable z test
    D3DRENDERSTATE_FILLMODE           = 8,    // fill mode
    D3DRENDERSTATE_SHADEMODE          = 9,    // shade mode
    D3DRENDERSTATE_LINEPATTERN        = 10,   // line pattern
    D3DRENDERSTATE_MONOENABLE         = 11,   // enable mono rendering
    D3DRENDERSTATE_ROP2               = 12,   // raster operation
    D3DRENDERSTATE_PLANEMASK          = 13,   // physical plane mask
    D3DRENDERSTATE_ZWRITEENABLE       = 14,   // enable z writes
    D3DRENDERSTATE_ALPHATESTENABLE    = 15,   // enable alpha tests
    D3DRENDERSTATE_LASTPIXEL          = 16,   // draw last pixel in a line
    D3DRENDERSTATE_TEXTUREMAG         = 17,   // how textures are magnified
    D3DRENDERSTATE_TEXTUREMIN         = 18,   // how textures are reduced
    D3DRENDERSTATE_SRCBLEND           = 19,   // blend factor for source
    D3DRENDERSTATE_DESTBLEND          = 20,   // blend factor for destination
    D3DRENDERSTATE_TEXTUREMAPBLEND    = 21,   // blend mode for map
    D3DRENDERSTATE_CULLMODE           = 22,   // back-face culling mode
    D3DRENDERSTATE_ZFUNC              = 23,   // z-comparison function
    D3DRENDERSTATE_ALPHAREF           = 24,   // reference alpha value
    D3DRENDERSTATE_ALPHAFUNC          = 25,   // alpha-comparison function
    D3DRENDERSTATE_DITHERENABLE       = 26,   // enable dithering
    D3DRENDERSTATE_ALPHABLENDENABLE   = 27,   // enable alpha blending
    D3DRENDERSTATE_FOGENABLE          = 28,   // enable fog
    D3DRENDERSTATE_SPECULARENABLE     = 29,   // enable specular highlights
    D3DRENDERSTATE_ZVISIBLE           = 30,   // enable z-checking
    D3DRENDERSTATE_SUBPIXEL           = 31,   // enable subpixel correction
    D3DRENDERSTATE_SUBPIXELX          = 32,   // enable x subpixel correction
    D3DRENDERSTATE_STIPPLEDALPHA      = 33,   // enable stippled alpha
    D3DRENDERSTATE_FOGCOLOR           = 34,   // fog color
    D3DRENDERSTATE_FOGTABLEMODE       = 35,   // fog mode
    D3DRENDERSTATE_FOGTABLESTART      = 36,   // fog table start
    D3DRENDERSTATE_FOGTABLEEND        = 37,   // fog table end
    D3DRENDERSTATE_FOGTABLEDENSITY    = 38,   // fog density
    D3DRENDERSTATE_STIPPLEENABLE      = 39,   // enables stippling
    D3DRENDERSTATE_EDGEANTIALIAS      = 40,   // antialias edges
    D3DRENDERSTATE_COLORKEYENABLE     = 41,   // enable color-key transparency
    D3DRENDERSTATE_BORDERCOLOR        = 43,   // border color
    D3DRENDERSTATE_TEXTUREADDRESSU    = 44,   // u texture address mode
    D3DRENDERSTATE_TEXTUREADDRESSV    = 45,   // v texture address mode
    D3DRENDERSTATE_MIPMAPLODBIAS      = 46,   // mipmap LOD bias
    D3DRENDERSTATE_ZBIAS              = 47,   // z-bias
    D3DRENDERSTATE_RANGEFOGENABLE     = 48,   // enables range-based fog
    D3DRENDERSTATE_ANISOTROPY         = 49,   // max. anisotropy
    D3DRENDERSTATE_FLUSHBATCH         = 50,   // explicit flush for DP batching (DX5 Only)
    D3DRENDERSTATE_TRANSLUCENTSORTINDEPENDENT=51, // enable sort-independent transparency
    D3DRENDERSTATE_STENCILENABLE      = 52,   // enable or disable stenciling
    D3DRENDERSTATE_STENCILFAIL        = 53,   // stencil operation
    D3DRENDERSTATE_STENCILZFAIL       = 54,   // stencil operation
    D3DRENDERSTATE_STENCILPASS        = 55,   // stencil operation
    D3DRENDERSTATE_STENCILFUNC        = 56,   // stencil comparison function
    D3DRENDERSTATE_STENCILREF         = 57,   // reference value for stencil test
    D3DRENDERSTATE_STENCILMASK        = 58,   // mask value used in stencil test
    D3DRENDERSTATE_STENCILWRITEMASK   = 59,   // stencil buffer write mask
    D3DRENDERSTATE_TEXTUREFACTOR      = 60,   // texture factor
    D3DRENDERSTATE_STIPPLEPATTERN00   = 64,   // first line of stipple pattern
       // Stipple patterns 01 through 30 omitted here.
    D3DRENDERSTATE_STIPPLEPATTERN31   = 95,   // last line of stipple pattern
    D3DRENDERSTATE_WRAP0              = 128,  // wrapping flags for first texture
       // Wrap renderstates 1 through 6 omitted here.
    D3DRENDERSTATE_WRAP7              = 135,  // wrapping flags for last texture
    D3DRENDERSTATE_FORCE_DWORD        = 0x7fffffff,
} D3DRENDERSTATETYPE;

Members

D3DRENDERSTATE_TEXTUREHANDLE
Texture handle for use when rendering with the IDirect3DDevice2 or earlier interfaces. The default value is NULL, which disables texture mapping and reverts to flat or Gouraud shading.

If the specified texture is in a system memory surface and the driver can only support texturing from display memory surfaces, the call will fail.

In retail builds the texture handle is not validated.

D3DRENDERSTATE_ANTIALIAS
One of the members of the D3DANTIALIASMODE enumerated type specifying the desired type of full-scene antialiasing. The default value is D3DANTIALIAS_NONE. For more information, see Full-scene Antialiasing and Antialiasing States.

You can only enable full-scene antialiasing on devices that expose the D3DPRASTERCAPS_ANTIALIASSORTINDEPENDENT or D3DPRASTERCAPS_ANTIALIASSORTDEPENDENT capabilities.

D3DRENDERSTATE_TEXTUREADDRESS
This render state is superseded by the D3DTSS_ADDRESS texture stage state value set through the IDirect3DDevice3::SetTextureStageState method, but can still be used to set the addressing mode of the first texture stage. Valid values are members of the D3DTEXTUREADDRESS enumerated type. The default value is D3DTADDRESS_WRAP. For more information, see Texture Addressing Modes.

Applications that need to specify separate texture-addressing modes for the u and v coordinates of a texture can use the D3DRENDERSTATE_TEXTUREADDRESSU and D3DRENDERSTATE_TEXTUREADDRESSV render states.

D3DRENDERSTATE_TEXTUREPERSPECTIVE
TRUE to enable for perspective correct texture mapping. (See perspective correction.) For the IDirect3DDevice3 interface, the default value is TRUE. For earlier interfaces, the default is FALSE. For more information, see Texture Perspective State.
D3DRENDERSTATE_WRAPU and
D3DRENDERSTATE_WRAPV
These render states are superseded by the D3DRENDERSTATE_WRAP0 through D3DRENDERSTATE_WRAP7 render states, but can be used to set wrapping for the first texture stage. Set to TRUE for wrapping in u direction. The default value is FALSE. For more information, see Texture Wrapping.
D3DRENDERSTATE_ZENABLE
The depth buffering state, as one of the members of the D3DZBUFFERTYPE enumerated type. Set this state to D3DZB_TRUE to enable z-buffering, D3DZB_USEW to enable w-buffering, or D3DZB_FALSE to disable depth buffering.

The default value for this render state is D3DZB_TRUE if a depth buffer is attached to the render-target surface, and D3DZB_FALSE otherwise.

D3DRENDERSTATE_FILLMODE
One or more members of the D3DFILLMODE enumerated type. The default value is D3DFILL_SOLID.
D3DRENDERSTATE_SHADEMODE
One or more members of the D3DSHADEMODE enumerated type. The default value is D3DSHADE_GOURAUD.
D3DRENDERSTATE_LINEPATTERN
The D3DLINEPATTERN structure. The default values are 0 for wRepeatPattern and 0 for wLinePattern.
D3DRENDERSTATE_MONOENABLE
TRUE to enable monochromatic rendering, using a gray scale based on the blue channel of the color rather than full RGB. The default value is FALSE. If the device does not support RGB rendering, the value will be TRUE. Applications can check whether the device supports RGB rendering by using the dcmColorModel member of the D3DDEVICEDESC structure.

In monochromatic rendering, only the intensity (gray scale) component of the color and specular components are interpolated across the triangle. This means that only one channel (gray) is interpolated across the triangle instead of 3 channels (R,G,B), which is a performance gain for some hardware. This gray-scale component is derived from the blue channel of the color and specular components of the triangle.

D3DRENDERSTATE_ROP2
One of the 16 standard Windows ROP2 binary raster operations specifying how the supplied pixels are combined with the pixels of the display surface. The default value is R2_COPYPEN. Applications can use the D3DPRASTERCAPS_ROP2 flag in the dwRasterCaps member of the D3DPRIMCAPS structure to determine whether additional raster operations are supported.
D3DRENDERSTATE_PLANEMASK
Physical plane mask whose type is ULONG. The default value is the bitwise negation of zero (~0). This physical plane mask can be used to turn off the red bit, the blue bit, and so on. This render state is not supported by the software rasterizers, and is often ignored by hardware drivers. To disable writes to the color buffer by using alpha blending, you can set D3DRENDERSTATE_SRCBLEND to D3DBLEND_ZERO and D3DRENDERSTATE_DESTBLEND to D3DBLEND_ONE.
D3DRENDERSTATE_ZWRITEENABLE
TRUE to enable writes to the depth buffer. The default value is TRUE. This member enables an application to prevent the system from updating the depth buffer with new depth values. If this state is FALSE, depth comparisons are still made according to the render state D3DRENDERSTATE_ZFUNC (assuming depth buffering is taking place), but depth values are not written to the buffer.
D3DRENDERSTATE_ALPHATESTENABLE
TRUE to enable alpha tests. The default value is FALSE. This member enables applications to turn off the tests that otherwise would accept or reject a pixel based on its alpha value.

The incoming alpha value is compared with the reference alpha value using the comparison function provided by the D3DRENDERSTATE_ALPHAFUNC render state. When this mode is enabled, alpha blending occurs only if the test succeeds.

D3DRENDERSTATE_LASTPIXEL
FALSE to enable drawing the last pixel in a line or triangle. The default value is TRUE.
D3DRENDERSTATE_TEXTUREMAG
This render state is superseded by the D3DTSS_MAGFILTER texture stage stage, set through the IDirect3DDevice3::SetTextureStageState method, but can still be used to set the magnification filter for the first texture stage. This render state can be one of the members of the D3DTEXTUREFILTER enumerated type, which describes how a texture should be filtered when it is being magnified (that is, when a texel must cover more than one pixel). The valid values are D3DFILTER_NEAREST (the default) and D3DFILTER_LINEAR.
D3DRENDERSTATE_TEXTUREMIN
This render state is superseded by the D3DTSS_MINFILTER texture stage stage, set through the IDirect3DDevice3::SetTextureStageState method, but can still be used to set the minification filter for the first texture stage. This render state can be one of the members of the D3DTEXTUREFILTER enumerated type, which describes how a texture should be filtered when it is being made smaller (that is, when a pixel contains more than one texel). Any of the members of the D3DTEXTUREFILTER enumerated type can be specified for this render state. The default value is D3DFILTER_NEAREST.
D3DRENDERSTATE_SRCBLEND
One of the members of the D3DBLEND enumerated type. The default value is D3DBLEND_ONE.
D3DRENDERSTATE_DESTBLEND
One of the members of the D3DBLEND enumerated type. The default value is D3DBLEND_ZERO.
D3DRENDERSTATE_TEXTUREMAPBLEND
This render state is used when rendering with the IDirect3DDevice2 interface. When rendering multiple textures with the IDirect3DDevice3 interface, you can set blending operations and arguments through the IDirect3DDevice3::SetTextureStageState method. For more information, see Multiple Texture Blending.

One of the members of the D3DTEXTUREBLEND enumerated type. The default value is D3DTBLEND_MODULATE.

D3DRENDERSTATE_CULLMODE
Specifies how back-facing triangles are to be culled, if at all. This can be set to one of the members of the D3DCULL enumerated type. The default value is D3DCULL_CCW.
D3DRENDERSTATE_ZFUNC
One of the members of the D3DCMPFUNC enumerated type. The default value is D3DCMP_LESSEQUAL. This member enables an application to accept or reject a pixel based on its distance from the camera.

The depth value of the pixel is compared with the depth buffer value. If the depth value of the pixel passes the comparison function, the pixel is written.

The depth value is written to the depth buffer only if the render state is TRUE.

Software rasterizers and many hardware accelerators work faster if the depth test fails, since there is no need to filter and modulate the texture if the pixel is not going to be rendered.

D3DRENDERSTATE_ALPHAREF
Value specifying a reference alpha value against which pixels are tested when alpha-testing is enabled. This is an 8 bit value placed in the low 8 bits of the DWORD render state value. Values can range from 0x00000000 to 0x000000FF.
D3DRENDERSTATE_ALPHAFUNC
One of the members of the D3DCMPFUNC enumerated type. The default value is D3DCMP_ALWAYS. This member enables an application to accept or reject a pixel based on its alpha value.
D3DRENDERSTATE_DITHERENABLE
TRUE to enable dithering. The default value is FALSE.
D3DRENDERSTATE_ALPHABLENDENABLE
TRUE to enable alpha-blended transparency. The default value is FALSE. This member supersedes the legacy D3DRENDERSTATE_BLENDENABLE render state; see remarks for more information.

Prior to DirectX 5.0, the software rasterizers used this render state to toggle both color keying and alpha blending. Currently, you can use the D3DRENDERSTATE_COLORKEYENABLE render state to toggle color keying. (Hardware rasterizers have always used the D3DRENDERSTATE_BLENDENABLE render state only for toggling alpha blending.)

The type of alpha blending is determined by the D3DRENDERSTATE_SRCBLEND and D3DRENDERSTATE_DESTBLEND render states. D3DRENDERSTATE_ALPHABLENDENABLE, with D3DRENDERSTATE_COLORKEYENABLE, allows fine blending control.

D3DRENDERSTATE_ALPHABLENDENABLE does not affect the texture-blending modes specified by the D3DTEXTUREBLEND enumerated type. Texture blending is logically well before the D3DRENDERSTATE_ALPHABLENDENABLE part of the pixel pipeline. The only interaction between the two is that the alpha portions remaining in the polygon after the D3DTEXTUREBLEND phase may be used in the D3DRENDERSTATE_ALPHABLENDENABLE phase to govern interaction with the content in the frame buffer.

Applications should check the D3DDEVCAPS_DRAWPRIMTLVERTEX flag in the D3DDEVICEDESC structure to find out whether this render state is supported.

D3DRENDERSTATE_FOGENABLE
TRUE to enable fog blending. The default value is FALSE. For more information, see Fog Blending and Fog.
D3DRENDERSTATE_SPECULARENABLE
TRUE to enable specular highlights. For the IDirect3DDevice3 interface, the default value is FALSE. For earlier interfaces, the default is TRUE.

Specular highlights are calculated as though every vertex in the object being lit were at the object's origin. This gives the expected results as long as the object is modeled around the origin and the distance from the light to the object is relatively large.

D3DRENDERSTATE_ZVISIBLE
This render state is not supported.
D3DRENDERSTATE_SUBPIXEL
TRUE to enable subpixel correction. The default value is FALSE.

Subpixel correction is the ability to draw pixels in precisely their correct locations. In a system that implemented subpixel correction, if a pixel were at position 0.1356, its position would be interpolated from the actual coordinate rather than simply drawn at 0 (using the integer values). Hardware can be non-subpixel correct or subpixel correct in x or in both x and y. When interpolating across the x-direction the actual coordinate is used. All hardware should be subpixel correct. Some software rasterizers are not subpixel correct because of the performance loss.

Subpixel correction means that the hardware always pre-steps the interpolant values in the x-direction to the nearest pixel centers and then steps one pixel at a time in the y-direction. For each x span it also pre-steps in the x-direction to the nearest pixel center and then steps in the x-direction one pixel each time. This results in very accurate rendering and eliminates almost all jittering of pixels on triangle edges. Most hardware either doesn't support it (always off) or always supports it (always on).

D3DRENDERSTATE_SUBPIXELX
TRUE to enable subpixel correction in the x-direction only. The default value is FALSE.
D3DRENDERSTATE_STIPPLEDALPHA
TRUE to enable stippled alpha. The default value is FALSE.

Current software rasterizers ignore this render state. You can use the D3DPSHADECAPS_ALPHAFLATSTIPPLED flag in the D3DPRIMCAPS structure to discover whether the current hardware supports this render state.

D3DRENDERSTATE_FOGCOLOR
Value whose type is D3DCOLOR. The default value is 0. For more information, see Fog Color.
D3DRENDERSTATE_FOGTABLEMODE
The fog formula to be used for pixel fog. Set to one of the members of the D3DFOGMODE enumerated type. The default value is D3DFOG_NONE. For more information, see Pixel Fog.
D3DRENDERSTATE_FOGTABLESTART
D3DRENDERSTATE_FOGTABLEEND
Depth at which pixel fog effects begin and end for linear fog mode. Depth is specified in world-space for hardware devices (which use eye-relative fog) or in device-space for software devices. For more information, see Pixel Fog Parameters and Eye-Relative vs. Z-Based Depth.

These render states enable you to exclude fog effects for positions close to the camera. For example, you could set the starting depth to 0.3 to prevent fog effects for depths between 0.0 and 0.299, and the ending depth to 0.7 to prevent additional fog effects for depths between 0.701 and 1.0.

D3DRENDERSTATE_FOGTABLEDENSITY
Fog density for pixel fog to be used in the exponential fog modes (D3DFOG_EXP and D3DFOG_EXP2). Valid density values range from 0.0 to 1.0, inclusive. The default value is 1.0. For more information, see Pixel Fog Parameters.
D3DRENDERSTATE_STIPPLEENABLE
Enables stippling in the device driver. When stippled alpha is enabled, it overrides the current stipple pattern, as specified by the D3DRENDERSTATE_STIPPLEPATTERN00 through D3DRENDERSTATE_STIPPLEPATTERN31 render states. When stippled alpha is disabled, the stipple pattern must be returned.
D3DRENDERSTATE_EDGEANTIALIAS
TRUE to antialias lines forming the convex outline of objects. The default value is FALSE. For more information, see Edge Antialiasing and Antialiasing States. When set to TRUE, applications should only render lines, and only to the exterior edges of polygons in a scene. The behavior is undefined if triangles or points are drawn when this render state is set. Antialiasing is performed simply by averaging the values of neighboring pixels. Although this is not the best way to perform antialiasing, it can be very efficient; hardware that supports this kind of operation is becoming more common.

You can only enable edge antialiasing on devices that expose the D3DPRASTERCAPS_ANTIALIASEDGES capability.

D3DRENDERSTATE_COLORKEYENABLE
TRUE to enable color-keyed transparency. The default value is FALSE. You can use this render state with D3DRENDERSTATE_ALPHABLENDENABLE to implement fine blending control.

Applications should check the D3DDEVCAPS_DRAWPRIMTLVERTEX flag in the D3DDEVICEDESC structure to find out whether this render state is supported.

When color-keyed transparency is enabled, only texture surfaces that were created with the DDSD_CKSRCBLT flag will be affected. Surfaces that were created without the DDSD_CKSRCBLT flag will exhibit color-keyed transparency effects.

D3DRENDERSTATE_BORDERCOLOR
A DWORD value specifying a border color. If the texture addressing mode is specified as D3DTADDRESS_BORDER (as set in the D3DTEXTUREADDRESS enumerated type), this render state specifies the border color the system uses when it encounters texture coordinates outside the range [0.0, 1.0].

The format of the physical-color information specified by the DWORD value depends on the format of the DirectDraw surface.

D3DRENDERSTATE_TEXTUREADDRESSU
This render state is superseded by the D3DTSS_ADDRESSU texture stage state value set through the IDirect3DDevice3::SetTextureStageState method, but can still be used to set the addressing mode of the first texture stage. Valid values are members of the D3DTEXTUREADDRESS enumerated type. The default value is D3DTADDRESS_WRAP. For more information, see Texture Addressing Modes.

This render state applies only to the u texture coordinate. This render state, along with D3DRENDERSTATE_TEXTUREADDRESSV, allows you to specify separate texture-addressing modes for the u and v coordinates of a texture. Because the D3DRENDERSTATE_TEXTUREADDRESS render state applies to both the u and v texture coordinates, it overrides any values set for the D3DRENDERSTATE_TEXTUREADDRESSU render state.

D3DRENDERSTATE_TEXTUREADDRESSV
This render state is superseded by the D3DTSS_ADDRESSV texture stage state value set through the IDirect3DDevice3::SetTextureStageState method, but can still be used to set the addressing mode of the first texture stage. Valid values are members of the D3DTEXTUREADDRESS enumerated type. The default value is D3DTADDRESS_WRAP. For more information, see Texture Addressing Modes.

This render state applies only to the v texture coordinate. This render state, along with D3DRENDERSTATE_TEXTUREADDRESSU, allows you to specify separate texture-addressing modes for the u and v coordinates of a texture. Because the D3DRENDERSTATE_TEXTUREADDRESS render state applies to both the u and v texture coordinates, it overrides any values set for the D3DRENDERSTATE_TEXTUREADDRESSV render state.

D3DRENDERSTATE_MIPMAPLODBIAS
Floating-point D3DVALUE value used to change the level of detail (LOD) bias. This value offsets the value of the mipmap level that is computed by trilinear texturing. It is usually in the range –1.0 to 1.0; the default value is 0.0.

Each unit bias (+/-1.0) biases the selection by exactly one mipmap level. A positive bias will cause the use of larger mipmap levels, resulting in a sharper but more aliased image. A negative bias will cause the use of smaller mipmap levels, resulting in a blurrier image. Applying a negative bias also results in the referencing of a smaller amount of texture data, which can boost performance on some systems.

D3DRENDERSTATE_ZBIAS
An integer value in the range 0 to 16 that causes polygons that are physically coplanar to appear separate. Polygons with a high z-bias value will appear in front of polygons with a low value, without requiring sorting for drawing order. Polygons with a value of 1 appear in front of polygons with a value of 0, and so on. The default value is zero. For more information, see Using Depth Buffers.
D3DRENDERSTATE_RANGEFOGENABLE
TRUE to enable range-based vertex fog. (The default value is FALSE, in which case the system uses depth-based fog.) In range-based fog, the distance of an object from the viewer is used to compute fog effects, not the depth of the object (that is, the z-coordinate) in the scene. In range-based fog, all fog methods work as usual, except that they use range instead of depth in the computations.

Range is the correct factor to use for fog computations, but depth is commonly used instead because range is expensive to compute and depth is generally already available. Using depth to calculate fog has the undesirable effect of having the 'fogginess' of peripheral objects change as the eye is rotated — in this case, the depth changes while the range remains constant.

This render state works only with D3DVERTEX vertices. When you specify D3DLVERTEX or D3DTLVERTEX vertices, the F (fog) component of the RGBF fog value should already be corrected for range.

Since no hardware currently supports per-pixel range-based fog, range correction offered only for vertex fog. For more information, see Range-based Fog and Vertex Fog.

D3DRENDERSTATE_ANISOTROPY
This render state is superseded by the D3DTSS_MAXANISOTROPY texture stage state, set through the IDirect3DDevice3::SetTextureStageState method, but can still be used to set the degree of anisotropic filtering for the first texture stage.

This render state can be an integer value that enables a degree of anisotropic filtering, used for bilinear or trilinear filtering. The value determines the maximum aspect ratio of the sampling filter kernel. To determine the range of appropriate values, use the D3DPRASTERCAPS_ANISOTROPY flag in the D3DPRIMCAPS structure.

Anisotropy is the distortion visible in the texels of a 3-D object whose surface is oriented at an angle with respect to the plane of the screen. The anisotropy is measured as the elongation (length divided by width) of a screen pixel that is inverse-mapped into texture space.

D3DRENDERSTATE_FLUSHBATCH
Flush any pending DrawPrimitive batches. When rendering with texture handles (using the IDirect3DDevice2 interface) you must flush batched primitives after modifying the current texture surface. Batched primitives are implicitly flushed when rendering with the IDirect3DDevice3 interface, as well as when rendering with execute buffers.
D3DRENDERSTATE_TRANSLUCENTSORTINDEPENDENT
TRUE to enable sort-independent transparency, or FALSE to disable.
D3DRENDERSTATE_STENCILENABLE
TRUE to enable stenciling, or FALSE to disable stenciling. The default value is FALSE. For more information, see Stencil Buffers.
D3DRENDERSTATE_STENCILFAIL
Stencil operation to perform if the stencil test fails. This can be one of the members of the D3DSTENCILOP enumerated type. The default value is D3DSTENCILOP_KEEP. For more information, see Stencil Buffers.
D3DRENDERSTATE_STENCILZFAIL
Stencil operation to perform if the stencil test passes and depth test (z-test) fails. This can be one of the members of the D3DSTENCILOP enumerated type. The default value is D3DSTENCILOP_KEEP. For more information, see Stencil Buffers.
D3DRENDERSTATE_STENCILPASS
Stencil operation to perform if both the stencil and depth (z) tests pass. This can be one of the members of the D3DSTENCILOP enumerated type. The default value is D3DSTENCILOP_KEEP. For more information, see Stencil Buffers.
D3DRENDERSTATE_STENCILFUNC
Comparison function for the stencil test. This can be one of the members of the D3DCMPFUNC enumerated type. The default value is D3DCMP_ALWAYS.

The comparison function is used to compare the reference value to a stencil buffer entry. This comparison only applies to the bits in the reference value and stencil buffer entry that are set in the stencil mask (set by the D3DRENDERSTATE_STENCILMASK render state). If the comparison is true, the stencil test passes.

D3DRENDERSTATE_STENCILREF
Integer reference value for the stencil test. The default value is 0.
D3DRENDERSTATE_STENCILMASK
Mask applied to the reference value and each stencil buffer entry to determine the significant bits for the stencil test. The default mask is 0xFFFFFFFF.
D3DRENDERSTATE_STENCILWRITEMASK
Write mask applied to values written into the stencil buffer. The default mask is 0xFFFFFFFF.
D3DRENDERSTATE_TEXTUREFACTOR
Color used for multiple texture blending with the D3DTA_TFACTOR texture-blending argument or D3DTOP_BLENDFACTORALPHA texture-blending operation. The associated value is a D3DCOLOR variable.
D3DRENDERSTATE_STIPPLEPATTERN00 through D3DRENDERSTATE_STIPPLEPATTERN31
Stipple pattern. Each render state applies to a separate line of the stipple pattern. Together, these render states specify a 32x32 stipple pattern.
D3DRENDERSTATE_WRAP0 through D3DRENDERSTATE_WRAP7
Texture wrapping behavior for multiple textures. Valid values for these render states are a combination of one or both of the D3DWRAP_U and D3DWRAP_V flags, which cause the system to wrap in the u and v directions for a given texture. The default value for these render states is 0 (wrapping disabled in both directions). For more information, see Texture Wrapping.
D3DRENDERSTATE_FORCE_DWORD
Forces this enumerated type to be 32 bits in size.

Remarks

The D3DRENDERSTATE_BLENDENABLE member was superseded by the D3DRENDERSTATE_ALPHABLENDENABLE member. Its name was changed to make its meaning more explicit. To maintain compatibility with legacy applications, the D3DRENDERSTATE_BLENDENABLE constant is declared as equivalent to D3DRENDERSTATE_ALPHABLENDENABLE:

#define D3DRENDERSTATE_BLENDENABLE  D3DRENDERSTATE_ALPHABLENDENABLE

Direct3D defines the D3DRENDERSTATE_WRAPBIAS constant as a convenience for applications to enable or disable texture wrapping based on the zero-based integer of a texture coordinate set (rather than explicitly using one of the D3DRENDERSTATE_WRAPn state values). Add the D3DRENDERSTATE_WRAPBIAS value to the zero-based index of a texture coordinate set to calculate the D3DRENDERSTATE_WRAPn value that corresponds to that index, as shown in the following example:

// Enable U/V wrapping for textures that use the texture
// coordinate set at the index within the dwIndex variable.
HRESULT hr = lpD3DDevice->SetRenderState(
    dwIndex + D3DRENDERSTATE_WRAPBIAS,
    D3DWRAP_U | D3DWRAPV);

// If dwIndex is 3, the value that results from
// the addition equates to D3DRENDERSTATE_WRAP3 (131).

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.

See Also

D3DOPCODE, D3DSTATE


D3DSHADEMODE

The D3DSHADEMODE enumerated type describes the supported shade mode for the D3DRENDERSTATE_SHADEMODE render state in the D3DRENDERSTATETYPE enumerated type.

typedef enum _D3DSHADEMODE {
    D3DSHADE_FLAT         = 1,
    D3DSHADE_GOURAUD      = 2,
    D3DSHADE_PHONG        = 3,
    D3DSHADE_FORCE_DWORD  = 0x7fffffff,
} D3DSHADEMODE;

Members

D3DSHADE_FLAT
Flat shade mode. The color and specular component of the first vertex in the triangle are used to determine the color and specular component of the face. These colors remain constant across the triangle; that is, they aren't interpolated.
D3DSHADE_GOURAUD
Gouraud shade mode. The color and specular components of the face are determined by a linear interpolation between all three of the triangle's vertices.
D3DSHADE_PHONG
Phong shade mode is not currently supported.
D3DSHADE_FORCE_DWORD
Forces this enumerated type to be 32 bits in size.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.

See Also

D3DRENDERSTATETYPE


D3DSTENCILOP

The D3DSTENCILOP enumerated type describes the stencil operations for the D3DRENDERSTATE_STENCILFAIL, D3DRENDERSTATE_STENCILZFAIL, D3DRENDERSTATE_STENCILPASS render states.

typedef enum _D3DSTENCILOP {
    D3DSTENCILOP_KEEP           = 1,
    D3DSTENCILOP_ZERO           = 2,
    D3DSTENCILOP_REPLACE        = 3,
    D3DSTENCILOP_INCRSAT        = 4,
    D3DSTENCILOP_DECRSAT        = 5,
    D3DSTENCILOP_INVERT         = 6,
    D3DSTENCILOP_INCR           = 7,
    D3DSTENCILOP_DECR           = 8,
    D3DSTENCILOP_FORCE_DWORD    = 0x7fffffff
} D3DSTENCILOP;

Members

D3DSTENCILOP_KEEP
Do not update the entry in the stencil buffer. This is the default value.
D3DSTENCILOP_ZERO
Set the stencil-buffer entry to zero.
D3DSTENCILOP_REPLACE
Replace the stencil-buffer entry with reference value.
D3DSTENCILOP_INCRSAT
Increment the stencil-buffer entry, clamping to the maximum value. See remarks for infomation on the maximum stencil-buffer values.
D3DSTENCILOP_DECRSAT
Decrement the stencil-buffer entry, clamping to zero.
D3DSTENCILOP_INVERT
Invert the bits in the stencil-buffer entry.
D3DSTENCILOP_INCR
Increment the stencil-buffer entry, wrapping to zero if the new value exceeds the maximum value. See remarks for infomation on the maximum stencil-buffer values.
D3DSTENCILOP_DECR
Decrement the stencil-buffer entry, wrapping to the maximum value if the new value is less than zero.
D3DSTENCILOP_FORCE_DWORD
Forces this enumeration to be compiled to 32 bits in size. This value is not used.

Remarks

Stencil-buffer entries are integer values ranging inclusively from 0 to 2n -1, where n is the bit depth of the stencil buffer.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.

See Also

D3DRENDERSTATETYPE, Stencil Buffers


D3DTEXTUREADDRESS

The D3DTEXTUREADDRESS enumerated type describes the supported texture addressing modes when setting them with IDirect3DDevice3::SetTextureStageState or with the D3DRENDERSTATE_TEXTUREADDRESS render state.

typedef enum _D3DTEXTUREADDRESS {
    D3DTADDRESS_WRAP         = 1,
    D3DTADDRESS_MIRROR       = 2,
    D3DTADDRESS_CLAMP        = 3,
    D3DTADDRESS_BORDER       = 4,
    D3DTADDRESS_FORCE_DWORD  = 0x7fffffff,
} D3DTEXTUREADDRESS;

Members

D3DTADDRESS_WRAP
Tile the texture at every integer junction. For example, for u values between 0 and 3, the texture will be repeated three times; no mirroring is performed.
D3DTADDRESS_MIRROR
Similar to D3DTADDRESS_WRAP, except that the texture is flipped at every integer junction. For u values between 0 and 1, for example, the texture is addressed normally, between 1 and 2 the texture is flipped (mirrored), between 2 and 3 the texture is normal again, and so on.
D3DTADDRESS_CLAMP
Texture coordinates outside the range [0.0, 1.0] are set to the texture color at 0.0 or 1.0, respectively.
D3DTADDRESS_BORDER
Texture coordinates outside the range [0.0, 1.0] are set to the border color, which is a new render state corresponding to D3DRENDERSTATE_BORDERCOLOR in the D3DRENDERSTATETYPE enumerated type.
D3DTADDRESS_FORCE_DWORD
Forces this enumerated type to be 32 bits in size.

Remarks

For information about using the D3DRENDERSTATE_WRAPU and D3DRENDERSTATE_WRAPV render states, see Textures.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.

See Also

D3DRENDERSTATETYPE


D3DTEXTUREBLEND

The D3DTEXTUREBLEND enumerated type defines the supported texture-blending modes. This enumerated type is used by the D3DRENDERSTATE_TEXTUREMAPBLEND render state in the D3DRENDERSTATETYPE enumerated type.

typedef enum _D3DTEXTUREBLEND {
    D3DTBLEND_DECAL         = 1,
    D3DTBLEND_MODULATE      = 2,
    D3DTBLEND_DECALALPHA    = 3,
    D3DTBLEND_MODULATEALPHA = 4,
    D3DTBLEND_DECALMASK     = 5,
    D3DTBLEND_MODULATEMASK  = 6,
    D3DTBLEND_COPY          = 7,
    D3DTBLEND_ADD           = 8,
    D3DTBLEND_FORCE_DWORD   = 0x7fffffff,
} D3DTEXTUREBLEND;

Members

D3DTBLEND_DECAL
Decal texture-blending mode is supported. In this mode, the RGB and alpha values of the texture replace the colors that would have been used with no texturing.
cPix = cTex
aPix = aTex
D3DTBLEND_MODULATE
Modulate texture-blending mode is supported. In this mode, the RGB values of the texture are multiplied with the RGB values that would have been used with no texturing. Any alpha values in the texture replace the alpha values in the colors that would have been used with no texturing; if the texture does not contain an alpha component, alpha values at the vertices in the source are interpolated between vertices.
cPix = cSrc * cTex
if( the texture has an alpha channel)
  aPix = aTex
else
  aPix = aSrc
D3DTBLEND_DECALALPHA
Decal-alpha texture-blending mode is supported. In this mode, the RGB and alpha values of the texture are blended with the colors that would have been used with no texturing, according to the following formulas:
cPix = (cSrc * (1.0 - aTex)) + (aTex * cTex)
aPix = aSrc
D3DTBLEND_MODULATEALPHA
Modulate-alpha texture-blending mode is supported. In this mode, the RGB values of the texture are multiplied with the RGB values that would have been used with no texturing, and the alpha values of the texture are multiplied with the alpha values that would have been used with no texturing.
cPix = cSrc * cTex
aPix = aSrc * aTex
D3DTBLEND_DECALMASK
This blending mode is not supported.
cPix = lsb(aTex) ? cTex : cSrc
aPix = aSrc

When the least-significant bit of the texture's alpha component is zero, the effect is as if texturing were disabled.

D3DTBLEND_MODULATEMASK
This blending mode is not supported.
cPix = lsb(aTex) ? cTex * cSrc : cSrc
aPix = aSrc

When the least-significant bit of the texture's alpha component is zero, the effect is as if texturing were disabled.

D3DTBLEND_COPY
This blending mode is obsolete, and is treated as equivalent to the D3DTBLEND_DECAL texture-blending mode.
D3DTBLEND_ADD
Add the Gouraud interpolants to the texture lookup with saturation semantics (that is, if the color value overflows it is set to the maximum possible value). This member was introduced in DirectX 5.0.
cPix = cTex + cSrc
aPix = aSrc
D3DTBLEND_FORCE_DWORD
Forces this enumerated type to be 32 bits in size.

Remarks

In the formulas given for the members of this enumerated type, the placeholders have the following meanings:

  • cTex is the color of the source texel
  • aTex is the alpha component of the source texel
  • cSrc is the interpolated color of the source primitive
  • aSrc is the alpha component of the source primitive
  • cPix is the new blended color value
  • aPix is the new blended alpha value

Modulation combines the effects of lighting and texturing. Because colors are specified as values between and including 0 and 1, modulating (multiplying) the texture and preexisting colors together typically produces colors that are less bright than either source. The brightness of a color component is undiminished when one of the sources for that component is white (1). The simplest way to ensure that the colors of a texture do not change when the texture is applied to an object is to ensure that the object is white (1,1,1).

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.


D3DTEXTUREFILTER

The D3DTEXTUREFILTER enumerated type defines the supported texture filter modes used by the D3DRENDERSTATE_TEXTUREMAG render state in the D3DRENDERSTATETYPE enumerated type.

typedef enum _D3DTEXTUREFILTER {
    D3DFILTER_NEAREST          = 1,
    D3DFILTER_LINEAR           = 2,
    D3DFILTER_MIPNEAREST       = 3,
    D3DFILTER_MIPLINEAR        = 4,
    D3DFILTER_LINEARMIPNEAREST = 5,
    D3DFILTER_LINEARMIPLINEAR  = 6,
    D3DFILTER_FORCE_DWORD   = 0x7fffffff,
} D3DTEXTUREFILTER;

Members

D3DFILTER_NEAREST
The texel with coordinates nearest to the desired pixel value is used. This is a point filter with no mipmapping.

This applies to both zooming in and zooming out. If either zooming in or zooming out is supported, then both must be supported.

D3DFILTER_LINEAR
A weighted average of a 2×2 area of texels surrounding the desired pixel is used. This is a bilinear filter with no mipmapping.

This applies to both zooming in and zooming out. If either zooming in or zooming out is supported, then both must be supported.

D3DFILTER_MIPNEAREST
The closest mipmap level is chosen and a point filter is applied.
D3DFILTER_MIPLINEAR
The closest mipmap level is chosen and a bilinear filter is applied within it.
D3DFILTER_LINEARMIPNEAREST
The two closest mipmap levels are chosen and then a linear blend is used between point filtered samples of each level.
D3DFILTER_LINEARMIPLINEAR
The two closest mipmap levels are chosen and then combined using a bilinear filter.
D3DFILTER_FORCE_DWORD
Forces this enumerated type to be 32 bits in size.

Remarks

All of these filter modes are valid with the D3DRENDERSTATE_TEXTUREMIN render state, but only the first two (D3DFILTER_NEAREST and D3DFILTER_LINEAR) are valid with D3DRENDERSTATE_TEXTUREMAG.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.


D3DTEXTUREMAGFILTER

The D3DTEXTUREMAGFILTER enumerated type defines texture magnification filtering modes for a texture stage.

typedef enum _D3DTEXTUREMAGFILTER {
    D3DTFG_POINT        = 1,
    D3DTFG_LINEAR       = 2,
    D3DTFG_FLATCUBIC    = 3,
    D3DTFG_GAUSSIANCUBIC= 4,
    D3DTFG_ANISOTROPIC  = 5,
    D3DTFG_FORCE_DWORD  = 0x7fffffff,
} D3DTEXTUREMAGFILTER;

Members

D3DTFG_POINT
Point filtering. The texel with coordinates nearest to the desired pixel value is used.
D3DTFG_LINEAR
Bilinear interpolation filtering. A weighted average of a 2×2 area of texels surrounding the desired pixel is used.
D3DTFG_FLATCUBIC
Not currently supported; do not use.
D3DTFG_GAUSSIANCUBIC
Not currently supported; do not use.
D3DTFG_ANISOTROPIC
Anisotropic texture filtering. Compensates for distortion caused by the difference in angle between the texture polygon and the plane of the screen.
D3DTFG_FORCE_DWORD
Forces this enumerated type to compile to 32 bits in size.

Remarks

You set a texture stage's magnification filter by calling the IDirect3DDevice3::SetTextureStageState method with the D3DTSS_MAGFILTER value as the second parameter, and one of members of this enumeration as the third parameter.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.

See Also

D3DTEXTUREMINFILTER, D3DTEXTUREMIPFILTER, Texture Filtering


D3DTEXTUREMINFILTER

The D3DTEXTUREMINFILTER enumerated type defines texture minification filtering modes for a texture stage.

typedef enum _D3DTEXTUREMINFILTER {
    D3DTFN_POINT        = 1,
    D3DTFN_LINEAR       = 2,
    D3DTFN_ANISOTROPIC  = 3,
    D3DTFN_FORCE_DWORD  = 0x7fffffff,
} D3DTEXTUREMINFILTER;

Members

D3DTFN_POINT
Point filtering. The texel with coordinates nearest to the desired pixel value is used.
D3DTFN_LINEAR
Bilinear interpolation filtering. A weighted average of a 2×2 area of texels surrounding the desired pixel is used.
D3DTFN_ANISOTROPIC
Anisotropic texture filtering. Compensates for distortion caused by the difference in angle between the texture polygon and the plane of the screen.
D3DTFN_FORCE_DWORD
Forces this enumerated type to compile to 32 bits in size.

Remarks

You set a texture stage's magnification filter by calling the IDirect3DDevice3::SetTextureStageState method with the D3DTSS_MINFILTER value as the second parameter, and one of members of this enumeration as the third parameter.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.

See Also

D3DTEXTUREMAGFILTER, D3DTEXTUREMIPFILTER, Texture Filtering


D3DTEXTUREMIPFILTER

The D3DTEXTUREMIPFILTER enumerated type defines texture mipmap filtering modes for a texture stage.

typedef enum _D3DTEXTUREMIPFILTER {
    D3DTFP_NONE         = 1,
    D3DTFP_POINT        = 2,
    D3DTFP_LINEAR       = 3,
    D3DTFP_FORCE_DWORD  = 0x7fffffff,
} D3DTEXTUREMIPFILTER;

Members

D3DTFP_NONE
Mipmapping disabled. The rasterizer should use the magnification filter instead.
D3DTFP_POINT
Nearest point mipmap filtering. The rasterizer uses the color from the texel of the nearest mipmap texture.
D3DTFP_LINEAR
Trilinear mipmap interpolation. The rasterizer linearly interpolates pixel color using the texels of the two nearest mipmap textures.
D3DTFP_FORCE_DWORD
Forces this enumerated type to compile to 32 bits in size.

Remarks

You set a texture stage's magnification filter by calling the IDirect3DDevice3::SetTextureStageState method with the D3DTSS_MIPFILTER value as the second parameter, and one of members of this enumeration as the third parameter.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.

See Also

D3DTEXTUREMAGFILTER, D3DTEXTUREMIPFILTER, Texture Filtering


D3DTEXTUREOP

The D3DTEXTUREOP enumerated type defines per-stage texture blending operations. The members of this type are used when setting color or alpha operations by using the D3DTSS_COLOROP or D3DTSS_ALPHAOP values with the IDirect3DDevice3::SetTextureStageState method.

typedef enum _D3DTEXTUREOP {
    D3DTOP_DISABLE    = 1,
    D3DTOP_SELECTARG1 = 2,
    D3DTOP_SELECTARG2 = 3,
    D3DTOP_MODULATE   = 4,
    D3DTOP_MODULATE2X = 5,
    D3DTOP_MODULATE4X = 6,
    D3DTOP_ADD        = 7,
    D3DTOP_ADDSIGNED  = 8,
    D3DTOP_ADDSIGNED2X  =  9,
    D3DTOP_SUBTRACT     = 10,
    D3DTOP_ADDSMOOTH    = 11,
    D3DTOP_BLENDDIFFUSEALPHA    = 12,
    D3DTOP_BLENDTEXTUREALPHA    = 13,
    D3DTOP_BLENDFACTORALPHA     = 14,
    D3DTOP_BLENDTEXTUREALPHAPM  = 15,
    D3DTOP_BLENDCURRENTALPHA    = 16,
    D3DTOP_PREMODULATE            = 17,
    D3DTOP_MODULATEALPHA_ADDCOLOR = 18,
    D3DTOP_MODULATECOLOR_ADDALPHA = 19,
    D3DTOP_MODULATEINVALPHA_ADDCOLOR = 20,
    D3DTOP_MODULATEINVCOLOR_ADDALPHA = 21,
    D3DTOP_BUMPENVMAP           = 22,
    D3DTOP_BUMPENVMAPLUMINANCE  = 23,
    D3DTOP_DOTPRODUCT3          = 24,
    D3DTOP_FORCE_DWORD = 0x7fffffff,
} D3DTEXTUREOP;

Members

Control members
D3DTOP_DISABLE
Disables output from this texture stage and all stages with a higher index. To disable texture mapping, set this operation for the first texture stage (stage 0).
D3DTOP_SELECTARG1
Use this texture stage's first color or alpha argument, unmodified, as the output. This operation affects the color argument when used with the D3DTSS_COLOROP texture stage state, and the alpha argument when used with D3DTSS_ALPHAOP.

D3DTOP_SELECTARG2
Use this texture stage's second color or alpha argument, unmodified, as the output. This operation affects the color argument when used with the D3DTSS_COLOROP texture stage state, and the alpha argument when used with D3DTSS_ALPHAOP.

Modulation members
D3DTOP_MODULATE
Multiply the components of the arguments together.

D3DTOP_MODULATE2X
Multiply the components of the arguments and shift the products to the left one bit (effectively multiplying them by two) for brightening.

D3DTOP_MODULATE4X
Multiply the components of the arguments and shift the products to the left two bits (effectively multiplying them by four) for brightening.

Addition and Subtraction members
D3DTOP_ADD
Add the components of the arguments.

D3DTOP_ADDSIGNED
Add the components of the arguments with a -0.5 bias, making the effective range of values from -0.5 to 0.5.

D3DTOP_ADDSIGNED2X
Add the components of the arguments with a -0.5 bias, and shift the products to the left one bit.

D3DTOP_SUBTRACT
Subtract the components of the second argument from those of the first argument.

D3DTOP_ADDSMOOTH
Add the first and second arguments, then subract their product from the sum.

Linear alpha blending members
D3DTOP_BLENDDIFFUSEALPHA
D3DTOP_BLENDTEXTUREALPHA
D3DTOP_BLENDFACTORALPHA
D3DTOP_BLENDCURRENTALPHA
Linearly blend this texture stage using the interpolated alpha from each vertex (D3DTOP_BLENDDIFFUSEALPHA), alpha from this stage's texture (D3DTOP_BLENDTEXTUREALPHA), a scalar alpha (D3DTOP_BLENDFACTORALPHA) set with the D3DRENDERSTATE_TEXTUREFACTOR render state, or the alpha taken from the previous texture stage (D3DTOP_BLENDCURRENTALPHA).

D3DTOP_BLENDTEXTUREALPHAPM
Linearly blend a texture stage that uses premultiplied alpha.

Specular mapping members
D3DTOP_PREMODULATE
Modulate this texture stage with the next texture stage.
D3DTOP_MODULATEALPHA_ADDCOLOR
Modulate the second argument's color using the first argument's alpha, then add the result to argument one. This operation is supported only for color operations (D3DTSS_COLOROP).

D3DTOP_MODULATECOLOR_ADDALPHA
Modulate the arguments, then add the first argument's alpha. This operation is supported only for color operations (D3DTSS_COLOROP).

D3DTOP_MODULATEINVALPHA_ADDCOLOR
Similar to D3DTOP_MODULATEALPHA_ADDCOLOR, but use the inverse of the first argument's alpha. This operation is supported only for color operations (D3DTSS_COLOROP).

D3DTOP_MODULATEINVCOLOR_ADDALPHA
Similar to D3DTOP_MODULATECOLOR_ADDALPHA, but use the inverse of the first argument's color. This operation is supported only for color operations (D3DTSS_COLOROP).

Bump mapping members
D3DTOP_BUMPENVMAP
Perform per-pixel bump-mapping using the environment map in the next texture stage (without luminance). This operation is supported only for color operations (D3DTSS_COLOROP).
D3DTOP_BUMPENVMAPLUMINANCE
Perform per-pixel bump-mapping using the environment map in the next texture stage (with luminance). This operation is supported only for color operations (D3DTSS_COLOROP).
D3DTOP_DOTPRODUCT3
Modulate the components of each argument (as signed components), add their products, then replicate the sum to all color channels, including alpha. This operation is supported for color and alpha operations.

Miscellaneous member
D3DTOP_FORCE_DWORD
Forces this enumerated type to be compiled to 32 bits in size. This value is not used.

Remarks

In the preceding formulas, SRGBA is the RGBA color produced by a texture operation, and Arg1 and Arg2 represent the complete RGBA color of the texture arguments. Individual components of an argument are shown with subscripts. For example, the alpha component for argument one would be shown as Arg1A.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.

See Also

IDirect3DDevice3::GetTextureStageState, IDirect3DDevice3::SetTextureStageState, D3DTEXTURESTAGESTATETYPE


D3DTEXTURESTAGESTATETYPE

The D3DTEXTURESTAGESTATETYPE enumerated type defines texture stage states. Members of this enumerated type are used with the IDirect3DDevice3::GetTextureStageState and IDirect3DDevice3::SetTextureStageState methods to retrieve and set texture state values.

typedef enum _D3DTEXTURESTAGESTATETYPE {
    D3DTSS_COLOROP        = 1,
    D3DTSS_COLORARG1      = 2,
    D3DTSS_COLORARG2      = 3,
    D3DTSS_ALPHAOP        = 4,
    D3DTSS_ALPHAARG1      = 5,
    D3DTSS_ALPHAARG2      = 6,
    D3DTSS_BUMPENVMAT00   = 7,
    D3DTSS_BUMPENVMAT01   = 8,
    D3DTSS_BUMPENVMAT10   = 9,
    D3DTSS_BUMPENVMAT11   = 10,
    D3DTSS_TEXCOORDINDEX  = 11,
    D3DTSS_ADDRESS        = 12,
    D3DTSS_ADDRESSU       = 13,
    D3DTSS_ADDRESSV       = 14,
    D3DTSS_BORDERCOLOR    = 15,
    D3DTSS_MAGFILTER      = 16,
    D3DTSS_MINFILTER      = 17,
    D3DTSS_MIPFILTER      = 18,
    D3DTSS_MIPMAPLODBIAS  = 19,
    D3DTSS_MAXMIPLEVEL    = 20,
    D3DTSS_MAXANISOTROPY  = 21,
    D3DTSS_BUMPENVLSCALE  = 22,
    D3DTSS_BUMPENVLOFFSET = 23,
    D3DTSS_FORCE_DWORD   = 0x7fffffff,
} D3DTEXTURESTAGESTATETYPE;

Members

D3DTSS_COLOROP
The texture stage state is a texture color blending operation identified by one of the members of the D3DTEXTUREOP enumerated type. The default value for the first texture stage (stage zero) is D3DTOP_MODULATE, and for all other stages the default is D3DTOP_DISABLE.
D3DTSS_COLORARG1
The texture stage state is the first color argument for the stage, identified by a texture argument flag. The default argument is D3DTA_TEXTURE.
D3DTSS_COLORARG2
The texture stage state is the second color argument for the stage, identified by a texture argument flag. The default argument is D3DTA_CURRENT.
D3DTSS_ALPHAOP
The texture stage state is texture alpha blending operation identified by one of the members of the D3DTEXTUREOP enumerated type. The default value for the first texture stage (stage zero) is D3DTOP_SELECTARG1, and for all other stages the default is D3DTOP_DISABLE.
D3DTSS_ALPHAARG1
The texture stage state is the first alpha argument for the stage, identified by a texture argument flag. The default argument is D3DTA_TEXTURE. If no texture is set for this stage, the default argument is D3DTA_DIFFUSE.
D3DTSS_ALPHAARG2
The texture stage state is the second alpha argument for the stage, identified by a texture argument flag. The default argument is D3DTA_CURRENT.
D3DTSS_BUMPENVMAT00
The texture stage state is a D3DVALUE for the [0][0] coefficient in a bump mapping matrix. The default value is zero.
D3DTSS_BUMPENVMAT01
The texture stage state is a D3DVALUE for the [0][1] coefficient in a bump mapping matrix. The default value is 0.
D3DTSS_BUMPENVMAT10
The texture stage state is a D3DVALUE for the [1][0] coefficient in a bump mapping matrix. The default value is 0.
D3DTSS_BUMPENVMAT11
The texture stage state is a D3DVALUE for the [1][1] coefficient in a bump mapping matrix. The default value is 0.
D3DTSS_TEXCOORDINDEX
Index of the texture coordinate set to use with this texture stage. The default index is 0. Set this state to the zero-based index of the coordinate set for each vertex that this texture stage will use. (You can specify up to eight sets of texture coordinates per vertex.) If a vertex does not include a set of texture coordinates at the specified index, the system defaults to using the u, v coordinates (0,0).
D3DTSS_ADDRESS
Member of the D3DTEXTUREADDRESS enumerated type. Selects the texture addressing method for both the u and v coordinates. The default is D3DTADDRESS_WRAP.
D3DTSS_ADDRESSU
Member of the D3DTEXTUREADDRESS enumerated type. Selects the texture addressing method for the u coordinate. The default is D3DTADDRESS_WRAP.
D3DTSS_ADDRESSV
Member of the D3DTEXTUREADDRESS enumerated type. Selects the texture addressing method for the v coordinate. The default value is D3DTADDRESS_WRAP.
D3DTSS_BORDERCOLOR
D3DCOLOR value that describes the color to be used for rasterizing texture coordinates outside the [0.0,1.0] range. The default color is 0x00000000.
D3DTSS_MAGFILTER
Member of the D3DTEXTUREMAGFILTER enumerated type that indicates the texture magnification filter to be used when rendering the texture onto primitives. The default value is D3DTFG_POINT.
D3DTSS_MINFILTER
Member of the D3DTEXTUREMINFILTER enumerated type that indicates the texture magnification filter to be used when rendering the texture onto primitives. The default value is D3DTFN_POINT.
D3DTSS_MIPFILTER
Member of the D3DTEXTUREMIPFILTER enumerated type that indicates the texture magnification filter to be used when rendering the texture onto primitives. The default value is D3DTFP_NONE.
D3DTSS_MIPMAPLODBIAS
Level of detail bias for mipmaps. Can be used to make textures appear more chunky or more blurred. The default value is 0.
D3DTSS_MAXMIPLEVEL
Maximum mipmap level-of-detail that the application will allow, expressed as an index from the top of the mipmap chain. (Lower values identify higher levels of detail within the mipmap chain). Zero, which is the default, indicates that all levels can be used. Non-zero values indicate that the application does not want to display mipmaps that have a higher level-of-detail than the mipmap at the specified index.
D3DTSS_MAXANISOTROPY
Maximum level of anisotropy. The default value is 1.
D3DTSS_BUMPENVLSCALE
D3DVALUE scale for bump map luminance. The default value is 0.
D3DTSS_BUMPENVLOFFSET
D3DVALUE offset for bump map luminance. The default value is 0.
D3DTSS_FORCE_DWORD
Forces this enumerated type to be compiled to 32 bits in size. This value is not used.

Remarks

The valid range of values for the D3DTSS_BUMPENVMAT00, D3DTSS_BUMPENVMAT01, D3DTSS_BUMPENVMAT10, and D3DTSS_BUMPENVMAT11 bump-mapping matrix coefficients is greater than or equal to -8.0, and less than 8.0. This range, expressed in mathematical notation is [-8.0,8.0).

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.


D3DTRANSFORMSTATETYPE

The D3DTRANSFORMSTATETYPE enumerated type describes the transformation state for the D3DOP_STATETRANSFORM opcode in the D3DOPCODE enumerated type. This enumerated type is part of the D3DSTATE structure.

typedef enum _D3DTRANSFORMSTATETYPE {
    D3DTRANSFORMSTATE_WORLD        = 1,
    D3DTRANSFORMSTATE_VIEW         = 2,
    D3DTRANSFORMSTATE_PROJECTION   = 3,
    D3DTRANSFORMSTATE_FORCE_DWORD  = 0x7fffffff,
} D3DTRANSFORMSTATETYPE;

Members

D3DTRANSFORMSTATE_WORLD
Define the matrices for the world transformation. The default value is NULL (the identity matrix).
D3DTRANSFORMSTATE_VIEW
Define the matrices for the view transformation. The default value is NULL (the identity matrix).
D3DTRANSFORMSTATE_PROJECTION
Define the matrices for the projection transformation. The default value is NULL (the identity matrix).
D3DTRANSFORMSTATE_FORCE_DWORD
Forces this enumerated type to be 32 bits in size.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.

See Also

D3DOPCODE, D3DRENDERSTATETYPE


D3DVERTEXTYPE

The D3DVERTEXTYPE enumerated type lists the vertex types that are supported by the legacy IDirect3DDevice2 and IDirect3DDevice interfaces. If your application uses IDirect3DDevice3, the D3DVERTEXTYPE enumerated type is superseded by flexible vertex format flags.

typedef enum _D3DVERTEXTYPE {
    D3DVT_VERTEX       = 1,
    D3DVT_LVERTEX      = 2,
    D3DVT_TLVERTEX     = 3
    D3DVT_FORCE_DWORD  = 0x7fffffff,
} D3DVERTEXTYPE;

Members

D3DVT_VERTEX
All the vertices in the array are of the D3DVERTEX type. This setting will cause transformation, lighting and clipping to be applied to the primitive as it is rendered.
D3DVT_LVERTEX
All the vertices in the array are of the D3DLVERTEX type. When used with this option, the primitive will have transformations applied during rendering.
D3DVT_TLVERTEX
All the vertices in the array are of the D3DTLVERTEX type. Rasterization only will be applied to this data.
D3DVT_FORCE_DWORD
Forces this enumerated type to be 32 bits in size.

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.

See Also

Vertex Formats


D3DZBUFFERTYPE

The D3DZBUFFERTYPE enumerated type describes depth-buffer formats for use with the D3DRENDERSTATE_ZENABLE render state.

typedef enum _D3DZBUFFERTYPE {
    D3DZB_FALSE        = 0,
    D3DZB_TRUE         = 1,
    D3DZB_USEW         = 2,
    D3DZB_FORCE_DWORD  = 0x7fffffff,
} D3DZBUFFERTYPE;

Members

D3DZB_FALSE
Disable depth-buffering.
D3DZB_TRUE
Enable z-buffering.
D3DZB_USEW
Enable w-buffering. To use w-buffering, perspective-correct texture mapping must also be enabled. To enable perspective-correct texture mapping, set the D3DRENDERSTATE_TEXTUREPERSPECTIVE render state to TRUE. For DirectX 6.0, this is the default value.
D3DZB_FORCE_DWORD
Forces this enumeration to be compiled to 32-bits in size. This value is not used.

Remarks

The D3DZB_FALSE and D3DZB_TRUE values are interchangeable with the TRUE and FALSE macro values previously used with D3DRENDERSTATE_ZENABLE.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.

See Also

IDirect3DDevice3::SetRenderState, Depth Buffers


Other Types

This section contains information about the following Direct3D Immediate Mode types that are neither structures nor enumerated types:

  • D3DCOLOR
  • D3DCOLORMODEL
  • D3DFIXED
  • D3DVALUE


D3DCOLOR

The D3DCOLOR type is the fundamental Direct3D color type.

typedef DWORD D3DCOLOR, D3DCOLOR, *LPD3DCOLOR;

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.

See Also

D3DRGB, D3DRGBA


D3DCOLORMODEL

The D3DCOLORMODEL type is used to define the color model in which the system will run. A driver can expose either or both flags in the dcmColorModel member of the D3DDEVICEDESC structure.

typedef DWORD D3DCOLORMODEL

Values

D3DCOLOR_MONO
Use a monochromatic model (or ramp model). In this model, the blue component of a vertex color is used to define the brightness of a lit vertex.
D3DCOLOR_RGB
Use a full RGB model.

Remarks

Prior to DirectX 5.0, these values were part of an enumerated type. The enumerated type in earlier versions of DirectX had this syntax:

typedef enum _D3DCOLORMODEL {
    D3DCOLOR_MONO = 1,
    D3DCOLOR_RGB  = 2,
} D3DCOLORMODEL;

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.

See Also

D3DDEVICEDESC, D3DFINDDEVICESEARCH, D3DLIGHTSTATETYPE


D3DFIXED

The D3DFIXED type is used to represent a 16:16 fixed point value.

typedef LONG D3DFIXED;

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.


D3DVALUE

The D3DVALUE type is the fundamental Direct3D fractional data type.

typedef float D3DVALUE, *LPD3DVALUE;

QuickInfo

Windows NT/2000: Requires Windows NT 4.0 SP3 or later.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in d3dtypes.h.


Flexible Vertex Format Flags

Direct3D Immediate Mode uses flag values to describe vertex formats used for DrawPrimitive-based rendering. The D3dtypes.h header file defines the following flags to explicitly describe a vertex format, and provides helper macros that act as common combinations of such flags. For more information, see About Vertex Formats.

Flexible vertex format (FVF) flags
D3DFVF_DIFFUSE
Vertex format includes a diffuse color component.
D3DFVF_NORMAL
Vertex format includes a vertex normal vector. This flag cannot be used with the D3DFVF_XYZRHW flag.
D3DFVF_SPECULAR
Vertex format includes a specular color component.
D3DFVF_XYZ
Vertex format includes the position of an untransformed vertex. This flag cannot be used with the D3DFVF_XYZRHW flag. If you use this flag, you must also specify a vertex normal, a vertex color component (D3DFVF_DIFFUSE or D3DFVF_SPECULAR), or include at least one set of texture coordinates (D3DFVF_TEX1 through D3DFVF_TEX8).
D3DFVF_XYZRHW
Vertex format includes the position of a transformed vertex. This flag cannot be used with the D3DFVF_XYZ or D3DFVF_NORMAL flags. If you use this flag, you must also specify a vertex color component (D3DFVF_DIFFUSE or D3DFVF_SPECULAR) or include at least one set of texture coordinates (D3DFVF_TEX1 through D3DFVF_TEX8).
Texture-related FVF flags
D3DFVF_TEX0 through D3DFVF_TEX8
Number of texture coordinate sets for this vertex. The actual values for these flags are not sequential.
Helper macros
D3DFVF_LVERTEX
Vertex format is equivalent to the D3DLVERTEX vertex type.
D3DFVF_TLVERTEX
Vertex format is equivalent to the D3DTLVERTEX vertex type.
D3DFVF_VERTEX
Vertex format is equivalent to the D3DVERTEX vertex type.
Mask values
D3DFVF_POSITION_MASK
Mask for position bits.
D3DFVF_RESERVED0 and D3DFVF_RESERVED2
Mask values for reserved bits in the flexible vertex format. Do not use.
D3DFVF_RESERVED1,
This bit is reserved to indicate that the system should emulate D3DLVERTEX processing. If this flag is used, the D3DFVF_XYZ, D3DFVF_DIFFUSE, D3DFVF_SPECULAR, and D3DFVF_TEX1 flags must also be used. This equates to the effect of the D3DFVF_LVERTEX helper macro.
D3DFVF_TEXCOUNT_MASK
Mask value for texture flag bits.
Miscellaneous
D3DFVF_TEXCOUNT_SHIFT
The number of bits to shift an integer value that identifies the number of a texture coordinates for a vertex. This value might be used as follows:
    DWORD dwNumTextures = 1;  // vertex has only one set of coordinates

    // Shift the value for use when creating an FVF combination.
    dwFVF = dwNumTextures<<D3DFVF_TEXCOUNT_SHIFT;

    /*
     * Now, create an FVF combination using the shifted value.
     */

The following example shows some other common flag combinations:

    // Lightweight, untransformed vertex for lit, untextured,
    // Gouraud-shaded content.
    dwFVF = ( D3DFVF_XYZ | D3DFVF_DIFFUSE );

    // Untransformed vertex for unlit, untextured, Gouraud-shaded
    // content with diffuse material color specified per vertex.
    dwFVF = ( D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE );

    // Untransformed vertex for light-map based lighting.
    dwFVF = ( D3DFVF_XYZ | D3DFVF_TEX2 );

    // Transformed vertex for light-map based lighting
    // with shared rhw.
    dwFVF = ( D3DFVF_XYZRHW | D3DFVF_TEX2 );

    // Heavyweight vertex for unlit, colored content with two
    //sets of texture coordinates.
    dwFVF = ( D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE |
              D3DFVF_SPECULAR | D3DFVF_TEX2 );


Texture Argument Flags

Each texture stage for a device can have two texture arguments that affect the color or alpha channel of the texture. You set and retrieve texture arguments by calling the IDirect3DDevice3::SetTextureStageState and IDirect3DDevice3::GetTextureStageState, specifying the D3DTSS_COLORARG1, D3DTSS_COLORARG2, D3DTSS_ALPHAARG1 or D3DTSS_ALPHAARG2 members of the D3DTEXTURESTAGESTATETYPE enumerated type.

The following flags, organized as arguments and modifiers, can be used with color and alpha arguments for a texture stage. You can combine an argument flag with a modifier, but you cannot combine two argument flags.

Argument flags
D3DTA_CURRENT
The texture argument is the result of the previous blending stage. In the first texture stage (stage zero), this argument defaults to D3DTA_DIFFUSE.
D3DTA_DIFFUSE
The texture argument is the diffuse color interpolated from vertex components during Gouraud shading. If the vertex does not contain a diffuse color, the default color is 0xFFFFFFFF.
D3DTA_SELECTMASK
Mask value for all arguments; not used when setting texture arguments.
D3DTA_TEXTURE
The texture argument is the texture color for this texture stage. This is valid only for the first color and alpha arguments in a stage (the D3DTSS_COLORARG1 and D3DTSS_ALPHAARG1 members of D3DTEXTURESTAGESTATETYPE).
D3DTA_TFACTOR
The texture argument is the texture factor set in a previous call to the IDirect3DDevice3::SetRenderState with the D3DRENDERSTATE_TEXTUREFACTOR render state value.
Modifier flags
D3DTA_ALPHAREPLICATE
Replicate the alpha information to all color channels before the operation completes.
D3DTA_COMPLEMENT
Invert the argument such that, if the result of the argument were referred to by the variable x, the value would be 1.0 - x.


Return Values

Errors are represented by negative values and cannot be combined. This table lists the values that can be returned by all Direct3D Immediate Mode methods. See the individual method descriptions for lists of the values each can return.

D3D_OK
No error occurred.
D3DERR_BADMAJORVERSION
The service you requested is unavailable in this major version of DirectX. (A "major version" denotes a primary release, such as DirectX 6.0.)
D3DERR_BADMINORVERSION
The service you requested is available in this major version of DirectX, but not in this minor version. Get the latest version of the component runtime from Microsoft. (A "minor version" denotes a secondary release, such as DirectX 6.1.)
D3DERR_COLORKEYATTACHED
The application attempted to create a texture with a surface that uses a color key for transparency.
D3DERR_CONFLICTINGTEXTUREFILTER
The current texture filters cannot be used together.
D3DERR_CONFLICTINGTEXTUREPALETTE
The current textures cannot be used simultaneously. This generally occurs when a multi-texture device requires that all palettized textures simultaneously enabled also share the same palette.
D3DERR_CONFLICTINGRENDERSTATE
The currently set render states cannot be used together.
D3DERR_DEVICEAGGREGATED
The IDirect3DDevice3::SetRenderTarget method was called on a device that was retrieved from the render target surface.
D3DERR_EXECUTE_CLIPPED_FAILED
The execute buffer could not be clipped during execution.
D3DERR_EXECUTE_CREATE_FAILED
The execute buffer could not be created. This typically occurs when no memory is available to allocate the execute buffer.
D3DERR_EXECUTE_DESTROY_FAILED
The memory for the execute buffer could not be deallocated.
D3DERR_EXECUTE_FAILED
The contents of the execute buffer are invalid and cannot be executed.
D3DERR_EXECUTE_LOCK_FAILED
The execute buffer could not be locked.
D3DERR_EXECUTE_LOCKED
The operation requested by the application could not be completed because the execute buffer is locked.
D3DERR_EXECUTE_NOT_LOCKED
The execute buffer could not be unlocked because it is not currently locked.
D3DERR_EXECUTE_UNLOCK_FAILED
The execute buffer could not be unlocked.
D3DERR_INITFAILED
A rendering device could not be created because the new device could not be initialized.
D3DERR_INBEGIN
The requested operation cannot be completed while scene rendering is taking place. Try again after the scene is completed and the IDirect3DDevice::EndScene method (or equivalent method) is called.
D3DERR_INVALID_DEVICE
The requested device type is not valid.
D3DERR_INVALIDCURRENTVIEWPORT
The currently selected viewport is not valid.
D3DERR_INVALIDMATRIX
The requested operation could not be completed because the combination of the currently set world, view, and projection matrices is invalid (the determinant of the combined matrix is zero).
D3DERR_INVALIDPALETTE
The palette associated with a surface is invalid.
D3DERR_INVALIDPRIMITIVETYPE
The primitive type specified by the application is invalid.
D3DERR_INVALIDRAMPTEXTURE
Ramp mode is being used and the texture handle in the current material does not match the current texture handle that is set as a render state.
D3DERR_INVALIDVERTEXFORMAT
The combination of flexible vertex format flags specified by the application is not valid.
D3DERR_INVALIDVERTEXTYPE
The vertex type specified by the application is invalid.
D3DERR_LIGHT_SET_FAILED
The attempt to set lighting parameters for a light object failed.
D3DERR_LIGHTHASVIEWPORT
The requested operation failed because the light object is associated with another viewport.
D3DERR_LIGHTNOTINTHISVIEWPORT
The requested operation failed because the light object has not been associated with this viewport.
D3DERR_MATERIAL_CREATE_FAILED
The material could not be created. This typically occurs when no memory is available to allocate for the material.
D3DERR_MATERIAL_DESTROY_FAILED
The memory for the material could not be deallocated.
D3DERR_MATERIAL_GETDATA_FAILED
The material parameters could not be retrieved.
D3DERR_MATERIAL_SETDATA_FAILED
The material parameters could not be set.
D3DERR_MATRIX_CREATE_FAILED
The matrix could not be created. This can occur when no memory is available to allocate for the matrix.
D3DERR_MATRIX_DESTROY_FAILED
The memory for the matrix could not be deallocated.
D3DERR_MATRIX_GETDATA_FAILED
The matrix data could not be retrieved. This can occur when the matrix was not created by the current device.
D3DERR_MATRIX_SETDATA_FAILED
The matrix data could not be set. This can occur when the matrix was not created by the current device.
D3DERR_NOCURRENTVIEWPORT
The viewport parameters could not be retrieved because none have been set.
D3DERR_NOTINBEGIN
The requested rendering operation could not be completed because scene rendering has not begun. Call IDirect3DDevice3::BeginScene to begin rendering then try again.
D3DERR_NOVIEWPORTS
The requested operation failed because the device currently has no viewports associated with it.
D3DERR_SCENE_BEGIN_FAILED
Scene rendering could not begin.
D3DERR_SCENE_END_FAILED
Scene rendering could not be completed.
D3DERR_SCENE_IN_SCENE
Scene rendering could not begin because a previous scene was not completed by a call to the IDirect3DDevice3::EndScene method.
D3DERR_SCENE_NOT_IN_SCENE
Scene rendering could not be completed because a scene was not started by a previous call to the IDirect3DDevice3::BeginScene method.
D3DERR_SETVIEWPORTDATA_FAILED
The viewport parameters could not be set.
D3DERR_STENCILBUFFER_NOTPRESENT
The requested stencil buffer operation could not be completed because there is no stencil buffer attached to the render target surface.
D3DERR_SURFACENOTINVIDMEM
The device could not be created because the render target surface is not located in video-memory. (Hardware-accelerated devices require video-memory render target surfaces.)
D3DERR_TEXTURE_BADSIZE
The dimensions of a current texture are invalid. This can occur when an application attempts to use a texture that has non-power-of-two dimensions with a device that requires them.
D3DERR_TEXTURE_CREATE_FAILED
The texture handle for the texture could not be retrieved from the driver.
D3DERR_TEXTURE_DESTROY_FAILED
The device was unable to deallocate the texture memory.
D3DERR_TEXTURE_GETSURF_FAILED
The DirectDraw surface used to create the texture could not be retrieved.
D3DERR_TEXTURE_LOAD_FAILED
The texture could not be loaded.
D3DERR_TEXTURE_LOCK_FAILED
The texture could not be locked.
D3DERR_TEXTURE_LOCKED
The requested operation could not be completed because the texture surface is currently locked.
D3DERR_TEXTURE_NO_SUPPORT
The device does not support texture mapping.
D3DERR_TEXTURE_NOT_LOCKED
The requested operation could not be completed because the texture surface is not locked.
D3DERR_TEXTURE_SWAP_FAILED
The texture handles could not be swapped.
D3DERR_TEXTURE_UNLOCK_FAILED
The texture surface could not be unlocked.
D3DERR_TOOMANYOPERATIONS
The application is requesting more texture filtering operations than the device supports.
D3DERR_TOOMANYPRIMITIVES
The device is unable to render the provided quantity of primitives in a single pass.
D3DERR_UNSUPPORTEDALPHAARG
The device does not support one of the specified texture blending arguments for the alpha channel.
D3DERR_UNSUPPORTEDALPHAOPERATION
The device does not support one of the specified texture blending operations for the alpha channel.
D3DERR_UNSUPPORTEDCOLORARG
The device does not support the one of the specified texture blending arguments for color values.
D3DERR_UNSUPPORTEDCOLOROPERATION
The device does not support the one of the specified texture blending operations for color values.
D3DERR_UNSUPPORTEDFACTORVALUE
The specified texture factor value is not supported by the device.
D3DERR_UNSUPPORTEDTEXTUREFILTER
The specified texture filter is not supported by the device.
D3DERR_VBUF_CREATE_FAILED
The vertex buffer could not be created. This can happen when there is insufficient memory to allocate a vertex buffer.
D3DERR_VERTEXBUFFERLOCKED
The requested operation could not be completed because the vertex buffer is locked.
D3DERR_VERTEXBUFFEROPTIMIZED
The requested operation could not be completed because the vertex buffer is optimized. (The contents of optimized vertex buffers are driver specific, and considered private.)
D3DERR_VIEWPORTDATANOTSET
The requested operation could not be completed because viewport parameters have not yet been set. Set the viewport parameters by calling IDirect3DViewport3::SetViewport method and try again.
D3DERR_VIEWPORTHASNODEVICE
The requested operation could not be completed because the viewport has not yet been associated with a device. Associate the viewport with a rendering device by calling IDirect3DDevice3::AddViewport and try again.
D3DERR_WRONGTEXTUREFORMAT
The pixel format of the texture surface is not valid.
D3DERR_ZBUFF_NEEDS_SYSTEMMEMORY
The requested operation could not be completed because the specified device requires system-memory depth-buffer surfaces. (Software rendering devices require system-memory depth buffers.)
D3DERR_ZBUFF_NEEDS_VIDEOMEMORY
The requested operation could not be completed because the specified device requires video-memory depth-buffer surfaces. (Hardware-accelerated devices require video-memory depth buffers.)
D3DERR_ZBUFFER_NOTPRESENT
The requested operation could not be completed because the render target surface does not have an attached depth buffer.


Direct3D Immediate Mode Samples

This section provides summaries of the applications in the DirectX® SDK that are primarily intended to demonstrate the Direct3D® component in Immediate Mode. The following sample programs demonstrate the use and capabilities of Direct3D:

  • Bend Sample
  • Billboard Sample
  • Boids Sample
  • BumpMap Sample
  • Compress Sample
  • D3DFrame Library
  • Filter Sample
  • Fireworks Sample
  • Flare Sample
  • Fog Sample
  • LightMap Sample
  • Lights Sample
  • MipMap Sample
  • MTexture Sample
  • PPlane Sample
  • ShadowVol Sample
  • ShadowVol2 Sample
  • Spheremap Sample
  • TunnelDP Sample
  • TunnelEB Sample
  • VideoTex Sample
  • VBuffer Sample
  • WBuffer Sample
  • XFile Sample

Note Most of the sample programs have a common interface (found in the D3DFrame Library) that has no menu bar. In addition to normal Windows® functions (minimize, maximize, restore, resize, and close), the interface supports the following commands:

Key / Input | Command
ESC | Quit
F1 | Help/About Box (lists these keystrokes)
F2 | Device options
ALT+ENTER | Toggle between full-screen and windowed mode
Right Mouse Button | Display options popup menu.

The device options dialog box allows the user to change the driver, Direct3D device, or display mode (full-screen only) at run time. Not all devices can support rendering in a window at all display depths. Note that 3-D hardware has finite video memory that may be exceeded for certain display modes and window sizes. In either case, the samples will display a message and default to a software rasterizer.

Although DirectX samples include Microsoft® Visual C++® project workspace files, you might need to verify other settings in your development environment to ensure that the samples compile properly. For more information, see Compiling DirectX Samples and Other DirectX Applications.


Bend Sample

Description

The Bend sample demonstrates a technique called surface skinning. It displays 3-D object which rotates about the y-axis and appears to bend.

Path

Source: (SDK root)\Samples\Multimedia\D3dim\Src\Bend

Executable: (SDK root)\Samples\Multimedia\D3dim\Bin

User's Guide

Press F1 to see available commands.

Programming Notes

The sample achieves the surface skinning effect by using two static copies of the object, one of which is oscillating along an axis. Each frame, the vertices of the two objects are merged and blended into a third object. The sample program displays the object derived from the third set of vertices.

This sample was built using the Direct3D sample framework.


Billboard Sample

Description

The Billboard sample illustrates the billboarding technique. Billboarding is a way of making 2-D sprites appear to be 3-D. It can also be used for smoke, clouds, vapor trails, energy blasts and more. For more information, see Common Techniques and Special Effects.

Path

Source: (SDK root)\Samples\Multimedia\D3dim\Src\Billboard

Executable: (SDK root)\Samples\Multimedia\D3dim\Bin

User's Guide

Press F1 to see available commands.

Programming Notes

The sample displays a grassy field with trees in it. The trees look like 3-D objects. However, they are actually 2-D texture bitmaps that are blended onto invisible rectangular polygons.

As the sample program executes, the viewpoint changes. Each time it does, all of the billboard polygons that the trees are painted onto are rotated so they face the viewer. The program then blends the images of the trees onto the billboard polygons. The trees appear to be 3-D because they can be viewed from all angles. However, close inspection reveals that the trees have exactly the same appearance from all angles. For many applications, users will not notice this minor drawback.

The shadows are also 2-D textures.

This sample was built using the Direct3D sample framework.


Boids Sample

Description

Boids illustrates how to write a Direct3D program. Using a flocking algorithm, the program moves a group of 3-D objects over a simple landscape.

Path

Source: (SDK root)\Samples\Multimedia\D3dim\Src\Boids

Executable: (SDK root)\Samples\Multimedia\D3dim\Bin

User's Guide

Press F1 to see available commands.

Programming Notes

The Boids program illustrates the fundamentals of creating a 3-D environment and animating a group of objects in it. From a programming perspective, the most interesting aspect is the way flocking is handled.


BumpMap Sample

Description

The BumpMap program demonstrates the bump mapping capabilities of Direct3D. Bump mapping is a texture blending technique used to render the appearance of rough surfaces.

Path

Source: (SDK root)\Samples\Multimedia\D3dim\Src\Bumpmap

Executable: (SDK root)\Samples\Multimedia\D3dim\Bin

User's Guide

Press F1 to see available commands.

Your graphics hardware might not support bump mapping, in which case Direct3D displays a message to that effect when you attempt to run this program. The solution is to enable the reference rasterizer. You can do so by running (SDK root)\Samples\Multimedia\D3dim\Bin\Enablerefrast.reg.

Programming Notes

Bump mapping is an advanced multitexture blending technique that can be used to render the appearance of rough surfaces. The bump map itself is a texture that stores the perturbation data.

In this sample program, the map of the world is a texture. The program blends both the map texture and the bump map texture onto the sphere to give the appearance of a high-resolution topographical map.

For more details on this technique, see Bump Mapping.

This sample was built using the Direct3D sample framework.


Compress Sample

Description

The Compress sample demonstrates how to load the DDS file format into a compressed texture surface. DDS textures can be created using the DxTex program included with the DirectX SDK.

Path

Source: (SDK root)\Samples\Multimedia\D3dim\Src\Compress

Executable: (SDK root)\Samples\Multimedia\D3dim\Bin

User's Guide

Press F1 to see available commands.

Programming Notes

The file format is called DDS because it encapsulates the information in a DirectDrawSurface. The data can be read directly into a surface of a matching format.

The ReadDDSTexture function demonstrations how a DDS surface is read from a file.

A DDS file has the following format:

DWORD dwMagic | (0x20534444, or "DDS ")
DDSURFACEDESC2 ddsd | Information about the surface format
BYTE bData1[] | Data for the main surface
[BYTE bData2[] | Data for attached surfaces, if any, follow

This format is easy to read and write, and supports features such as alpha and multiple mip levels, as well as DXTn compression. If it uses DXTn compression, it may be one of 5 compressed types. See Compressed Texture Surfaces.

After the texture is read in, a pixel format must be chosen that is supported by the renderer. In the sample, the supported pixel formats are enumerated and stored in a linked list. After the pixel formats are collected, the list is searched for a best match, using the FindBestPixelFormatMatch function.

Some Direct3D devices such as the reference rasterizer and some hardware devices can render compressed textures directly. But for renderers that don't directly support this, the compressed surface must be blitted to a non-compressed surface. The function BltToUncompressedSurface demonstrates how this is done.


D3DFrame Library

Description

The D3D framework is a set of C++ classes that were used to create the Direct3D Immediate Mode sample programs. It is not a part of the Direct3D API. The framework was created and used to provide consistency and clarity of presentation for the Direct3D samples. The framework classes may or may not be appropriate for use in your applications.

Path

Source: (SDK root)\Samples\Multimedia\D3dim\Src\D3DFrame

Executable: None.

User's Guide

D3DFrame compiles as a static linker library, which is used to build the remainder of the Direct3D Immediate Mode samples.

Programming Notes

The framework consists of classes that enumerate the DirectDraw drivers, Direct3D devices, and display modes available to each device. The sample programs use them to initialize and run Direct3D. The classes also help provide a consistent user interface for the set of sample programs. In addition, the framework includes a set of classes for loading and managing textures.

The Direct3D framework also contains numerous macros and functions for debugging, for manipulating Direct3D objects, and for doing math operations common in Direct3D programming.


Filter Sample

Description

The Filter sample program demonstrates the texture filtering techniques that Direct3D supports. Direct3D texture filtering techniques enable applications to achieve a greater realism in the appearance of rendered primitives. For more information, see Texture Filtering.

Path

Source: (SDK root)\Samples\Multimedia\D3dim\Src\Filter

Executable: None.

User's Guide

When the program begins, it displays two rectangular primitives with textures on them.

In addition to the usual commands listed in the About box when you press F1, this program has a main menu.

The File menu contains choices for pausing and resuming the program, changing the Direct3D device, and exiting the program. You can also pause and resume the application by pressing the ENTER key on your keyboard.

The Left Pane menu controls the texture filtering methods that the program uses for magnification and minification of the 3-D primitive on the left side of the screen. It also has options for edge antialiasing and anisotropic texture filtering. You may have to enable to software reference rasterizer to view the effects of these options. To enable the reference rasterizer, run (SDK root)\Samples\Multimedia\D3dim\Bin\Enablerefrast.reg.

The Right Pane menu enables you to set the filtering methods that the program uses to perform magnification and minification when it renders the primitive on the right side of the screen.

Programming Notes

This program demonstrates nearest point sampling, linear filtering, and anisotropic texture filtering. It illustrates how to enable and disable anisotropy. In addition, this sample shows how your program can set Direct3D to perform edge antialiasing.


Fireworks Sample

Description

Fireworks implements a system of particles simulating a fireworks explosion. Particles are popular in games to show effects like smoke, sparks, and explosions.

Path

Source: (SDK root)\Samples\Multimedia\D3dim\Src\Fireworks

Executable: (SDK root)\Samples\Multimedia\D3dim\Bin

User's Guide

Press F1 to see available commands.

Programming Notes

The fireworks explosion is simulated by using a system of particles, where each particle is rendered with a partially transparent texture map of a sphere. The position and color of each particle are governed by parameterized equations and are updated in each frame.


Flare Sample

Description

The Flare sample shows how to create a lens flare effect using alpha blending.

Path

Source: (SDK root)\Samples\Multimedia\D3dim\Src\Flare

Executable: (SDK root)\Samples\Multimedia\D3dim\Bin

User's Guide

Press F1 to see available commands.

Programming Notes

In this sample, lens flare is simulated with mathematical functions which govern the position of each flare. The flares are rendered using additive alpha blending, and animated to give a sparkle effect.


Fog Sample

Description

The Fog sample does a fly-by over some terrain with fog enabled.

Path

Source: (SDK root)\Samples\Multimedia\D3dim\Src\Fog

Executable: (SDK root)\Samples\Multimedia\D3dim\Bin

User's Guide

Press F1 to see available commands. The effects are most striking in full-screen mode.

Programming Notes

Games that use terrain typically turn on fog so they can prevent the rendering of objects in the far distance. It looks like a cool effect, but is actually used to get high performance.


LightMap Sample

Description

This sample shows how to use multitexturing and multipass techniques to do some complex lighting effects. There is a light swinging in a room, which dynamically lights up the walls and ceiling as the light moves.

Path

Source: (SDK root)\Samples\Multimedia\D3dim\Src\LightMap

Executable: (SDK root)\Samples\Multimedia\D3dim\Bin

User's Guide

On the Options menu, choose between multipass and multiple texture blending. The latter will not be available if your hardware does not support it.

Press F1 to see other available commands.

Programming Notes

There is no "true" lighting in this sample–everything is done with light maps. Light maps are extremely popular in games theses days, because they are much faster than real lighting. Also, real lighting is calculated only at the vertices, so highly tesselated meshes are required.


Lights Sample

Description

The Lights sample shows how to turn on and move the various types of Direct3D lights. The lights fly around, illuminating the scene, and switch every few seconds to a new light type.

Path

Source: (SDK root)\Samples\Multimedia\D3dim\Src\Lights

Executable: (SDK root)\Samples\Multimedia\D3dim\Bin

User's Guide

Press F1 to see available commands.

Programming Notes

This sample shows how to set up the D3DLIGHT structure for each of the several types of lights available. It also shows how to dynamically orient the lights on each frame.


MipMap Sample

Description

This sample shows two brick walls moving back and forth along the z-axis. One uses mipmapping and the other does not, giving a side-by-side comparison of the benefits of mipmapping.

Path

Source: (SDK root)\Samples\Multimedia\D3dim\Src\MipMap

Executable: (SDK root)\Samples\Multimedia\D3dim\Bin

User's Guide

Press F1 to see available commands.

Programming Notes

This sample does not use the texture code of D3DFrame, but actually shows the full implementation needed to load and build mipmapped textures.


MTexture Sample

Description

The MTexture program shows how to use multitexturing. The scene consists of a room with walls that have a base texture and a spotlight texture, each using a different set of texture coordinates.

Path

Source: (SDK root)\Samples\Multimedia\D3dim\Src\MTexture

Executable: (SDK root)\Samples\Multimedia\D3dim\Bin

User's Guide

Press F1 to see available commands.

Programming Notes

This sample shows how to program the multitexture stages using the new IDirect3DDevice3::SetTextureStageState method. Dozens of different effects are attainable with this method. The sample just shows one, monochrome light mapping, which is very popular in current game titles.


PPlane Sample

Description

The PPlane program is a simple example of how to create Direct3D Immediate Mode programs.

Path

Source: (SDK root)\Samples\Multimedia\D3dim\Src\Pplane

Executable: (SDK root)\Samples\Multimedia\D3dim\Bin

User's Guide

Press F1 to see available commands.

Programming Notes

In addition to demonstrating Direct3D Immediate Mode programming techniques, this application contains a flocking algorithm used to animate the paper planes.


ShadowVol Sample

Description

The ShadowVol sample demonstrates how to create and use stencil buffers to implement shadow volumes. With shadow volumes, an arbitrarily shaped object can cast a shadow onto another arbitrarily shaped object.

Path

Source: (SDK root)\Samples\Multimedia\D3dim\Src\ShadowVol

Executable: (SDK root)\Samples\Multimedia\D3dim\Bin

User's Guide

This sample will run only on devices that support stencil buffers.

Press F1 to see available commands.

Programming Notes

Shadow volumes are a fairly advanced technique. To start, take an object that you'd like to have cast a shadow. From that object, build a set of polygonal faces that encompass the volume of its shadow. Next, use the stencil buffer to render the front facing planes of the shadow volume. Then, set up the stencil buffer to render the back-facing planes, this time subtracting values from the stencil buffer. Afterwards, the stencil buffer contains a mask of the cast shadow. Just draw a large gray or black rectangle using the stencil buffer as a mask, and the frame buffer will get updated with the shadow.


ShadowVol2 Sample

Description

The ShadowVol2 sample demonstrates how to create and use stencil buffers to implement shadow volumes, which are used to cast shadows on arbitrarily complex objects. It is an extension of the ShadowVol Sample.

Path

Source: (SDK root)\Samples\Multimedia\D3dim\Src\ShadowVol2

Executable: (SDK root)\Samples\Multimedia\D3dim\Bin

User's Guide

This sample will run only on devices that support stencil buffers.

Press F1 to see available commands.

The following options are available on the Shadow Modes menu:

  • Draw Shadows: Check this option to enable shadow rendering.
  • Show Shadow Volumes: Instead of shadows, draw the shadow volumes used to compute them.
  • Draw Shadow Volume Caps: If this is turned off, "extra" shadows may be visible where the far caps of the directional-light cylindrical shadow volumes happen to be visible.
  • Show Quarter Viewpoint: Show scene from a different angle.
  • 1 Bit Stencil Mode: Use different algorithm that uses only 1 bit of stencil buffer, where overlapping shadows are not allowed. If the device only supports 1-bit stencil, you will not be allowed to switch out of this mode.
  • Z Order Shadow Vols: In 1-Bit Mode, shadow volumes must be rendered front-to-back, so rendering may be incorrect unless this option is checked.

Programming Notes

Shadow volumes are a technique for casting shadows onto arbitrary non-planar surfaces. The effect is achieved by constructing a shadow volume with respect to the light source and the shadow caster. In this example, the light source is a directional light whose direction circles about points on the plane, and the shadow volume is computed by projecting the vertices of the shadow caster onto a plane perpendicular to the light, finding the 2-D convex hull of these points in the plane, and extruding the 2-D hull in the light direction to form the 3-D shadow volume. The shadow volume must extend far enough so that it covers any geometry that will be in shadow. This particular shadow volume computation requires that the shadow caster be a convex object.

The rendering proceeds as follows. First the geometry is rendered as normal, then the shadow volume is rendered without writing to the z or color buffer (alpha blending is used here to avoid writes to the color buffer). Every place the shadow volume appears is marked in the stencil buffer. Next, the cull order is reversed and the back faces of the shadow volume are rendered, this time unmarking all the pixels that are covered in the stencil buffer. These have passed the z-test, and thus are visible behind the back of the shadow volume, so they are not in shadow. The pixels still marked are those that lie inside the front and back bounds of the shadow volume and are thus in shadow. These pixels are blended with a large black rectangle that covers the viewport, generating the shadow.


Spheremap Sample

Description

This samples loads a 3-D object and renders it using a sphere map.

Path

Source: (SDK root)\Samples\Multimedia\D3dim\Src\Spheremap

Executable: (SDK root)\Samples\Multimedia\D3dim\Bin

User's Guide

Press F1 to see available commands.

Programming Notes

The sphere map itself is a special, preconstructed texture map containing a 180-degree view of an environment. Before a frame is rendered, the object's normals are used to compute the texture coordinates for each vertex of the object. When rendered, the object looks as if it reflects the environment.


TunnelDP Sample

Description

This sample uses DrawPrimitive to render objects.

Path

Source: (SDK root)\Samples\Multimedia\D3dim\Src\TunnelDP

Executable: (SDK root)\Samples\Multimedia\D3dim\Bin

User's Guide

Press F1 to see available commands. In addition, you can change some effects by using the main menu.

Programming Notes

The point of this sample is to compare its source code to that of TunnelEB, the identical version using execute buffers.


TunnelEB Sample

Description

This sample uses execute buffers to render objects.

Path

Source: (SDK root)\Samples\Multimedia\D3dim\Src\TunnelEB

Executable: (SDK root)\Samples\Multimedia\D3dim\Bin

User's Guide

Press F1 to see available commands. In addition, you can change some effects by using the main menu.

Programming Notes

The point of this sample is to compare its source code to that of TunnelDP, the identical version using DrawPrimitive.


VBuffer Sample

Description

This sample shows how to use the vertex buffers that are new to DirectX 6.0.

Path

Source: (SDK root)\Samples\Multimedia\D3dim\Src\VBuffer

Executable: (SDK root)\Samples\Multimedia\D3dim\Bin

User's Guide

Press F1 to see available commands.

Programming Notes

Before vertex buffers, geometry rendering was accomplished by using an array of vertices passed to DrawPrimitive calls. Vertex buffers are more useful, but need to be specifically created, locked, filled, and unlocked before being rendered with the new DrawPrimitiveVB calls.


VideoTex Sample

The VideoTex sample shows how to use an .avi file as a texture map.

Path

Source: (SDK root)\Samples\Multimedia\D3dim\Src\VideoTex

Executable: (SDK root)\Samples\Multimedia\D3dim\Bin

User's Guide

Press F1 to see a list of the usual commands.

Programming Notes

The program draws a cube with an .avi texture mapped to each of its faces. The key is to have the texture's surface use the DDSCAPS2_HINTDYNAMIC flag.


WBuffer Sample

Description

The WBuffer sample shows how to use w-buffering.

Path

Source: (SDK root)\Samples\Multimedia\D3dim\Src\WBuffer

Executable: (SDK root)\Samples\Multimedia\D3dim\Bin

User's Guide

Press F1 to see a list of the usual commands. In addition, you can change the buffering mechanism by pressing W (w-buffering, if supported), Z (z-buffering), or N (no buffering). Note the artifacts that appear when using z-buffering.

Programming Notes

W-buffering is a depth-buffering alternative to z-buffering, and should be used in cases where z-buffering produces artifacts. W-buffering does a much better job of quantizing the depth buffer.


XFile Sample

Description

This sample shows how to load and render .x files.

Path

Source: (SDK root)\Samples\Multimedia\D3dim\Src\Xfile

Executable: (SDK root)\Samples\Multimedia\D3dim\Bin

User's Guide

When you run the program, an Open File dialog box appears. You can find some .x files in the media folder of the D3DIM samples directory. If there is a .bmp file of the same name in the directory, the bmp is automatically used as a texture for the object.

Press F1 to see available commands. In addition, you can load a different file from the File menu.

Programming Notes

If a texture appears upside-down on an object you have loaded, it is because of the way the object loads the texture. An earlier version of Direct3D loaded bitmaps upside-down, so the creators of some .x files compensated by reversing the coordinates.


DirectInput

This section provides information about the DirectInput® component of DirectX® application programming interface (API). The information is divided into the following topics:

  • About DirectInput
  • Why Use DirectInput?
  • DirectInput Architecture
  • DirectInput Essentials
  • DirectInput Tutorials
  • DirectInput Reference
  • DirectInput Samples


About DirectInput

Microsoft® DirectInput® provides support for input devices including the mouse, keyboard, joystick, and other game controllers, as well as for force-feedback (input/output) devices. Like other DirectX® components, DirectInput is based on the Component Object Model (COM).


Why Use DirectInput?

Aside from providing new services for devices not supported by the Win32® API, such as force-feedback game devices, DirectInput gives faster access to input data by communicating directly with the hardware drivers rather than relying on Windows® messages.

The extended services and improved performance of DirectInput make it a valuable tool for games, simulations, and other real-time interactive applications running under Windows.


DirectInput Architecture

This section covers the basic structure of DirectInput and how it works with both the Windows operating system and input hardware. It also introduces the way DirectInput handles device access, input data, and force-feedback effects.

  • Architectural Overview of DirectInput
  • The DirectInput Object
  • The DirectInputDevice Object
  • DirectInput Device Object Instances
  • The DirectInputEffect Object
  • Integration with Windows
  • Human Interface Device


Architectural Overview of DirectInput

The basic architecture of DirectInput consists of the DirectInput object, which supports a COM interface, and an object for each input device that provides data. Each device in turn has "object instances," which are individual controls or switches such as keys, buttons, or axes. Individual force-feedback effects are also represented by objects.

Note The word "object" is used to describe an entity created by the DirectInput system to support the methods of a COM interface, even when these methods are not being called through an object-oriented programming language such as C++. Somewhat confusingly, "object" may also mean one of the individual controls on an input device.

In the interests of speed and responsiveness, DirectInput works directly with device drivers, bypassing the Windows message system.

DirectInput enables an application to gain access to input devices even when the application is in the background.


The DirectInput Object

The DirectInput object in an application represents the DirectInput subsystem. It is used to enumerate and manage input devices.

You create the DirectInput object by calling the DirectInputCreate function, which returns a pointer to an IDirectInput COM interface. There are different versions of this interface for the ANSI and Unicode character sets.

Having created the DirectInput object, you can use the methods of the interface to enumerate individual devices available to the system and to create a DirectInputDevice object for each device you wish to use in your application.


The DirectInputDevice Object

Each DirectInputDevice object represents one input device such as a mouse, keyboard, or joystick. (In this documentation, the term "joystick" includes other game devices that behave similarly, such as steering wheels and game pads.)

You create a DirectInputDevice instance by calling the IDirectInput::CreateDevice method, which returns a pointer to the IDirectInputDevice interface. The IDirectInputDevice methods are used to get information about the device, set its properties, and get data from it.

Note A physical device that is really a combination of different types of input devices, such as a keyboard with a trackball, may be represented by two or more DirectInputDevice objects. A force-feedback device is represented by a single joystick object that handles both input and output.


DirectInput Device Object Instances

An object instance, sometimes called simply an object, is one of the various switches and other controls available on an input device. For example, object instances on a joystick might include the x-axis and y-axis of the stick, several buttons, and a throttle slider. Mouse objects might include two or three buttons, the x-axis and y-axis, and a wheel. For a keyboard, each key is an object.

The application ascertains the number and type of objects available on a device through the IDirectInputDevice::EnumObjects method. Individual device objects are not encapsulated as code objects but are described in DIDEVICEOBJECTINSTANCE structures.


The DirectInputEffect Object

A DirectInputEffect object represents a force-feedback effect that you have defined. It is used to manipulate the effect on the input/output device.

You create a DirectInputEffect object by calling the IDirectInputDevice2::CreateEffect method, which returns a pointer to an IDirectInputEffect COM interface.


Integration with Windows

Because DirectInput works directly with the device drivers, it either suppresses or ignores mouse and keyboard messages. When using the mouse in exclusive mode, DirectInput suppresses mouse messages; as a result, Windows is unable to show the standard cursor.

DirectInput also ignores mouse and keyboard settings made by the user in Control Panel.

For the keyboard, character repeat settings are not used by DirectInput. When using buffered data, DirectInput interprets each press and release as a single event, with no repetition. When using immediate data, DirectInput is concerned only with the present physical state of the keys, not with keyboard events as interpreted by Windows.

For the mouse, DirectInput ignores Control Panel settings such as acceleration and swapped buttons. Again, DirectInput works directly with the mouse driver, bypassing the subsystem of Windows that interprets mouse data for windowed applications.

Note Settings in the driver itself will be recognized by DirectInput. For example, if the user has a three-button mouse and uses the driver utility software to make the middle button a double-click shortcut, DirectInput will report a click of the middle button as two clicks of the primary button.

For a joystick or other game device, DirectInput does use the calibrations set by the user in Control Panel.


Human Interface Device

Human Interface Device (HID) is a class under the Universal Serial Bus (USB) standard. DirectInput provides full support for devices that conform with HID.

Getting data from HID devices is substantially the same as with traditional devices. In addition, HID devices may accept output: for example, you can turn the keyboard LEDs on and off.

By querying a HID device, DirectInput is able to determine its usage page and usage. These are predefined codes that give information about the type and subtype of the device.

HID controls are grouped in collections. Collections may be nested.


DirectInput Essentials

This section introduces the concepts and components of DirectInput, and provides enough information for you to get started in implementing the DirectInput system in your application.

The following topics are discussed:

  • DirectInput Device Enumeration
  • DirectInput Devices
  • DirectInput Device Data
  • Force Feedback
  • Designing for Previous Versions of DirectInput


DirectInput Device Enumeration

DirectInput is able to query the system for all available input devices, determine whether they are connected, and return information about them. This process is called enumeration.

If your application is using only the standard keyboard or mouse, or both, you don't need to enumerate the available input devices. As explained under Creating the DirectInput Device, you can simply use predefined global variables when calling the IDirectInput::CreateDevice method.

For all other input devices, and for systems with multiple keyboards or mice, you need to call IDirectInput::EnumDevices in order to obtain at least the instance GUIDs (globally unique identifiers) so that device objects can be created.

Here's a sample implementation of the IDirectInput::EnumDevices method:

GUID              KeyboardGUID = GUID_SysKeyboard;
// LPDIRECTINPUT  lpdi;   //This has been initialized with
                          //DirectInputCreate and points to
                          //the DirectInput object

lpdi->EnumDevices(DIDEVTYPE_KEYBOARD,
                  DIEnumDevicesProc,
                  &KeyboardGUID,
                  DIEDFL_ATTACHEDONLY);

The first parameter determines what types of devices are to be enumerated. It is NULL if you want to enumerate all devices regardless of type; otherwise it is one of the DIDEVTYPE_* values described in the reference for DIDEVICEINSTANCE.

The second parameter is a pointer to a callback function that will be called once for each device enumerated. This function can be called by any name; the documentation uses the placeholder name DIEnumDevicesProc.

The third parameter to the EnumDevices method is any 32-bit value that you want to pass into the callback function. In this example, it's a pointer to a variable of type GUID, passed in so that the callback can assign a keyboard instance GUID.

The fourth parameter is a flag to request enumeration of either all devices or only those that are attached (DIEDFL_ALLDEVICES or DIEDFL_ATTACHEDONLY).

If your application is using more than one input device, the callback function is a good place to initialize each device as it is enumerated. (For an example, see Tutorial 3: Using the Joystick.) The callback function is where you obtain the instance GUID of the device. You can also perform other processing here, such as looking for particular subtypes of devices.

Here is a sample callback function that checks for the presence of an enhanced keyboard and stops the enumeration as soon as it finds one. It assigns the instance GUID of the last keyboard found to the KeyboardGUID variable (passed in as pvRef by the previous example of a EnumDevices call), which can then be used in a call to IDirectInput::CreateDevice.

BOOL          hasEnhanced;

BOOL CALLBACK DIEnumKbdProc(LPCDIDEVICEINSTANCE lpddi,
                            LPVOID pvRef)
{
  *(GUID*) pvRef = lpddi->guidInstance;
  if (GET_DIDEVICE_SUBTYPE(lpddi->dwDevType) ==
                       DIDEVTYPEKEYBOARD_PCENH)
  {
    hasEnhanced = TRUE;
    return DIENUM_STOP;
  }
  return DIENUM_CONTINUE;
} // end of callback

The first parameter points to a structure containing information about the device. This structure is created for you by DirectInput.

The second parameter points to data passed in from EnumDevices. In this case it is a pointer to the variable KeyboardGUID. This variable was assigned a default value earlier, but it will be given a new value each time a device is enumerated. It is not actually important what instance GUID you use for a single keyboard, but the code does illustrate a technique for retrieving an instance GUID from the callback.

The return value in this case indicates that enumeration is to stop if the sought-for device has been found, or otherwise that it is to continue. Enumeration will automatically stop as soon as all devices have been enumerated.


DirectInput Devices

This section contains information about the code objects that represent devices such as mice, keyboards, and joysticks. The following topics are covered:

  • Device Setup
  • Creating a DirectInput Device
  • Device Capabilities
  • Cooperative Levels
  • Device Object Enumeration
  • Device Data Formats
  • Device Properties
  • Acquiring Devices

For information on how to retrieve and interpret data from devices, see DirectInput Device Data.


Device Setup

Your application must obtain a COM interface for each device from which it expects input. It must also prepare each device for use, which requires, at the very least, setting the data format and acquiring the device. You may also wish to carry out other preparatory tasks such as getting information about the devices and changing their properties.

The following tasks are part of the setup process. Certain steps are always required; others may only be necessary if you need further information about devices or need to change default values.

  • Create the DirectInput device (required). See Creating a DirectInput Device.
  • Get the device capabilities (optional).
  • Enumerate the keys, buttons, and axes on the device (optional). See Device Object Enumeration.
  • Set the cooperative level (recommended).
  • Set the data format (required).
  • Set the device properties (optional).
  • When ready to read data, acquire the device (required). See Acquiring Devices.


Creating a DirectInput Device

The IDirectInput::CreateDevice method is used to obtain a pointer to the IDirectInputDevice interface. Methods of this interface are then used to manipulate the device and obtain data.

The following example, where lpdi is a pointer to the IDirectInput interface, creates a keyboard device:

LPDIRECTINPUTDEVICE  lpdiKeyboard;
lpdi->CreateDevice(GUID_SysKeyboard, &lpdiKeyboard, NULL);

The first parameter in IDirectInput::CreateDevice is an instance GUID that identifies the instance of the device for which the interface is to be created. DirectInput has two predefined GUIDs, GUID_SysMouse and GUID_SysKeyboard, which represent the system mouse and keyboard, and you can pass these identifiers into the CreateDevice method. The global variable GUID_Joystick should not be used as a parameter for CreateDevice, because it is a product GUID, not an instance GUID.

Note If the workstation has more than one mouse, input from all of them is combined to form the system device. The same is true for multiple keyboards.

For devices other than the system mouse or keyboard, use the instance GUID for the device returned by IDirectInput::EnumDevices. The instance GUID for a device will always be the same. You can allow the user to select a device from a list of those enumerated, then save the GUID to a configuration file and use it again in future sessions.

If you want to use the IDirectInputDevice2 interface methods for force-feedback devices, you must obtain a pointer to that interface instead of IDirectInputDevice. The following function is a wrapper for the CreateDevice method that attempts to obtain the IDirectInputDevice2 interface. Note the use of macros to call the Release and CreateDevice methods according to either the C or C++ syntax.

HRESULT IDirectInput_CreateDevice2(LPDIRECTINPUT pdi,
                                   REFGUID rguid,
                                   LPDIRECTINPUTDEVICE2 *ppdev2,
                                   LPUNKNOWN punkOuter)
{
    LPDIRECTINPUTDEVICE *pdev;
    HRESULT hres;

    hres = IDirectInput_CreateDevice(pdi, rguid, &pdev, punkOuter);

    if (SUCCEEDED(hres)) {
#ifdef __cplusplus
    hres = pdev->QueryInterface(IID_IDirectInputDevice2,
                                    (LPVOID *)ppdev2);
#else
    hres = pdev->lpVtbl->QueryInterface(pdev,
                       &IID_IDirectInputDevice2,
                              (LPVOID *)ppdev2);
#endif
    IDirectInputDevice_Release(pdev);
    } else {
    *ppdev2 = 0;
    }
    return hres;
}


Device Capabilities

Before you begin asking for input from a device, you may need to find out something about its capabilities. Does the joystick have a point-of-view hat? Is the mouse currently attached to the user's machine? Such questions are answered with a call to the IDirectInputDevice::GetCapabilities method, which returns the data in a DIDEVCAPS structure. As with other such structures in DirectX, you must initialize the dwSize member before passing this structure to the method.

Note To optimize speed or memory usage, you can use the smaller DIDEVCAPS_DX3 structure instead.

Here's an example that checks whether the mouse is attached and whether it has a third axis (presumably a wheel):

//  LPDIRECTINPUTDEVICE  lpdiMouse;  // initialized previously

DIDEVCAPS  DIMouseCaps;
HRESULT    hr;
BOOLEAN    HasWheel;

DIMouseCaps.dwSize = sizeof(DIDEVCAPS);
hr = lpdiMouse->GetCapabilities(&DIMouseCaps);
HasWheel = ((DIMouseCaps.dwFlags & DIDC_ATTACHED)
        && (DIMouseCaps.dwAxes > 2));

Another way to check for a certain button or axis is to call IDirectInputDevice::GetObjectInfo for that object. If the call returns DIERR_OBJECTNOTFOUND, the object is not present. The following code determines whether there is a z-axis even if it is not the third axis:

DIDEVICEOBJECTINSTANCE  didoi;

didoi.dwSize = sizeof(DIDEVICEOBJECTINSTANCE);
hr = lpdiMouse->GetObjectInfo(&didoi,DIMOFS_Z, DIPH_BYOFFSET);
HasWheel = SUCCEEDED(hr);


Cooperative Levels

The cooperative level of a device determines how the input is shared with other applications and with the Windows system. You set it by using the IDirectInputDevice::SetCooperativeLevel method, as in this example:

lpdiDevice->SetCooperativeLevel(hwnd,
                                DISCL_NONEXCLUSIVE | DISCL_FOREGROUND)

The parameters are the handle to the top-level window associated with the device (generally the application window) and one or more flags. The valid flag combinations are shown in the following table:

Flags | Notes
DISCL_NONEXCLUSIVE | DISCL_BACKGROUND | The default setting
DISCL_NONEXCLUSIVE | DISCL_FOREGROUND |
DISCL_EXCLUSIVE | DISCL_FOREGROUND | Not valid for keyboard
DISCL_EXCLUSIVE | DISC_BACKGROUND | Not valid for keyboard or mouse

Note Although DirectInput provides a default setting, you should still explicitly set the cooperative level, because doing so is the only way to give DirectInput the window handle. Without this handle, DirectInput will not be able to react to situations that involve window messages, such as joystick recalibration.

The cooperative level has two components: whether the device is being used in the foreground or the background, and whether it is being used exclusively or nonexclusively . Both these components require some explanation.

Foreground and Background

A foreground cooperative level means that the input device is available only when the application is in the foreground or, in other words, has the input focus. If the application moves to the background, the device is automatically unacquired, or made unavailable.

A background cooperative level really means "foreground and background." A device with a background cooperative level can be acquired and used by an application at any time.

You will usually want to have foreground access only, since most applications are not interested in input that takes place when another program is in the foreground.

While developing an application, it is useful to have a conditional define that sets the background cooperative level during debugging. This will prevent your application from losing access to the device every time it moves to the background as you switch to a debugging window.

Exclusive and Nonexclusive

The fact that your application is using a device at the exclusive level does not mean that other applications cannot get data from the device. However, it does mean that no other application can also acquire the device exclusively.

Why does it matter? Take the example of a music player that accepts input from a hand-held remote-control device, even when the application is running in the background. Now suppose you run a similar application that plays movies, again in response to signals from the remote control. What happens when the user presses Play? Both programs start playing, which is probably not what the user wants. To prevent this from happening, each application should have the DISCL_EXCLUSIVE flag set, so that only one of them can be running at a time.

In order to use force-feedback effects, an application must have exclusive access to the device.

Windows itself requires exclusive access to the mouse and keyboard. The reason is that mouse and keyboard events such as a click on an inactive window or ALT+TAB could force an application to unacquire the device, with potentially harmful results such as a loss of data from the input buffer.

When an application has exclusive access to the mouse, Windows is not allowed any access at all. No mouse messages are generated. A further side effect is that the cursor disappears.

DirectInput does not allow any application to have exclusive access to the keyboard. If it did, Windows would not have access to the keyboard and the user would not even be able to use CTRL+ALT+DELETE to restart the system.


Device Object Enumeration

It may be necessary for your application to determine what buttons or axes are available on a given device. To do this you enumerate the device objects in much the same way you enumerate devices.

To some extent IDirectInputDevice::EnumObjects overlaps the functionality of IDirectInputDevice::GetCapabilities. Either method may be used to determine how many buttons or axes are available. However, EnumObjects is really intended for cataloguing all the available objects rather than checking for a particular one. The DirectInput Quick Test application provided with the DirectX SDK, for example, uses EnumObjects to populate the list on the Objects page for the selected device.

Like IDirectInput::EnumDevices, the EnumObjects method has a callback function that gives you the chance to do other processing on each object — for example, adding it to a list or creating a corresponding element on a user interface.

Here's a callback function that simply extracts the name of each object so that it can be added to a string list or array. This standard callback is documented under the placeholder name DIEnumDeviceObjectsProc, but you can give it any name you like. Remember, this function is called once for each object enumerated.

char  szName[MAX_PATH];

BOOL CALLBACK DIEnumDeviceObjectsProc(
                      LPCDIDEVICEOBJECTINSTANCE lpddoi,
                      LPVOID pvRef)
{
  lstrcpy(szName, lpddoi->tszName);
  // Now add szName to a list or array
  .
  .
  .
  return DIENUM_CONTINUE;
}

The first parameter points to a structure containing information about the object. This structure is created for you by DirectInput.

The second parameter is an application-defined pointer to data, equivalent to the second parameter to EnumObjects. In the example, this parameter is not used.

The return value in this case indicates that enumeration is to continue as long as there are still objects to be enumerated.

Now here's the call to the EnumObjects method, which puts the callback function to work.

lpdiMouse->EnumObjects(DIEnumDeviceObjectsProc,
                       NULL, DIDFT_ALL);

The first parameter is the address of the callback function.

The second parameter can be a pointer to any data you want to use or modify in the callback. The example does not use this parameter and so passes NULL.

The third parameter is a flag to indicate which type or types of objects are to be included in the enumeration. In the example, all objects are to be enumerated. To restrict the enumeration, you can use one or more of the other DIDFT_* flags listed in the reference for IDirectInput::EnumDevices.

Note Some of the DIDFT_* flags are combinations of others; for example, DIDFT_AXIS is equivalent to DIDFT_ABSAXIS | DIDFT_RELAXIS.


Device Data Formats

Setting the data format for a device is an essential step before you can acquire and begin using the device. The IDirectInputDevice::SetDataFormat method tells DirectInput what device objects will be used and how the data will be arranged.

The examples in the reference for the DIDATAFORMAT structure and DIOBJECTDATAFORMAT structure will give you an idea of how to set up custom data formats for nonstandard devices. Fortunately, this step is not necessary for the joystick, keyboard, and mouse. DirectInput provides four global variables, c_dfDIJoystick, c_dfDIJoystick2, c_dfDIKeyboard, and c_dfDIMouse, which can be passed into SetDataFormat to create a standard data format for these devices.

Here is an example, where lpdiMouse is an initialized pointer to the mouse device object:

lpdiMouse->SetDataFormat(&c_dfDIMouse);

Note You cannot change the dwFlags member in the predefined DIDATAFORMAT global variables (for example, in order to change the property of an axis), because they are const variables. To change properties, use the IDirectInputDevice::SetProperty method after setting the data format but before acquiring the device.


Device Properties

Properties of DirectInput devices include the size of the data buffer, the range and granularity of values returned from an axis, whether axis data is relative or absolute, and the dead zone and saturation values for a joystick axis, which affect the relationship between the physical position of the stick and the reported data. Specialized devices may have other properties as well.

With one exception — the gain property of a force-feedback device — properties may only be changed when the device is in an unacquired state.

Before calling the IDirectInputDevice::SetProperty or IDirectInputDevice::GetProperty methods you need to set up a property structure, which consists of a DIPROPHEADER structure and one or more elements for data. There are potentially a great variety of properties for input devices, and SetProperty must be able to work with all sorts of structures defining those properties. The purpose of the DIPROPHEADER structure is to define the size of the property structure and how the data is to be interpreted.

DirectInput includes the following predefined property structures:

  • DIPROPDWORD defines a structure containing a DIPROPHEADER and a DWORD data member, for properties that require a single value, such as a buffer size.
  • DIPROPRANGE is for range properties, which require two values (maximum and minimum). It consists of a DIPROPHEADER and two LONG data members.

For SetProperty, the data members of the property structure are the values you want to set. For GetProperty, the current value is returned in these members.

Before the call to GetProperty or SetProperty, the DIPROPHEADER structure must be initialized with the following:

  • The size of the property structure
  • The size of the DIPROPHEADER structure itself
  • An object identifier
  • A "how" code indicating the way the object identifier should be interpreted

When getting or setting properties for a whole device, the object identifier dwObj is zero and the "how" code dwHow is DIPH_DEVICE. If you want to get or set properties for a device object (for example, a particular axis), the combination of dwObj and dwHow values identifies the object. For details, see the reference for the DIPROPHEADER structure.

After setting up the property structure, you pass the address of its header into GetProperty or SetProperty, along with an identifier for the property you want to obtain or change.

The following values are used to identify the property passed to SetProperty and GetProperty. For more information see the reference for IDirectInputDevice::GetProperty.

  • DIPROP_BUFFERSIZE. See also Buffered and Immediate Data.
  • DIPROP_AXISMODE. See also Relative and Absolute Axis Coordinates.
  • DIPROP_CALIBRATIONMODE
  • DIPROP_GRANULARITY
  • DIPROP_FFGAIN
  • DIPROP_FFLOAD
  • DIPROP_AUTOCENTER
  • DIPROP_RANGE
  • DIPROP_DEADZONE
  • DIPROP_SATURATION

For more information about the last three properties, see also Interpreting Joystick Axis Data.

The following example sets the buffer size for a device so that it will hold 10 data items:

DIPROPDWORD  dipdw;
HRESULT      hres;
dipdw.diph.dwSize = sizeof(DIPROPDWORD);
dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
dipdw.diph.dwObj = 0;
dipdw.diph.dwHow = DIPH_DEVICE;
dipdw.dwData = 10;
hres = lpdiDevice->SetProperty(DIPROP_BUFFERSIZE, &dipdw.diph);


Acquiring Devices

Acquiring a DirectInput device means giving your application access to it. As long as a device is acquired, DirectInput is making its data available to your application. If the device is not acquired, you may manipulate its characteristics but not obtain any data.

Acquisition is not permanent; your application may acquire and unacquire a device many times.

In certain cases, depending on the cooperative level, a device may be unacquired automatically whenever your application moves to the background. The mouse is automatically unacquired when the user clicks on a menu, because at this point Windows takes over the device.

You need to unacquire a device before changing its properties. The only exception is that you may change the gain for a force-feedback device while it is in an acquired state.

Why is the acquisition mechanism needed? There are two main reasons.

First, DirectInput has to be able to tell the application when the flow of data from the device has been interrupted by the system. For instance, if the user has switched to another application with ALT+TAB, and used the input device in that application, your application needs to know that the input no longer belongs to it and that the state of the buffers may have changed. Or consider an application with the DISCL_FOREGROUND cooperative level. The user presses the SHIFT key, and while continuing to press it switches to another application. Then the user releases the key and switches back to the first application. As far as the first application is concerned, the SHIFT key is still down. The acquisition mechanism, by telling the application that input was lost, allows it to recover from these conditions.

Second, because your application can alter the properties of the device, without safeguards DirectInput would have to check the properties each time you wanted to get data with the IDirectInputDevice::GetDeviceState or IDirectInputDevice::GetDeviceData methods. Obviously this would be very inefficient. Even worse, potentially disastrous things could happen like a hardware interrupt accessing a data buffer just as you were changing the buffer size. So DirectInput requires your application to unacquire the device before changing properties. When you reacquire it, DirectInput looks at the properties and decides on the optimal way of transferring data from the device to the application. This is done only once, thereby making GetDeviceState and GetDeviceData very fast.

Since the most common cause of losing a device is that your application moves to the background, you may want to reacquire devices whenever your application is activated. Be careful, though, about relying on a WM_ACTIVATE handler at startup time. The first WM_ACTIVATE message will likely arrive when your window is being initialized, before DirectInput has been set up. To ensure that the device is acquired at startup, call IDirectInputDevice::Acquire as soon as the device has been initialized.

Even acquiring the device on activation of your program window might not cover all cases where a device is unacquired, especially for devices other than the standard mouse or keyboard. Because your application might unacquire a device unexpectedly, you need to have a mechanism for checking the acquisition state before attempting to get data from the device. The Scrawl sample application does this in the Scrawl_OnMouseInput function, where a DIERR_INPUTLOST error triggers a message to reacquire the mouse. (See also Tutorial 2: Using the Mouse.)

There's no harm in attempting to reacquire a device that is already acquired. Redundant calls to IDirectInputDevice::Acquire are ignored, and the device can always be unacquired with a single call to IDirectInputDevice::Unacquire.

Remember, Windows doesn't have access to the mouse when your application is using it in exclusive mode. If you want to let Windows have the mouse, you must let it go. There's an example in Scrawl, which responds to a click of the right button by unacquiring the mouse, putting the Windows cursor in the same spot as its own, popping up a context menu, and letting Windows handle the input until a menu choice is made.


DirectInput Device Data

This section covers the basic concepts of getting data from DirectInput devices.

  • Buffered and Immediate Data
  • Time Stamps and Sequence Numbers
  • Polling and Events
  • Relative and Absolute Axis Coordinates

Specific details about mouse, keyboard, and joystick input data, and about output data, are given in the following sections:

  • Mouse Data
  • Keyboard Data
  • Joystick Data
  • Output Data

Examples of retrieving data from input devices are found in the following tutorials:

  • Tutorial 1: Using the Keyboard
  • Tutorial 2: Using the Mouse
  • Tutorial 3: Using the Joystick


Buffered and Immediate Data

DirectInput supplies two types of data: buffered and immediate. Buffered data is a record of events that is stored until an application retrieves it. Immediate data is a snapshot of the current state of a device.

You might use immediate data in an application that is concerned only with the current state of a device: for example, a flight combat simulation that responds to the current position of the joystick and a pressed "fire" button. Buffered data might be the better choice where events are more important than states: for example, in an application that responds to movement of the mouse and button clicks.

You get immediate data with the IDirectInputDevice::GetDeviceState method. As the name implies, this method simply returns the current state of the device: for example, whether each button is up or down. The method provides no data about what has happened with the device since the last call, apart from implicit information you can derive by comparing the current state with the last one. If the user manages to press and release a button between two calls to GetDeviceState, your application won't know anything about it. On the other hand, if the user is holding a button down, GetDeviceState will continue reporting "button down" until the user releases it.

This way of reporting the device state is different from the way Windows reports events with one-time messages like WM_LBUTTONDOWN; it is more akin to the results from the Win32 GetKeyboardState function. If you are polling a device with GetDeviceState, you are responsible for determining what constitutes a button click, a double-click, a single keystroke, and so on, and for ensuring that your application doesn't keep responding to a button-down or key-down state when it's not appropriate to do so.

With buffered data, events are stored until you're ready to deal with them. Every time a button or key is pressed or an axis is moved, information about the event is placed in a DIDEVICEOBJECTDATA structure in the buffer. If the buffer overflows, new data is lost. Your application reads the buffer with a call to IDirectInputDevice::GetDeviceData. You can read any number of items at a time.

Reading an item normally deletes it from the buffer, but you also have the choice of peeking without deleting.

In order to get buffered data you must first set the buffer size with the IDirectInputDevice::SetProperty method. (See the example under Device Properties.) You set the buffer size before acquiring the device for the first time. For reasons of efficiency, the default size of the buffer is zero. You will not be able to obtain buffered data unless you change this value.

Note The size of the buffer is measured in items of data for that type of device, not in bytes or words.

You should check the value of the pdwInOut parameter after a call to the GetDeviceData method. The number of items actually retrieved from the buffer is returned in this variable.

The Direct Input Quick Test application supplied with the DirectX SDK lets you see both immediate and buffered data from a device. After you create the device in the application window, set its properties on the Mode page. Now, on the Data page, you see immediate data on the left and buffered data on the right.

Note For devices that do not generate interrupts, such as analog joysticks, DirectInput does not obtain any data until you call the IDirectInputDevice2::Poll method. For more information, see Polling and Events.

For examples of retrieving buffered data, see IDirectInputDevice::GetDeviceData.

See also:

  • Time Stamps and Sequence Numbers
  • Mouse Data
  • Keyboard Data
  • Joystick Data


Time Stamps and Sequence Numbers

When DirectInput input data is buffered (see Buffered and Immediate Data), each DIDEVICEOBJECTDATA structure contains not only information about the type of event and the device object associated with it, but also a time stamp and a sequence number.

The dwTimeStamp member contains the system time in milliseconds at the time the event took place. This is equivalent to the value that would have been returned by the Win32 GetTickCount function.

The dwSequence member contains a sequence number assigned by DirectInput. The DirectInput system keeps a single sequence counter, which is incremented by each non-simultaneous buffered event from any device. You can use this number to compare events from different devices and see which came first. The DISEQUENCE_COMPARE macro takes wraparound into account.

Simultaneous events are assigned the same sequence number. If a mouse or joystick is moved diagonally, for example, the changes in the x-axis and the y-axis have the same sequence number.

Note Events are always placed in the buffer in chronological order, so you don't need to check the sequence numbers just to sort the events from a single device.


Polling and Events

There are two ways to find out whether input data is available: by polling and by event notification.

Polling a device means regularly getting the current state of the device objects with IDirectInputDevice::GetDeviceState or retrieving the contents of the buffer with IDirectInputDevice::GetDeviceData. Polling is typically used by real-time games that are never idle but are constantly updating and rendering the game world.

Event notification is suitable for applications like the Scrawl sample that wait for input before doing anything. To use event notification, you set up a thread synchronization object with the Win32 CreateEvent function and then associate this event with the device by passing its handle to the IDirectInputDevice::SetEventNotification method. The event is then signaled by DirectInput whenever the state of the device changes. Your application can receive notification of the event with a Win32 function such as WaitForSingleObject, and then respond by checking the input buffer to find out what the event was. For sample code, see the Scrawl sample and the reference for IDirectInputDevice::SetEventNotification.

Some joysticks and other game devices, or particular objects on them, do not generate hardware interrupts and will not return any data or signal any events until you call the IDirectInputDevice2::Poll method. To find out whether this is necessary, first set the data format for the device, then call the IDirectInputDevice::GetCapabilities method and check for the DIDC_POLLEDDATAFORMAT flag in the DIDEVCAPS structure.

Do not confuse the DIDC_POLLEDDATAFORMAT flag with the DIDC_POLLEDDEVICE flag. The latter will be set if any object on the device requires polling. You can then find out whether this is the case for a particular object by calling the IDirectInputDevice::GetObjectInfo method and checking for the DIDOI_POLLED flag in the DIDEVICEOBJECTINSTANCE structure.

The DIDC_POLLEDDEVICE flag describes the worst case for the device, not the actual situation. For example, a HID mouse with software-controllable resolution might be marked as DIDC_POLLEDDEVICE because reading the resolution information requires polling. Polling the device under these conditions is pointless if all you want is the standard button and axis data.

Nonetheless it doesn't hurt to call the IDirectInputDevice2::Poll method for any input device. If the call is unnecessary, it will have no effect and will be very fast.


Relative and Absolute Axis Coordinates

Axis coordinates may be returned as relative values; that is, the amount by which they have changed since the last call to the IDirectInputDevice::GetDeviceState method or, in the case of buffered input, since the last item was put in the buffer.

Absolute axis coordinates are a running total of all the relative coordinates returned by the system since the device was acquired; in other words, they show the position of the axis in relation to a fixed point.

By default, mouse axes are reported as relative coordinates and joystick axes as absolute coordinates. You can use the IDirectInputDevice::SetProperty method to change the default behavior of any axis or all the axes of a device.


Mouse Data

To set up the mouse device for data retrieval, first call the IDirectInputDevice::SetDataFormat method with the c_dfDIMouse global variable as the parameter.

For maximum performance in a full-screen application, set the cooperative level to DISCL_EXCLUSIVE | DISCL_FOREGROUND. Note that the exclusive setting will cause the Windows cursor to disappear. Remember too that the DISCL_FOREGROUND setting will cause the application to lose access to the mouse when you switch to a debugging window. Changing to DISCL_BACKGROUND will allow you to debug the application more easily, at a cost in performance.

The following sections give more information about getting and interpreting immediate and buffered mouse data:

  • Immediate Mouse Data
  • Buffered Mouse Data
  • Interpreting Mouse Axis Data
  • Checking for Lost Mouse Input

See also

Device Data Formats, Cooperative Levels


Immediate Mouse Data

To retrieve the current state of the mouse, call IDirectInputDevice::GetDeviceState with a pointer to a DIMOUSESTATE structure. The mouse state returned in the structure includes axis data and the state of each of the buttons.

The first three members of the DIMOUSESTATE structure hold the axis coordinates. (See Interpreting Mouse Axis Data.)

The rgbButtons member is an array of bytes, one for each of four buttons. Generally the first element in the array is the left button, the second is the right button, the third is the middle button, and the fourth is any other button. The high bit is set if the button is down and clear if the button is up or not present.

See also

Buffered and Immediate Data


Buffered Mouse Data

To retrieve buffered data from the mouse, you must first set the buffer size (see Device Properties). The default size of the buffer is zero, so this step is essential. You then declare an array of DIDEVICEOBJECTDATA structures with the same number of elements as the buffer size.

After acquiring the device, you can examine and flush the buffer anytime by using the IDirectInputDevice::GetDeviceData method. (See Buffered and Immediate Data.)

Each element in the DIDEVICEOBJECTDATA array represents a change in state for a single object on the mouse. For instance, a typical mouse contains four objects or input sources: x-axis, y-axis, button 0 and button 1. If the user presses button 0 and moves the mouse diagonally, the array passed to IDirectInputDevice::GetDeviceData will have three elements filled in: an element for button 0 being pressed, an element for the change in the x-axis, and an element for the change in the y-axis.

You can determine which object an element in the array refers to by checking the dwOfs member of the DIDEVICEOBJECTDATA structure against the following values:

  • DIMOFS_BUTTON0 to DIMOFS_BUTTON3
  • DIMOFS_X
  • DIMOFS_Y
  • DIMOFS_Z

Each of these values is derived from the offset of the data for the object in a DIMOUSESTATE structure. For example, DIMOFS_BUTTON0 is equivalent to the offset of rgbButtons[0] in the DIMOUSESTATE structure. With the macros you can use simple comparisons to determine which device object is associated with an item in the buffer. For example:

DIDEVICEOBJECTDATA  *lpdidod;
int                 n;
.
.
.
/* MouseBuffer is an array of DIDEVICEOBJECTDATA structures
   that has been set by a call to GetDeviceData.
   n is incremented in a loop that examines all filled elements
   in the array. */
lpdidod = &MouseBuffer[n];
if (( (int) lpdidod->dwOfs == DIMOFS_BUTTON0)
      && (lpdidod->dwData & 0x80))
{
 ;  // do something in response to left button press
}

The data for the change of state of the device object is located in the dwData member of the DIDEVICEOBJECTDATA structure. For axes, the coordinate value is returned in this member. For button objects, only the low byte of dwData is significant; the high bit of this byte is set if the button was pressed and clear if the button was released. In other words, the button was pressed if (dwData & 0x80) is nonzero.

For more information on the other members of the DIDEVICEOBJECTDATA structure, see Time Stamps and Sequence Numbers.


Interpreting Mouse Axis Data

The data returned for the x-axis and y-axis of a mouse indicates the movement of the mouse itself, not the cursor. The units of measurement, sometimes called mickeys, are based on the actual values returned by the mouse hardware. Because DirectInput communicates directly with the mouse driver, the values for mouse speed and acceleration set by the user in Control Panel do not affect this data.

Axis data returned from the mouse can be either relative or absolute. (See Relative and Absolute Axis Coordinates.) Because a mouse is a relative device—unlike a joystick, it does not have a home position—relative data is returned by default.

The axis mode, which specifies whether relative or absolute data should be returned, is a property that can be changed before the device is acquired. (See Device Properties.) To set the axis mode to absolute, call IDirectInputDevice::SetProperty with the DIPROP_AXISMODE value in the rguidProp parameter and with DIPROPAXISMODE_ABS in the dwData member of the DIPROPDWORD structure.

When the axis mode for the mouse is set to relative, the axis coordinate represents the number of mickeys that the device has been moved along the axis since the last value was returned. A negative value indicates that the mouse was moved to the left for the x-axis, or away from the user for the y-axis, or that the z-axis (the wheel) was rotated back. Positive values indicate movement in the opposite direction.

When the axis mode is set to absolute, the coordinates are simply a running total of all relative motions received by DirectInput. The axis coordinates are not initialized to any particular value when the device is acquired, so your application should treat absolute values as relative to an unknown origin. You can record the current absolute position whenever the device is acquired and save it as the "virtual origin." This virtual origin can then be subtracted from subsequent absolute coordinates retrieved from the device to compute the relative distance the mouse has moved from the point of acquisition.

The data returned for the axis coordinates is also affected by the granularity property of the device. For the x-axis and y-axis of the mouse, granularity is normally 1, meaning that the minimum change in value is 1. For the wheel axis it may be larger.


Checking for Lost Mouse Input

Because Windows may force your application to unacquire the mouse when you have set the cooperative level to DISCL_FOREGROUND and the focus switches to another application or even to the menu in your own application, you should check for the DIERR_INPUTLOST return value from the IDirectInputDevice::GetDeviceData or IDirectInputDevice::GetDeviceState methods, and attempt to reacquire the mouse if necessary. (See Acquiring Devices.)

Note You should not attempt to reacquire the mouse on getting a DIERR_NOTACQUIRED error. If you do, you are likely to get caught in an infinite loop: acquisition will fail, you will get another DIERR_NOTACQUIRED error, and so on.


Keyboard Data

As far as DirectInput is concerned, the keyboard is not a text input device but a game pad with many buttons. When your application requires text input, don't use DirectInput methods; it is far easier to retrieve the data from the normal Windows messages, where you can take advantage of services such as character repeat and translation of physical keys to virtual keys. This is particularly important for languages other than English, which may require special translation of key presses.

To set up the keyboard device for data retrieval, you must first call the IDirectInputDevice::SetDataFormat method with the c_dfDIKeyboard global variable as the parameter. (See Device Data Formats.)

The following sections give more information about obtaining and interpreting keyboard data:

  • Immediate Keyboard Data
  • Buffered Keyboard Data
  • Interpreting Keyboard Data
  • Checking for Lost Keyboard Input


Immediate Keyboard Data

To retrieve the current state of the keyboard, call the IDirectInputDevice::GetDeviceState method with a pointer to an array of 256 bytes that will hold the returned data.

The GetDeviceState method behaves in the same way as the Win32 GetKeyboardState function, returning a snapshot of the current state of the keyboard. Each key is represented by a byte in the array of 256 bytes whose address was passed as the lpvData parameter. If the high bit of the byte is set, the key is down. The array is most conveniently indexed with the DirectInput Keyboard Device Constants. (See also Interpreting Keyboard Data.)

Here is an example that does something in response to the ESC key being down:

// LPDIRECTINPUTDEVICE  lpdiKeyboard;  // previously initialized
                                       // and acquired

BYTE  diKeys[256];
if (lpdiKeyboard->GetDeviceState(256, diKeys) == DI_OK)
{
  if (diKeys[DIK_ESCAPE] & 0x80) DoSomething();
}


Buffered Keyboard Data

To retrieve buffered data from the keyboard, you must first set the buffer size (see Device Properties). This step is essential, because the default size of the buffer is zero. You then declare an array of DIDEVICEOBJECTDATA structures with the same number of elements as the buffer size.

After acquiring the keyboard device, you can examine and flush the buffer anytime by using the IDirectInputDevice::GetDeviceData method. (See Buffered and Immediate Data.)

Each element in the DIDEVICEOBJECTDATA array represents a change in state for a single key; that is, a press or release. Because DirectInput gets the data directly from the keyboard, any settings for character repeat in Control Panel are ignored. This means that a keystroke is only counted once, no matter how long the key is held down.

You can determine which key an element in the array refers to by checking the dwOfs member of the DIDEVICEOBJECTDATA structure against the DirectInput Keyboard Device Constants. (See also Interpreting Keyboard Data.)

The data for the change of state of the key is located in the dwData member of the DIDEVICEOBJECTDATA structure. Only the low byte of dwData is significant; the high bit of this byte is set if the key was pressed and clear if it was released. In other words, the key was pressed if (dwData & 0x80) is nonzero.


Interpreting Keyboard Data

This section covers the identification of keys for which data is reported by the IDirectInputDevice:GetDeviceState and IDirectInputDevice:GetDeviceData methods. For more information on interpreting the data from GetDeviceData, see Time Stamps and Sequence Numbers.

In one important respect, DirectInput differs from other ways of reading the keyboard in Windows. Keyboard data refers not to virtual keys but to the actual physical keys; that is, the scan codes. DIK_ENTER, for example, refers to the ENTER key on the main keyboard but not to the one on the numerical keypad. (For a list of the DIK_* values, see Keyboard Device Constants.)

DirectInput defines a constant for each key on the enhanced keyboard as well as the additional keys found on international keyboards. Because NEC keyboards support different scan codes than the PC-enhanced keyboards, DirectInput translates NEC key scan codes into PC-enhanced scan codes where possible.

Not all PC-enhanced keyboards have the Windows keys (DIK_LWIN, DIK_RWIN, and DIK_APPS). There is no way to determine whether the keys are physically available.

Laptops and other small computers often do not implement a full set of keys. Instead, some keys (typically numeric keypad keys) are multiplexed with other keys, selected by an auxiliary mode key, which does not generate a separate scan code.

If the keyboard subtype indicates a PC XT or PC AT keyboard, then the following keys are not available: DIK_F11, DIK_F12, and all the extended keys (DIK_* values greater than 0x7F). Furthermore, the PC XT keyboard lacks DIK_SYSRQ.

Japanese keyboards, particularly the NEC PC-98 keyboards, contain a substantially different set of keys than U.S. keyboards. For more information, see DirectInput and Japanese Keyboards.


Checking for Lost Keyboard Input

Because Windows may force your application to unacquire the keyboard when you have set the cooperative level to DISCL_FOREGROUND and the focus switches to another application, you should check for the DIERR_INPUTLOST return value from the IDirectInputDevice::GetDeviceData or IDirectInputDevice::GetDeviceState methods, and attempt to reacquire the keyboard if necessary. (See Acquiring Devices.)

Note You should not attempt to reacquire the keyboard on getting a DIERR_NOTACQUIRED error. If you do, you are likely to get caught in an infinite loop: acquisition will fail, you will get another DIERR_NOTACQUIRED error, and so on.


Joystick Data

To set up the joystick device for data retrieval, first call the IDirectInputDevice::SetDataFormat method with the c_dfDIJoystick or c_dfDIJoystick2 global variable as the parameter. (See Device Data Formats.)

Because some device drivers do not notify DirectInput of changes in state until explicitly asked to do so, you should always call the IDirectInputDevice2::Poll method before attempting to retrieve data from the joystick. For more information, see Polling and Events.

The following sections cover getting and interpreting data from a joystick or other similar input device such as a game pad or flight yoke:

  • Immediate Joystick Data
  • Buffered Joystick Data
  • Interpreting Joystick Axis Data
  • Checking for Lost Joystick Input


Immediate Joystick Data

To retrieve the current state of the joystick, call the IDirectInputDevice::GetDeviceState method with a pointer to a DIJOYSTATE or DIJOYSTATE2 structure, depending on whether the data format was set with c_dfDIJoystick or c_dfDIJoystick2. (See Device Data Formats.) The joystick state returned in the structure includes the coordinates of the axes, the state of the buttons, and the state of the point-of-view controllers.

The first seven members of the DIJOYSTATE structure hold the axis coordinates. The last of these, rglSlider, is an array of two values. (See Interpreting Joystick Axis Data.)

The rgdwPOV member contains the position of up to four point-of-view controllers in hundredths of degrees clockwise from north (or forward). The center position is reported as –1. For controllers that have only five positions, dwPOV will be one of the following values:

–1
0
90 * DI_DEGREES
180 * DI_DEGREES
270 * DI_DEGREES.

Note Some drivers report a value of 65,535 instead of –1 for the neutral position. You should check for a centered POV indicator as follows:

BOOL POVCentered = (LOWORD(dwPOV) == 0xFFFF);

The rgbButtons member is an array of bytes, one for each of 32 or 128 buttons, depending on the data format. For each button, the high bit is set if the button is down and clear if the button is up or not present.

The DIJOYSTATE2 structure has additional members for information about the velocity, acceleration, force, and torque of the axes.

See also

Buffered and Immediate Data


Buffered Joystick Data

To retrieve buffered data from the joystick, you must first set the buffer size (see Device Properties) and declare an array of DIDEVICEOBJECTDATA structures. The number of elements required in this array is the same as the buffer size. After acquiring the device, you can examine and flush the buffer anytime with the IDirectInputDevice:GetDeviceData method. (See Buffered and Immediate Data.)

Each element in the DIDEVICEOBJECTDATA array represents a change in state for a single object on the joystick. For instance, a simple joystick contains four objects or input sources: x-axis, y-axis, button 0 and button 1. If the user presses button 0 and moves the stick diagonally, the array passed to IDirectInputDevice::GetDeviceData will have three elements filled in: an element for button 0 being pressed, an element for the change in the x-axis, and an element for the change in the y-axis.

You can determine which object an element in the array refers to by checking the dwOfs member of the DIDEVICEOBJECTDATA structure against the following values:

  • DIJOFS_X
  • DIJOFS_Y
  • DIJOFS_Z
  • DIJOFS_Rx
  • DIJOFS_Ry
  • DIJOFS_Rz
  • DIJOFS_BUTTON0 to DIJOFS_BUTTON31 or DIJOFS_BUTTON(n)
  • DIJOFS_POV(n)
  • DIJOFS_SLIDER(n)

Each of these values is equivalent to the offset of the data for the object in a DIJOYSTATE structure. For example, DIJOFS_BUTTON0 is equivalent to the offset of rgbButtons[0] in the DIJOYSTATE structure. You can use simple comparisons to determine which device object is associated with an item in the buffer. For example:

DIDEVICEOBJECTDATA  *lpdidod;
int                 n;
.
.
.
/* JoyBuffer is an array of DIDEVICEOBJECTDATA structures
   that has been set by a call to GetDeviceData.
   n is incremented in a loop that examines all filled elements
   in the array. */
lpdidod = &JoyBuffer[n];
if (( (int) lpdidod->dwOfs == DIJOFS_BUTTON0)
   && (lpdidod->dwData & 0x80))
{
 ;  // do something in response to press of primary button
}

The data for the change of state of the device object is located in the dwData member of the DIDEVICEOBJECTDATA structure. For axes, the coordinate value is returned in this member. For button objects, only the low byte of dwData is significant; the high bit of this byte is set if the button is pressed and clear if the button is released.

For the other members, see Time Stamps and Sequence Numbers.


Interpreting Joystick Axis Data

Axis values for the joystick are like those for the mouse: the value returned for the x-axis is greater as the stick moves to the right, and the value for the y-axis increases as the stick moves toward the user.

Data is in arbitrary units determined by the range property of the axis. For example, if the range for the stick's x-axis is 0 to 10,000, a unit is one ten-thousandth of the stick's left-right travel, and the center position is 5,000. For some axes the granularity property may be greater than 1, in which case values will be rounded off; for example, if the granularity is 10 then values will be reported as 0, 10, 20, and so on.

Axis data is also affected by the dead zone, a region around the center position in which motion is ignored. The dead zone provides tolerance for a slight deviation from the true center position for either or both axes of the stick. An axis value within the range of the dead zone is reported as true center.

The saturation property of an axis is a zone of tolerance at the minimum and maximum of the range. An axis value within this zone is reported as the minimum or maximum value. The purpose of the saturation property is to allow for slight differences between, for example, the minimum x-axis value reported at the top left and bottom left positions of the stick.

The following diagram shows the effect of the dead zone and the saturation zones. The vertical axis represents the returned axis values, where min and max are the lower and upper limits of the reported range and ctr is the reported center. The horizontal axis shows the physical position of the stick, where pmin and pmax are the extremes of the physical range, pctr is neutral position of the axis, dmin and dmax are the limits of the dead zone, and smin and smax are the boundaries of the lower and upper saturation zones. The lower saturation zone lies between pmin and smin; the upper saturation zone lies between smax and pmax; and the dead zone lies between dmin and dmax.

For more information on joystick properties, see the following:

  • IDirectInputDevice::GetProperty
  • IDirectInputDevice::SetProperty
  • DIPROPRANGE

Axis coordinates from the joystick can be either relative or absolute. (See Relative and Absolute Axis Coordinates.) Because a joystick is an absolute device–unlike a mouse, it cannot travel infinitely far along any axis–absolute data is returned by default.

The axis mode, which specifies whether relative or absolute data should be returned, is a property that can be changed before the device is acquired. (See Device Properties.) To set the axis mode to relative, call the IDirectInputDevice::SetProperty method with the DIPROP_AXISMODE value in the rguidProp parameter and with DIPROPAXISMODE_REL in the dwData member of the DIPROPDWORD structure.

When the axis mode for the joystick is set to relative, the axis coordinate represents the number of units of movement along the axis since the last value was returned.


Checking for Lost Joystick Input

If you are using the joystick in foreground mode (see Cooperative Levels) you may lose the device when the focus shifts to another application.

You can check for the DIERR_INPUTLOST return value from the IDirectInputDevice::GetDeviceData or IDirectInputDevice::GetDeviceState methods, and attempt to reacquire the joystick if necessary. (See Acquiring Devices.)

Note You should not attempt to reacquire the joystick on getting a DIERR_NOTACQUIRED error. If you do, you are likely to get caught in an infinite loop: acquisition will fail, you will get another DIERR_NOTACQUIRED error, and so on.

Because access to the joystick is not going to be lost except when your application moves to the background—unlike the mouse and keyboard, the joystick is never used by the Windows system—an alternative method is to reacquire the device in response to a WM_ACTIVATE message.


Output Data

Human Interface Devices may accept output as well as generating input. The IDirectInputDevice2::SendDeviceData method is used to send packets of data to such devices.

SendDeviceData may be viewed as IDirectInputDevice::GetDeviceData in reverse. Like that method, it uses the DIDEVICEOBJECTDATA structure as the basic unit of data. In this case, however, the dwOfs member contains the instance ID of the device object associated with the data, rather than its offset in the data format for the device. (Because offset identifiers exist only for device objects that provide input in the selected data format, an object that only accepts output may not even have an offset.) The dwData member contains whatever data is appropriate for the object. The dwTimeStamp and dwSequence members are not used and must be set to zero.

To send data to the device, you first set up an array of DIDEVICEOBJECTDATA structures, fill the required number of elements with data, then pass its address and the number of elements used to SendDeviceData. Data for different device objects is combined into a single packet that is then sent to the device.

The form of the data packet is specific to the device, as is the treatment of unused fields in the packet. Some devices may treat fields as optional, meaning that if no data is supplied, the state of the object remains unchanged. More commonly, all fields are significant, even when you do not specifically supply data for them. For example, if you send data to a single keyboard LED, it is assumed that the data for the other two LEDs is zero and they will be turned off. However, you can override this behavior by using the DISDD_CONTINUE flag, in which case the data for the other two LEDs will be the value you most recently sent them.

The following function, when called repeatedly, causes the LEDs on the keyboard, as represented by the IDirectInputDevice2 interface pdev, to flash in a recurring pattern. The device object identifiers, NumLockID, CapsLockID, and ScrollLockID, have previously been obtained from the dwType member of the DIDEVICEOBJECTINSTANCE structure, either during enumeration of device objects or by calling IDirectInputDevice::GetObjectInfo. It is assumed that the high bit of the data byte determines the state of the LED.

void FlashLEDs(void)
    {
    static int         rgiBits[] = { 1, 2, 4, 2 };
    static int         iLooper = 0;
    DWORD              cdod = 3;                  // number of items
    DIDEVICEOBJECTDATA rgdod[3];
    HRESULT            hres;

    // Must clear dwTimeStamp and dwSequence
    ZeroMemory(rgdod, sizeof(rgdod));

    rgdod[0].dwOfs = NumLockID;
    rgdod[1].dwOfs = CapsLockID
    rgdod[2].dwOfs = ScrollLockID;

    rgdod[0].dwData = (rgiBits[iLooper] & 1) ? 0x80 : 0;
                                           // 1,0,0,0,...
    rgdod[1].dwData = (rgiBits[iLooper] & 2) ? 0x80 : 0;
                                           // 0,1,0,1,...
    rgdod[2].dwData = (rgiBits[iLooper] & 4) ? 0x80 : 0;
                                           // 0,0,1,0,...

    iLooper = (iLooper + 1) % ARRAYSIZE(rgiBits); // loops from 0 to 3

    hres = IDirectInputDevice2_SendDeviceData(pdev,
            sizeof(DIDEVICEOBJECTDATA),
            rgdod, &cdod, 0);
    }


Force Feedback

Force feedback is the generation of push or resistance in an input/output device, for example by motors mounted in the base of a joystick. DirectInput allows you to generate force-feedback effects for devices that have compatible drivers.

The following sections introduce the elements of force feedback:

  • Basic Concepts of Force Feedback
  • Effect Enumeration
  • Information About a Supported Effect
  • Creating an Effect
  • Effect Direction
  • Examples of Setting Effect Direction
  • Envelopes and Offsets
  • Effect Playback
  • Downloading and Unloading Effects
  • Changing an Effect
  • Gain
  • Force-Feedback State
  • Effect Object Enumeration
  • Constant Forces
  • Ramp Forces
  • Periodic Effects
  • Conditions
  • Custom Forces
  • Device-Specific Effects

To enumerate, create, and manipulate effects, you must first obtain a pointer to the IDirectInputDevice2 interface for the force-feedback device. For an example of how to do this, see Creating the DirectInput Device.


Basic Concepts of Force Feedback

A particular instance of force feedback is called an effect, and the push or resistance is called the force. Most effects fall into one of the following categories:

  • Constant force. A steady force in a single direction.
  • Ramp force. A force that steadily increases or decreases in magnitude.
  • Periodic effect. A force that pulsates according to a defined wave pattern.
  • Condition. A force that occurs only in response to input by the user. Two examples are a friction effect that generates resistance to movement of the joystick, and a spring effect that tends to move the stick back to a certain position after it has been moved from that position.

The strength of the force is called its magnitude. Magnitude is measured in units ranging from zero (no force) to 10,000 (maximum force for the device, defined in Dinput.h as DI_FFNOMINALMAX). A negative value indicates force in the opposite direction. Magnitudes are linear: a force of 10,000 is twice as great as one of 5,000.

Ramp forces have a beginning and ending magnitude. For a periodic effect, the basic magnitude is the force at the peak of the wave.

The direction of a force is the direction from which it comes; just as a north wind comes from the north, a positive force on an given axis pushes from the positive toward the negative.

Effects also have duration, measured in microseconds. Periodic effects have a period, or the duration of one cycle, also measured in microseconds. The phase of a periodic effect is the point along the wave where playback begins.

The following diagram represents a sawtooth periodic effect with a magnitude of 5,000, or half the maximum force for the device. The horizontal axis represents the duration of the effect, and the vertical axis represents the magnitude. Points above the center line represent positive force in the direction defined for the effect, and points below the center line represent negative force, or force in the opposite direction.

A force may be further shaped by an envelope. An envelope defines an attack value and a fade value, which modify the beginning and ending magnitude of the effect. Attack and fade also have duration, which determines how long the magnitude takes to reach or fall away from the sustain value, the magnitude in the middle portion of the effect.

The following diagram represents an envelope. The attack level is set to 8,000 and the fade level to 1,000. The sustain level will be defined by the basic magnitude of the force to which the envelope is being applied; in the example it is 5,000. Note that in this case the attack is greater than the sustain, giving the effect an initial strong kick. Both the attack and the fade level can be either greater or lesser than the sustain level.

The next diagram shows the result of the envelope being applied to the periodic effect in the first diagram. Note that the envelope is mirrored on the negative side of the magnitude. An attack value of 8,000 means that the initial magnitude of the force in either direction will be 80 percent of the maximum possible.

Periodic effects and conditions can also be modified by the addition of an offset, which defines the amount by which the waveform is shifted up or down from the base level. The practical effect of applying a positive offset to the sawtooth example would be to strengthen the positive force and weaken the negative one — in other words, the force would peak more strongly in one direction than in the other.

Finally, the overall magnitude of an effect can be scaled by gain, which is analogous to a volume control in audio. A single gain value can be applied to all effects for a device; you might want to do this to compensate for stronger or weaker forces on different hardware, or to accommodate the user's preferences.


Effect Enumeration

The IDirectInputDevice2::EnumEffects method returns information about the support offered by the device for various kinds of effects.

It is important to distinguish between supported effects and created effects, or effect objects. A supported effect might be a constant force that can be shaped by an envelope. However, this effect has no properties such as magnitude, direction, duration, attack, or fade. You set these properties when you create an effect object in your application. A supported effect may be represented by many effect objects, each with different parameters—for example, several constant forces each with different duration, magnitude, and direction.

For information on enumerating created effects, see Effect Object Enumeration.

Like other DirectInput enumerations, the IDirectInputDevice2::EnumEffects method requires a callback function; this is documented with the placeholder name DIEnumEffectsProc, but you can use a different name if you wish. This function is called for each effect enumerated. Within the function you can obtain the GUID for each effect, get information about the extent of hardware support, and create one or more effect objects whose methods you can use to manipulate the effect.

Here is a skeletal C++ example of the callback function, and the call to the IDirectInputDevice2::EnumEffects method that sets the enumeration in motion. Note that the pvRef parameter of the callback can be any 32-bit value; in this case it is a pointer to the device interface, used for getting information about effects supported by the device and for creating effect objects.

HRESULT  hr;
// LPDIRECTINPUTDEVICE lpdid2;   // already initialized

BOOL CALLBACK DIEnumEffectsProc(LPCDIEFFECTINFO pdei,
                                LPVOID pvRef)
{
    LPDIRECTINPUTDEVICE2 lpdid = pvRef;   // pointer to calling device
    LPDIRECTINPUTEFFECT  lpdiEffect;      // pointer to created effect
    DIEFFECT             diEffect;        // params for created effect
    DICONSTANTFORCE      diConstantForce; // type-specific parameters
                                          // for diEffect

    if (DIEF_GETTYPE(pdei->dwEffType) == DIEFFT_CONSTANTFORCE)
    {
       /* Here you can extract information about support for the
          effect type (from pdei), and tailor your effects
          accordingly. For example, the device might not support
          envelopes for this type of effect. */
       .
       .
       .
       // Create one or more constant force effects.
       // For each you have to initialize a DICONSTANTFORCE
       // and a DIEFFECT structure.
       // See detailed example at Creating an Effect
       .
       .
       .
        hr = pdid->CreateEffect(pdei->guid,
                                &diEffect,
                                &lpdiEffect,
                                NULL);
       .
       .
       .
    }
    // And so on for other types of effect
   .
   .
   .

    return DIENUM_CONTINUE;
}  // end of callback
.
.
.
// Set the callback into motion
hr = lpdid2->EnumEffects(&EnumEffectsProc,
                        lpdid2, DIEFT_ALL);

For more information on how to initialize an effect, see Creating an Effect.


Information About a Supported Effect

The IDirectInputDevice2::GetEffectInfo method can be used to retrieve information about the device's support for an effect. It retrieves the same information that is returned in the DIEFFECTINFO structure during enumeration. For more information, see Effect Enumeration.

The following C++ example fetches information about an enumerated effect whose GUID is stored in the EffectGuid variable:

DIEFFECTINFO diEffectInfo;
diEffectInfo.dwSize = sizeof(DIEFFECTINFO);
lpdid2->GetEffectInfo(&diEffectInfo, EffectGuid);


Creating an Effect

You create an effect object by using the IDirectInputDevice2::CreateEffect method, as in the following C++ example, where pdev2 points to an instance of the interface. This example creates a very simple effect that will pull the joystick away from the user at full force for half a second.

HRESULT  hr;
LPDIRECTINPUTEFFECT lpdiEffect;  // receives pointer to created effect
DIEFFECT diEffect;               // parameters for created effect

DWORD    dwAxes[2] = { DIJOFS_X, DIJOFS_Y };
LONG     lDirection[2] = { 18000, 0 };

DICONSTANTFORCE diConstantForce;

diConstantForce.lMagnitude = DI_FFNOMINALMAX;   // full force

diEffect.dwSize = sizeof(DIEFFECT);
diEffect.dwFlags = DIEFF_POLAR | DIEFF_OBJECTOFFSETS;
diEffect.dwDuration = 0.5 * DI_SECONDS;
diEffect.dwSamplePeriod = 0;               // = default
diEffect.dwGain = DI_FFNOMINALMAX;         // no scaling
diEffect.dwTriggerButton = DIEB_NOTRIGGER; // not a button response
diEffect.dwTriggerRepeatInterval = 0;      // not applicable
diEffect.cAxes = 2;
diEffect.rgdwAxes = &dwAxes;
diEffect.rglDirection = &lDirection;
diEffect.lpEnvelope = NULL;
diEffect.cbTypeSpecificParams = sizeof(DICONSTANTFORCE);
diEffect.lpvTypeSpecificParams = &diConstantForce;

hr = pdev2->CreateEffect(GUID_ConstantForce,
                         &diEffect,
                         &lpdiEffect,
                         NULL);

In the method call, the first parameter identifies the supported effect with which the created effect is to be associated. The example uses one of the predefined GUIDs found in Dinput.h. Note that if you use a predefined GUID, the call will fail if the device doesn't support the effect.

The second parameter sets the parameters as specified in the DIEFFECT structure.

The third parameter receives a pointer to the effect object if the call is successful.

The DIEFF_POLAR flag specifies the type of coordinates used for the direction of the force. (See Effect Direction.) It is combined with DIEFF_OBJECTOFFSETS, which indicates that any buttons or axes used in other members will be identified by their offsets within the DIDATAFORMAT structure for the device. The alternative is to use the DIEFF_OBJECTIDS flag, signifying that buttons and axes will be identified by the dwType member of the DIDEVICEOBJECTINSTANCE structure returned for the object when it was enumerated with the IDirectInputDevice::EnumObjects method.

For more information on the members of the DIEFFECT structure, see Effect Direction.


Effect Direction

Directions can be defined for one or more axes. As with the mouse and joystick, the x-axis increases from left to right, and the y-axis increases from far to near. For three-dimensional devices, the z-axis increases from up to down.

The direction of an effect is the direction from which it comes. An effect with a direction along the negative y-axis tends to push the stick along the positive y-axis (toward the user). It is somewhat easier to visualize the axis values of a direction if you imagine the user exerting a counteracting force on the device. If the user must push the stick toward the left in order to counteract an effect, the effect has a "left" direction; that is, it lies on the negative x-axis.

Direction can be expressed in polar, spherical, or Cartesian coordinates.

Polar coordinates are expressed as a single angle, in hundredths of degrees clockwise from whatever zero-point, or true north, has been established for the effect. Normally this is the negative y-axis; that is, away from the user. Thus an effect with a polar coordinate of 9,000 normally has a direction of east, or to the user's right, and the user must exert force to the right in order to counteract it.

Spherical coordinates are also in hundredths of degrees but may contain two or more angles; for each angle, the direction is rotated in the positive direction of the next axis. For a three-dimensional device, the first angle would normally be rotated from the positive x-axis toward the positive y-axis (clockwise from east); the second angle would be rotated toward the positive z-axis (down). Thus a force with a direction of (0, 0) would be to the user's right and parallel to the tabletop. A direction of 27,000 for the first angle and 4,500 for the second would be directly away from the user (270 degrees clockwise from east) and angling toward the floor (45 degrees downward from the tabletop); to counteract a force with this direction, the user would have to push forward and down.

Cartesian coordinates are similar to 3-D vectors. If you draw a straight line on graph paper with an origin of (0, 0) at the center of the page, the direction of the line can be defined by the coordinates of any intersection it crosses, regardless of the distance from the origin. A direction of (1, -2) and a direction of (5, -10) are exactly the same.

Note The coordinates used in creating force-feedback effects define only direction, not magnitude or distance.

When an effect is created or modified, the cAxes, rgdwAxes, and rglDirection members of the DIEFFECT structure are used to specify the direction of the force.

The cAxes member simply specifies the number of elements in the arrays pointed to by the next two members.

The array pointed to by rgdwAxes identifies the axes. If the DIEFF_OBJECTOFFSETS flag has been set, the axes are identified by the offsets within the data format structure. These offsets are most readily identified by using the DIJOFS_* defines. (For a list of these values, see Joystick Device Constants.)

Finally, the rglDirection member specifies the direction of the force.

Note The cAxes and rgdwAxes members cannot be modified once they have been set. An effect always has the same axis list.

Regardless of whether you are using Cartesian, polar, or spherical coordinates, you must provide exactly as many elements in rglDirection as there are axes in the array pointed to by rgdwAxes.

In the polar coordinate system, "north" (zero degrees) lies along the vector (0, -1), where the elements of the vector correspond to the elements in the axis list pointed to by rgdwAxes. Normally those axes are x and y, so north is directly along the negative y-axis; that is, away from the user. The last element of rglDirection must be zero.

In the example under Creating an Effect, the direction of a two-dimensional force is defined in polar coordinates. The force has a south direction—it comes from the direction of the user, so that the user has to pull the stick to counteract it. The direction is 180 degrees clockwise from north, and can be assigned as follows:

LONG  lDirection[2] = { 18000, 0 };

For greater clarity, the assignment could also be expressed this way:

LONG  lDirection[2] = { 180 * DI_DEGREES, 0 };

For spherical coordinates, presuming that you are working with a three-axis device, the same direction is assigned as follows:

LONG  lDirection[3] = { 90 * DI_DEGREES, 0, 0 }

The reference for the DIEFFECT structure tells us that the first angle is measured in hundredths of degrees from the (1, 0) direction, rotated in the direction of (0, 1); the second angle is measured in hundredths of degrees towards (0, 0, 1). The elements of the vector notation again correspond to elements in the array pointed to by the rgdwAxes member. Suppose the elements of this array represent the x, y, and z axes, in that order. The point of origin is at x = 1 and y = 0; that is, to the user's right. The direction of rotation is toward the positive y-axis ( 0, 1); that is, toward the user, or clockwise. The force in the example is 90 degrees clockwise from the right; that is, south. Because the second element of lDirection is 0, there is no rotation on the third axis.

How do you accomplish the same thing with Cartesian coordinates? Presuming you have used the DIEFF_CARTESIAN flag in the dwFlags member, you would specify the direction like this:

LONG     lDirection[2] = { 0, 1 };

Here again the elements of the array correspond to the axes listed in the array pointed to by rgdwAxes. The example sets the x-axis to zero and the y-axis to 1; that is, the direction lies directly along the positive y-axis, or to the south.

The theory of effect directions can be difficult to grasp, but the practice is fairly straightforward. For sample code, see Examples of Setting Effect Direction.


Examples of Setting Effect Direction

Single-Axis Effects

Setting up the direction for a single-axis effect is extremely simple, because there is really nothing to specify. You put the DIEFF_CARTESIAN flag in the dwFlags member of the DIEFFECT structure and set rglDirection to point to a single LONG containing the value 0.

The following example sets up the direction and axis parameters for an x-axis effect:

DIEFFECT eff;
LONG     lZero = 0;                        // No direction
DWORD    dwAxis = DIJOFS_X;                // x-axis effect

ZeroMemory(&eff, sizeof(DIEFFECT));
eff.cAxes = 1;                             // One axis
eff.dwFlags =
    DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS; // Flags
eff.rglDirection = &lZero;                 // Direction
eff.rgdwAxes = &dwAxis;                    // Axis for effect

Two-Axis Effects with Polar Coordinates

Setting up the direction for a polar two-axis effect is only a little more complicated. You set the DIEFF_POLAR flag in dwFlags and set rglDirection to point to an array of two LONGs. The first element in this array is the direction from which you want the effect to come. The second element in the array must be zero.

The following example sets up the direction and axis parameters for a two-axis effect coming from the east:

DIEFFECT eff;
LONG     rglDirection = { 90 * DI_DEGREES, 0 }; // 90 degrees from
                                                // north, i.e. east
DWORD    rgdwAxes[2] = { DIJOFS_X, DIJOFS_Y };  // x- and y-axis

ZeroMemory(&eff, sizeof(DIEFFECT));
eff.cAxes = 2;                                  // Two axes
eff.dwFlags =
    DIEFF_POLAR | DIEFF_OBJECTOFFSETS;          // Flags
eff.rglDirection = rglDirection;                // Direction
eff.rgdwAxes = rgdwAxes;                        // Axis for effect

Two-Axis Effects with Cartesian Coordinates

Setting up the direction for a Cartesian two-axis effect is a bit trickier, but not by much. You set the DIEFF_CARTESIAN flag in dwFlags and again set rglDirection to point to an array of two LONGs. This time the first element in the array is the x-coordinate of the direction vector, and the second is the y-coordinate.

The following example sets up the direction and axis parameters for a two-axis effect coming from the east:

DIEFFECT eff;
LONG     rglDirection = { 1, 0 };               // Positive x = east
DWORD    rgdwAxes[2] = { DIJOFS_X, DIJOFS_Y };  // x- and y-axis

ZeroMemory(&eff, sizeof(DIEFFECT));
eff.cAxes = 2;                                  // Two axes
eff.dwFlags =
    DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS;      // Flags
eff.rglDirection = rglDirection;                // Direction
eff.rgdwAxes = rgdwAxes;                        // Axis for effect


Envelopes and Offsets

You can modify the basic magnitude of some effects by applying an envelope and an offset. For an overview, see Basic Concepts of Force Feedback.

To apply an envelope when creating or modifying an effect, initialize a DIENVELOPE structure and put a pointer to it in the lpEnvelope member of the DIEFFECT structure.

The device driver determines which effects support envelopes. Typically you can apply an envelope to a constant force, a ramp force, or a periodic effect, but not to a condition. To determine whether a particular effect supports an envelope, you call the IDirectInputDevice2::GetEffectInfo method and check for the DIEP_ENVELOPE flag in the dwStaticParams member of the DIEFFECTINFO structure.

To apply an offset, set the lOffset member of the DIPERIODIC or DICONDITION structure pointed to by the lpvTypeSpecificParams member of the DIEFFECT structure. For periodic effects, the absolute value of the offset plus the magnitude of the effect must not exceed DI_FFNOMINALMAX.

You cannot apply an offset to a constant force or ramp force. In these cases the same effect can be achieved by altering the magnitude.


Effect Playback

There are two principal ways to start playback of an effect: manually by a call to the IDirectInputEffect::Start method, and automatically in response to a button press. Playback also starts when you change an effect by calling the IDirectInputEffect::SetParameters method with the DIEP_START flag.

Passing INFINITE in the dwIterations parameter has the effect of playing the effect repeatedly, with the envelope being applied each time. If you want to repeat an effect without repeating the envelope—for example, to begin with a strong kick, then settle down to a steady throb—set dwIterations to 1 and set the dwDuration member of the DIEFFECT structure to INFINITE. (This is the structure passed to the IDirectInputDevice2::CreateEffect method.)

Note Some devices do not support multiple iterations of an effect and accept only the value 1 in the dwIterations parameter to the Start method. You should always check the return value from Start to make sure the effect played successfully.

To associate an effect with a button press, you set the dwTriggerButton member of the DIEFFECT structure. You also set the dwTriggerRepeatInterval member to the desired delay between playbacks when the button is held down; this is the interval, in microseconds, between the end of one playback and the start of the next. On some devices, multiple effects cannot be triggered by the same button; if you associate more than one effect with a button; the last effect downloaded will be the one triggered.

To dissociate an effect from its trigger button, you must either call the IDirectInputEffect::Unload method or set the parameters for the effect with dwTriggerButton set to DIEB_NOTRIGGER.

Triggered effects, like all others, are lost when the application loses access to the device. In order to make them active again, you must download them as soon as the application reacquires the device. This step is not necessary for effects not associated with a trigger, because they are automatically downloaded if necessary whenever the Start method is called.

If an effect has a finite duration and is started by a call to the Start method, it will stop playing when the time has elapsed. If its duration was set to INFINITE, playback ends only when the IDirectInputEffect::Stop method is called. An effect associated with a trigger button starts when the button is pressed and stops when the button is released or the duration has elapsed, whichever comes sooner.


Downloading and Unloading Effects

Before an effect can be played, it must be downloaded to the device. Downloading an effect means telling the driver to prepare the effect for playback. It is entirely up to the driver to determine how this is done. Generally the driver will place the parameters of the effect in hardware memory in order to minimize the subsequent transfer of data between the device and the system. The consequent reduction in latency is particularly important for conditions and for effects played in response to a trigger, such as a "fire" button. Ideally the device will not have to communicate with the system at all in order to respond to axis movements and button presses.

Downloading is done automatically when you create an effect, provided the device is not full and is acquired at the exclusive cooperative level. By default it is also done when you start the effect or change its parameters. If you specify the DIEP_NODOWNLOAD flag when changing parameters, you must subsequently use the IDirectInputEffect::Download method to download or update the effect.

When the device is unacquired — for example, when it has been acquired with the exclusive foreground cooperative level and the application moves to the background — effects are unloaded and must be downloaded again when the application regains the foreground. As previously stated, this will be done automatically when you call the IDirectInputEffect::Start method, but you may choose to download all effects immediately on reacquiring the device. You always have to download effects associated with a trigger button, since the Start method will not normally be called for such effects.

If your application gets the DIERR_DEVICEFULL error when downloading an effect, you have to make room for the new effect by unloading an old one. You can remove an effect from the device by calling the IDirectInputEffect::Unload method. You can also remove all effects by resetting the device through a call to the IDirectInputDevice2::SendForceFeedbackCommand method.

When you create a force-feedback device, the hardware and driver are reset, so any existing effects are cleared.


Changing an Effect

You can modify the parameters of an effect, in some cases even while the effect is playing. You do this by using the IDirectInputEffect::SetParameters method.

The dwDynamicParams member of the DIEFFECTINFO structure tells you which effect parameters can be changed while an effect is playing. If you attempt to modify an effect parameter that cannot be modified while the effect is playing, and the effect is still playing, then DirectInput will normally stop the effect, update the parameters, and restart the effect. You can override this default behavior by passing the DIEP_NORESTART flag.

The following C++ example changes the magnitude of the constant force that was set in the example under Creating an Effect.

DIEFFECT        diEffect;           // parameters for effect
DICONSTANTFORCE diConstantForce;
  // type-specific parameters.

diConstantForce.lMagnitude = 5000;
diEffect.dwSize = sizeof(DIEFFECT);
diEffect.cbTypeSpecificParams = sizeof(DICONSTANTFORCE);
diEffect.lpvTypeSpecificParams = &diConstantForce;
hr = lpdiEffect->SetParameters(&diEffect, DIEP_TYPESPECIFICPARAMS);

The flag ensures that the transfer of data from the DIEFFECT structure is restricted to the relevant members, so that you do not have to initialize the entire structure and so that the minimum possible amount of data needs to be sent to the device.


Gain

You may want to scale the force of your effects according to the actual force exerted by different devices. For example, if an application's effects feel right on a device that puts out a maximum force of n Newtons on a given axis, then you may want to adjust the gain for a device that puts out more force. (You cannot use the gain to increase the maximum force of the axis, so you should set the basic effect magnitudes to values suitable for devices that put out less force.)

The actual force generated by a device object such as an axis or button is returned in the dwFFMaxForce member of the DIDEVICEOBJECTINSTANCE structure when objects are enumerated. (See Device Object Enumeration.)

You can set the gain for the entire device by using the IDirectInputDevice::SetProperty method. You can also set the gain for individual effects when creating or modifying them. Put the new gain value in the dwGain member of the DIEFFECT structure. If modifying the effect with the SetProperty method, be sure to include DIEP_GAIN in the flags parameter.

The purpose of setting the device gain is to allow your application to have control over the strength of all effects all at once. For example, you might have a slider control in your application to allow the user to specify how strong the force-feedback effects should be, like the master volume control on a sound mixer. By setting the device gain, your application won't need to adjust the gain of each individual effect to suit the user's preferences.

A gain value may be in the range 0 to 10,000 (or DI_FFNOMINALMAX), where 10,000 indicates that magnitudes are not to be scaled, 7,500 means that forces are to be scaled to 75 percent of their nominal magnitudes, and so on.


Force Feedback State

The IDirectInputDevice2::SendForceFeedbackCommand method allows you to turn off the device's actuators (effectively causing it to ignore any effects that are being played), pause or stop playback of effects, and reset the device so that all downloaded effects are removed.

To retrieve the current force-feedback state, use the IDirectInputDevice2::GetForceFeedbackState method. This method returns information about whether the actuators are active, whether playback is paused, and whether the device has been reset. It also retrieves information about various switches and about whether the device is currently powered.


Effect Object Enumeration

Whenever you need to examine or manipulate all the effects you have created, you can use the IDirectInputDevice2::EnumCreatedEffectObjects method. As no flags are currently defined for this method, you cannot restrict the enumeration to particular kinds of effects; all effects will be enumerated.

Note This method enumerates created effects, not effects supported by a device. For more information on the distinction between the two, see Effect Enumeration.

Like other DirectInput enumerations, the EnumCreatedEffectObjects method requires a callback function. This standard callback is documented with the placeholder name DIEnumCreatedEffectObjectsProc, but you can use a different name. The function is called for each effect enumerated. Within the function you can perform any processing you want; however, it is not safe to create a new effect while enumeration is going on.

Here is a skeletal C++ example of the callback function, and the call to the EnumCreatedEffectObjects method. Note that the pvRef parameter of the callback can be any 32-bit value; in this case it is a pointer to the device interface.

HRESULT  hr;
// LPDIRECTINPUTDEVICE lpdid;   // already initialized

BOOL CALLBACK DIEnumCreatedEffectObjectsProc(
                     LPDIRECTINPUTEFFECT peff, LPVOID pvRef);
{
    LPDIRECTINPUTDEVICE  pdid = pvRef; // pointer to calling device
    DIEFFECT            diEffect;      // params for created effect

    diEffect.dwSize = sizeof(DIEFFECTINFO);
    peff->GetParameters(&diEffect, DIEP_ALLPARAMS);
    // check or set parameters, or do anything else
    .
    .
    .
}  // end of callback

// Set the callback into motion
hr = lpdid->EnumCreatedEffectObjects(&EnumCreatedEffectObjectsProc,
                                     &lpdid, 0);


Constant Forces

A constant force is a force with a defined magnitude and duration.

You can apply an envelope to a constant force in order to give it shape. For example, suppose you have an effect with a nominal magnitude of 2,000 and a duration of 2 seconds. Then you apply an envelope with the following values:

Attack time | 0.5 second
Initial attack level | 5,000
Fade time | 1 second
Fade level | 0

When you play the effect, you get the following:

Elapsed time | Magnitude
0.0 | 5,000
0.1 | 4,400
0.2 | 3,800
0.3 | 3,200
0.4 | 2,600
0.5 | 2,000
(duration of sustain) | 2,000
1.0: | 2,000
1.1 | 1,800
1.2 | 1,600
1.3 | 1,400
1.4 | 1,200
1.5 | 1,000
1.6 | 800
1.7 | 600
1.8 | 400
1.9 | 200
2.0 | 0

You cannot apply an offset to a constant force.

To create a constant force, pass GUID_ConstantForce to the IDirectInputDevice2::CreateEffect method. You can also pass any other GUID obtained by the IDirectInputDevice2::EnumEffects method, provided the low byte of the dwEffType member of the DIEFFECTINFO structure (DIEFT_GETTYPE(dwEfftype)) is equal to DIEFT_CONSTANTFORCE. In this way you can use hardware-specific forces designed by the manufacturer, such as a "constant" force that actually varies in magnitude in a seemingly random fashion to simulate turbulence.

A constant force uses a DICONSTANTFORCE structure to define the magnitude of the force, while the duration is taken from the DIEFFECT structure. An envelope may be applied.


Ramp Forces

A ramp force is a force with defined starting and ending magnitudes and a finite duration. A ramp force may continue in a single direction, or it may start as a strong push in one direction, weaken, stop, and then strengthen in the opposite direction.

The following diagram shows a ramp force that starts at a magnitude of -5,000 and ends at 5,000:

You can apply an envelope to a ramp force in order to shape it further. The following diagram shows the effect of applying an envelope, shown in green, to the ramp force in the previous diagram.

Note that during the sustain portion of the envelope, the magnitude of the effect follows the same straight line as before the envelope was applied. For the duration of the attack and fade, the slope of the ramp is modified by the attack and fade levels.

You cannot apply an offset to a ramp force.

To create a ramp force, pass GUID_RampForce to the IDirectInputDevice2::CreateEffect method. You can also pass any other GUID obtained by the IDirectInputDevice2::EnumEffects method, provided the low byte of the dwEffType member of the DIEFFECTINFO structure (DIEFT_GETTYPE(dwEfftype)) is equal to DIEFT_RAMPFORCE. In this way you can use hardware-specific ramp forces designed by the manufacturer.

A ramp force uses a DIRAMPFORCE structure to define the starting and ending magnitude of the force, while the duration is taken from the DIEFFECT structure. Duration must never be set to INFINITE.


Periodic Effects

Periodic effects are waveform effects. DirectInput defines the following forms:

  • Square.
  • Sine.
  • Cosine.
  • Triangle.
  • SawtoothUp. The waveform drops vertically after it reaches maximum positive force. See the example at Basic Concepts of Force Feedback.
  • SawtoothDown. The waveform rises vertically after it reaches maximum negative force.

An envelope can be applied to periodic effects. See the example at Basic Concepts of Force Feedback.

The phase of a periodic effect is the point along the waveform where the effect begins. Phase is measured in hundredths of a degree, from 0 to 35,999. The following table indicates where selected phase values (in degrees) lie along the various waveforms. Max is the top (+) or bottom (–) of the wave and Mid is the midpoint, where no force is applied in either direction.

 | 0 | 90 | 180 | 270
Square | +Max | +Max | –Max | –Max
Sine | Mid | +Max | Mid | –Max
Triangle | +Max | Mid | –Max | Mid
SawtoothUp | –Max | –Max/2 | Mid | +Max/2 (reaches +Max just before the cycle repeats)
SawtoothDown | +Max | +Max/2 | Mid | –Max/2 (reaches –Max just before the cycle repeats)

A driver may round off a phase value to the nearest supported value. For example, for a sine effect some drivers support only values of 0 and 9,000 (to create a cosine); for other effects, only values of 0 and 18,000 are supported.

To create a periodic force, pass one of the following values in the rguid parameter of the IDirectInputDevice2::CreateEffect method:

  • GUID_Square
  • GUID_Sine
  • GUID_Triangle
  • GUID_SawtoothUp
  • GUID_SawtoothDown

You can also pass any other GUID obtained by the IDirectInputDevice2::EnumEffects method, provided the low byte of the dwEffType member of the DIEFFECTINFO structure (DIEFT_GETTYPE(dwEfftype)) is equal to DIEFT_PERIODIC. In this way you can use hardware-specific forces designed by the manufacturer. For example, a hardware device might support a periodic effect that rotates the stick in a small circle.

The type-specific structure for periodic effects is DIPERIODIC.


Conditions

Conditions are forces applied in response to current sensor values within the device. In other words, conditions require information about device motion such as position or velocity of a joystick handle.

In general, conditions are not associated with individual events during a game or other application. They represent ambient phenomena such as the stiffness or looseness of a flight stick, or the tendency of a steering wheel to return to a straight-ahead position.

A condition does not have a predefined magnitude; the magnitude is scaled in proportion to the movement or position of the input object.

DirectInput defines the following types of condition effects:

  • Friction. The force is applied when the axis is moved, and depends on the defined friction coefficient.
  • Damper. The force increases in proportion to the velocity with which the user moves the axis.
  • Inertia. The force increases in proportion to the acceleration of the axis.
  • Spring. The force increases in proportion to the distance of the axis from a defined neutral point.

Most hardware devices do not support the application of envelopes to conditions. To determine whether a particular effect supports an envelope, check for the DIEP_ENVELOPE flag in the dwStaticParams member of the DIEFFECTINFO structure.

Conditions have the following type-specific parameters:

Offset.
The offset from the zero reading of the appropriate sensor value where the condition begins to be applied. For a spring effect, the neutral point — that is, the point along the axis where the spring would be considered at rest — would be defined by the offset for the condition. For a damper, the offset would define the greatest velocity value for which damping force is zero. Offset is not normally used for inertia or friction effects.
Coefficient.
A multiplier that scales the effect. For some devices, you can set separate coefficients for the positive and negative direction along the axis associated with the condition. For example, a flight stick controlling a damaged aircraft might move more easily to the right than to the left.
Saturation.
In force feedback, saturation is an expression of the maximum possible force for an effect. For example, suppose a flight stick has a spring condition on the x-axis. The offset is 0 and the coefficient is 10,000, so the maximum force is normally exerted when the stick is furthest from the center. But if you define a positive and negative saturation of 5,000, the force does not increase after the stick has been moved halfway to the right or left.
Deadband.
The deadband is a zone around the offset of an axis where the condition is not active. In the case of a spring that is at rest in the middle of an axis, the deadband enlarges this area of rest.

Conditions can have duration, though in most cases you would probably want to set the duration to INFINITE and stop the effect only in response to some event in the application.

To create a condition, pass one of the following values in the rguid parameter of the IDirectInputDevice2::CreateEffect method:

  • GUID_Spring
  • GUID_Damper
  • GUID_Inertia
  • GUID_Friction

You can also pass any other GUID obtained by the IDirectInputDevice2::EnumEffects method, provided the low byte of the dwEffType member of the DIEFFECTINFO structure (DIEFT_GETTYPE(dwEfftype)) is equal to DIEFT_CONDITION. In this way you can use hardware-specific conditions designed by the manufacturer.

The type-specific structure for conditions is DICONDITION. For multiple-axis conditions you may provide an array of such structures, one for each axis, or a single structure that defines the condition in the specified direction. In either case you need to set the cbTypeSpecificParams member of the DIEFFECT structure to the actual number of bytes used; that is, to sizeof(DICONDITION) * n, where n is the number of structures provided. For more information on how to use either single or multiple structures, see the Remarks for the DICONDITION structure.

An application should call the IDirectInputDevice2::GetEffectInfo method or the IDirectInputDevice2::EnumEffects method and examine the dwEffectType member of the DIEFFECTINFO structure in order to determine if the both a positive and negative coefficient and saturation for the effect are supported on the device. If the effect does not return the DIEFT_POSNEGCOEFFICIENTS flag, it will ignore the value in the lNegativeCoefficient member and the value in lPositiveCoefficient will be applied to the entire axis. Likewise, if the effect does not return the DIEFT_POSNEGSATURATION flag, it will ignore the value in the dwNegativeSaturation and the value in dwPositiveSaturation will be used as the negative saturation level. Finally, if the effect does not return the DIEFT_SATURATION flag, it will ignore both the lPositiveSaturation and lNegativeSaturation values and no saturation will be applied.

Note that you can set a coefficient to a negative value, and this has the effect of generating the force in the opposite direction. For example, for a spring effect it would cause the spring to push away from the offset point rather than pulling toward it.

You should also check the dwEffectType member for the DIEFT_DEADBAND flag, to see if deadband is supported for the condition. If it is not supported, the value in the lDeadBand member of the DICONDITION structure will be ignored.


Custom Forces

Application writers can create their own effects by creating a custom force. A custom force is an array of constant force values played back by the device.

The type-specific structure for custom waveform effects is DICUSTOMFORCE.

You should set the dwSamplePeriod member of the DICUSTOMFORCE structure and the dwSamplePeriod member of the DIEFFECT structure to the same value. This is the length of time, in milliseconds, for which each element in the array of forces will be played.

The custom force is played repeatedly until the time set in the dwDuration member of the DIEFFECT structure has elapsed.


Device-Specific Effects

DirectInput provides a way to control device-specific effects. This is useful for hardware vendors who have extra effects that are not directly supported by DirectInput.

The hardware vendor must provide a GUID identifying the device-specific effect and may provide a custom structure for the type-specific parameters of the effect. Your application then must initialize a DIEFFECT structure and a type-specific structure, just as with any other effect. You then call the IDirectInputDevice2::CreateEffect method, passing the device-specific GUID and a pointer to the DIEFFECT structure.

When you obtain information about a device-specific effect in a DIEFFECTINFO structure, the low byte of the dwEffType member (DIEFT_GETTYPE(dwEfftype)) indicates into which of the predefined DirectInput effect categories (constant force, ramp force, periodic, or condition) the effect falls. If it does not fall into any of the predefined categories, then the value is DIEFT_HARDWARE.

If a device-specific effect falls into one of the predefined categories, then the lpvTypeSpecificParams member of the DIEFFECT structure must point to the corresponding DICONSTANTFORCE, DIRAMPFORCE, DIPERIODIC, or DICONDITION structure, and the cbTypeSpecificParams member must be equal to the size of that structure.

If the (DIEFT_GETTYPE(dwEfftype) == DIEFT_HARDWARE), then the values of the lpvTypeSpecificParams and cbTypeSpecificParams members depend on whether the effect requires custom type-specific parameters. If it does, then these values must refer to the appropriate structure defined in the manufacturer's header file and declared and initialized by your application. If the effect does not require custom parameters—that is, if the dwStaticParms member of the DIEFFECTINFO structure for the hardware effect does not have the DIEP_TYPESPECIFICPARAMS flag—then lpvTypeSpecificParams must be NULL and cbTypeSpecificParams must be zero.

DirectInput passes the GUID and the DIEFFECT structure to the device driver for verification. If the GUID is unknown, the device will return DIERR_DEVICENOTREG. If the GUID is known but the type-specific data is incorrect for that effect, the device will return DIERR_INVALIDPARAM.


Designing for Previous Versions of DirectInput

In several places, DirectInput requires you to pass a version number to a method. This parameter specifies which version of DirectX the DirectInput subsystem should emulate.

Applications designed for the latest version of DirectInput should pass the value DIRECTINPUT_VERSION as defined in Dinput.h.

Applications designed to run under previous versions should pass a value corresponding to the version of DirectInput for which they were designed, with the main version number in the high-order byte. For example, an application that was designed to run on DirectInput 3 should pass a value of 0x0300.

If you define DIRECTINPUT_VERSION as 0x0300 before including the Dinput.h header file, then the header file will generate structure definitions compatible with DirectInput 3.0.

If you do not define DIRECTINPUT_VERSION before including the Dinput.h header file, then the header file will generate structure definitions compatible with the current version of DirectInput. However, the DirectX 3–compatible structures will be available under the same names with "_DX3" appended. For example, the DirectX 3–compatible DIDEVCAPS structure is called DIDEVCAPS_DX3.


DirectInput Tutorials

This section contains four tutorials, each providing step-by-step instructions for implementing basic DirectInput functionality.

  • Tutorial 1: Using the Keyboard

    The first tutorial shows how to add DirectInput keyboard support to an existing application.

  • Tutorial 2: Using the Mouse

    The next tutorial takes you through the steps of providing DirectInput mouse support in an application. The tutorial is based on the Scrawl sample, and focuses on buffered data.

  • Tutorial 3: Using the Joystick

    This tutorial shows how to enumerate all the joysticks connected to a system, how to create and initialize DirectInputDevice objects for each of them in a callback function, and how to retrieve immediate data. Sample code is from the Space Donuts sample.

  • Tutorial 4: Using Force Feedback

    The final tutorial illustrates the creation and manipulation of a simple effect on a force-feedback joystick.


Tutorial 1: Using the Keyboard

To prepare for keyboard input, you first create an instance of a DirectInput object. Then you use the IDirectInput::CreateDevice method to create an instance of an IDirectInputDevice interface. The IDirectInputDevice interface methods are used to manipulate the device, set its behavior, and retrieve data.

The tutorial breaks down the required tasks into the following steps:

  • Step 1: Creating the DirectInput Object
  • Step 2: Creating the DirectInput Keyboard Device
  • Step 3: Setting the Keyboard Data Format
  • Step 4: Setting the Keyboard Behavior
  • Step 5: Gaining Access to the Keyboard
  • Step 6: Retrieving Data from the Keyboard
  • Step 7: Closing Down the DirectInput System

Adding DirectInput keyboard support to an application is relatively simple, so this tutorial is not accompanied by a complete sample application. All of the tutorial steps are illustrated by code within the text. The related steps for initializing the system are gathered in Sample Function 1: DI_Init. Another function, Sample Function 2: DI_Term , is called whenever the system needs to be closed down.


Step 1: Creating the DirectInput Object

The first step in setting up the DirectInput system is to create a single DirectInput object as overall manager. This is done with a call to the DirectInputCreate function.

// HINSTANCE  hinst; // initialized earlier
HRESULT        hr;
LPDIRECTINPUT  g_lpdi;

hr = DirectInputCreate(hinst, DIRECTINPUT_VERSION, &g_lpdi, NULL);
if FAILED(hr)
{
  // DirectInput not available; take appropriate action
}

The first parameter for DirectInputCreate is the instance handle to the application or DLL that is creating the object.

The second parameter tells the DirectInput object which version of the DirectInput system should be used. You can design your application to be compatible with earlier versions of DirectInput. For more information, see Designing for Previous Versions of DirectInput.

The third parameter is the address of a variable that will be initialized with a valid IDirectInput interface pointer if the call succeeds.

The last parameter specifies the address of the controlling object's IUnknown interface for use in COM aggregation. Most applications will not be using aggregation and so will pass NULL.


Step 2: Creating the DirectInput Keyboard Device

After creating the DirectInput object, your application must create the keyboard object–the device–and retrieve a pointer to an IDirectInputDevice interface. The device will perform most of the keyboard-related tasks, using the methods of the interface.

To do this your application must call the IDirectInput::CreateDevice method, as shown in Sample Function 1: DI_Init. CreateDevice accepts three parameters.

The first parameter is the GUID for the device being created. Since the system keyboard will be used, your application should pass the GUID_SysKeyboard predefined global variable.

The second parameter is the address of a variable that will be initialized with a valid IDirectInputDevice interface pointer if the call succeeds.

The third parameter specifies the address of the controlling object's IUnknown interface for use in COM aggregation. Your application will likely not use aggregation, in which case the parameter is NULL.

The following example attempts to retrieve a pointer to an IDirectInputDevice interface. If this fails, it calls the DI_Term application-defined sample function to deallocate existing DirectInput objects, if any.

Note In all the examples, g_lpdi is the initialized pointer to the DirectInput object. The method calls are in the C++ form.

HRESULT              hr;
LPDIRECTINPUTDEVICE  g_lpDIDEVICE

hr = g_lpDI->CreateDevice(GUID_SysKeyboard, &g_lpDIDevice, NULL);
if FAILED(hr)
{
    DI_Term();
    return FALSE;
}


Step 3: Setting the Keyboard Data Format

After retrieving an IDirectInputDevice pointer, your application must set the device's data format, as shown in Sample Function 1: DI_Init. For keyboards, this is a very simple task. Call the IDirectInputDevice::SetDataFormat method, specifying the data format provided for your convenience by DirectInput in the c_dfDIKeyboard global variable.

The following example attempts to set the data format. If this fails, it calls the DI_Term sample function to deallocate existing DirectInput objects, if any.

hr = g_lpDIDevice->SetDataFormat(&c_dfDIKeyboard);

if FAILED(hr){
    DI_Term();
    return FALSE;
}


Step 4: Setting the Keyboard Behavior

Before your application can gain access to the keyboard, it must set the device's behavior using the IDirectInputDevice::SetCooperativeLevel method, as shown in Sample Function 1: DI_Init. This method accepts the handle to the window to be associated with the device. DirectInput does not support exclusive access to keyboard devices, so the DISCL_NONEXCLUSIVE flag must be included in the dwFlags parameter.

The following example attempts to set the device's cooperative level. If this fails, it calls the DI_Term application-defined sample function to deallocate existing DirectInput objects, if any.

// Set the cooperative level
hr = g_lpDIDevice->SetCooperativeLevel(g_hwndMain,
                   DISCL_FOREGROUND | DISCL_NONEXCLUSIVE);

if FAILED(hr){
    DI_Term();
    return FALSE;
}


Step 5: Gaining Access to the Keyboard

After your application sets the keyboard's behavior, it can acquire access to the device by calling the IDirectInputDevice::Acquire method. The application must acquire the device before retrieving data from it. The Acquire method accepts no parameters.

The following line of code acquires the keyboard device that was created in Step 2: Creating the DirectInput Keyboard Device:

if (g_lpDIDevice) g_lpDIDevice->Acquire();


Step 6: Retrieving Data from the Keyboard

Once a device is acquired, your application can start retrieving data from it. The simplest way to do this is to call the IDirectInputDevice::GetDeviceState method, which takes a snapshot of the device's state at the time of the call.

The GetDeviceState method accepts two parameters: the size of a buffer to be filled with device state data, and a pointer to that buffer. For keyboards, always declare a buffer of 256 unsigned bytes.

The following sample attempts to retrieve the state of the keyboard. If this fails, it calls an application-defined sample function to deallocate existing DirectInput objects, if any. (See Sample Function 2: DI_Term.)

After retrieving the keyboard's current state, your application may respond to specific keys that were down at the time of the call. Each element in the buffer represents a key. If an element's high bit is on, the key was down at the moment of the call; otherwise, the key was up. To check the state of a given key, use the DirectInput Keyboard Device Constants to index the buffer for a given key.

The following skeleton function, called from the main loop of a hypothetical spaceship game, uses the IDirectInputDevice::GetDeviceState method to poll the keyboard. It then checks to see if the LEFT ARROW, RIGHT ARROW, UP ARROW or DOWN ARROW keys were pressed when the device state was retrieved. This is accomplished with the KEYDOWN macro defined in the body of the function. The macro accepts a buffer's variable name and an index value, then checks the byte at the specified index to see if the high bit is set and returns TRUE if it is.

void WINAPI ProcessKBInput()
{
    #define KEYDOWN(name,key) (name[key] & 0x80)

    char     buffer[256];
    HRESULT  hr;

    hr = g_lpDIDevice->GetDeviceState(sizeof(buffer),(LPVOID)&buffer);
    if FAILED(hr)
    {
         // If it failed, the device has probably been lost.
         // We should check for (hr == DIERR_INPUTLOST)
         // and attempt to reacquire it here.
         return;
    }

    // Turn the ship right or left
    if (KEYDOWN(buffer, DIK_RIGHT));
        // Turn right.
    else if(KEYDOWN(buffer, DIK_LEFT));
        // Turn left.

    // Thrust or stop the ship
    if (KEYDOWN(buffer, DIK_UP)) ;
        // Move the ship forward.
    else if (KEYDOWN(buffer, DIK_DOWN));
        // Stop the ship.
}


Step 7: Closing Down the DirectInput System

When an application is about to close, it should destroy all DirectInput objects. This is a three-step process:

  • Unacquire all DirectInput devices (IDirectInputDevice::Unacquire)
  • Release all DirectInput devices (IDirectInputDevice::Release)
  • Release the DirectInput object (IDirectInput::Release)

For a sample function that closes down the DirectInput system, see Sample Function 2: DI_Term.


Sample Function 1: DI_Init

This application-defined sample function creates a DirectInput object, initializes it, and retrieves the necessary interface pointers, assigning them to global variables. When initialization is complete, it acquires the device.

If any part of the initialization fails, this function calls the DI_Term application-defined sample function to deallocate DirectInput objects and interface pointers in preparation for terminating the program. (See Sample Function 2: DI_Term.)

Besides creating the DirectInput object, the DI_Init function performs the tasks discussed in the following tutorial steps:

  • Step 2: Creating the DirectInput Keyboard Device
  • Step 3: Setting the Keyboard Data Format
  • Step 4: Setting the Keyboard Behavior
  • Step 5: Gaining Access to the Keyboard

Here is the DI_Init function:

// HINSTANCE            g_hinst;    //initialized application instance
// HWND                 g_hwndMain; //initialized application window
LPDIRECTINPUT        g_lpDI;
LPDIRECTINPUTDEVICE  g_lpDIDevice;

BOOL WINAPI DI_Init()
{
    HRESULT hr;

    // Create the DirectInput object.
    hr = DirectInputCreate(g_hinst, DIRECTINPUT_VERSION,
                           &g_lpDI, NULL);
    if FAILED(hr) return FALSE;

    // Retrieve a pointer to an IDirectInputDevice interface
    hr = g_lpDI->CreateDevice(GUID_SysKeyboard, &g_lpDIDevice, NULL);
    if FAILED(hr)
    {
        DI_Term();
        return FALSE;
    }

// Now that you have an IDirectInputDevice interface, get
// it ready to use.

    // Set the data format using the predefined keyboard data
    // format provided by the DirectInput object for keyboards.
    hr = g_lpDIDevice->SetDataFormat(&c_dfDIKeyboard);
    if FAILED(hr)
    {
        DI_Term();
        return FALSE;
    }

    // Set the cooperative level
    hr = g_lpDIDevice->SetCooperativeLevel(g_hwndMain,
                       DISCL_FOREGROUND | DISCL_NONEXCLUSIVE);
    if FAILED(hr)
    {
        DI_Term();
        return FALSE;
    }

    // Get access to the input device.
    hr = g_lpDIDevice->Acquire();
    if FAILED(hr)
    {
        DI_Term();
        return FALSE;
    }

    return TRUE;
}


Sample Function 2: DI_Term

This application-defined sample function deallocates existing DirectInput interface pointers in preparation for program shutdown or in the event of a failure to properly initialize a device.

//  LPDIRECTINPUT        g_lpDI;
//  LPDIRECTINPUTDEVICE  g_lpDIDevice;

void WINAPI DI_Term()
{
    if (g_lpDI)
    {
        if (g_lpDIDevice)
        {
            /*
  • Always unacquire the device before calling Release().
             */
             g_lpDIDevice->Unacquire();
             g_lpDIDevice->Release();
             g_lpDIDevice = NULL;
        }
        g_lpDI->Release();
        g_lpDI = NULL;
    }
}


Tutorial 2: Using the Mouse

This tutorial guides you through the process of setting up a mouse device and retrieving buffered input data. The examples are taken from the Scrawl sample.

To prepare for mouse input, you first create an instance of a DirectInput object. Then you use the IDirectInput::CreateDevice method to create an instance of an IDirectInputDevice interface. The IDirectInputDevice interface methods are used to manipulate the device, set its behavior, and retrieve data.

The preliminary step of setting up the DirectInput system and the final step of closing it down are the same for any application and are covered in Tutorial 1: Using the Keyboard.

This tutorial breaks down the required tasks into the following steps:

  • Step 1: Creating the DirectInput Mouse Device
  • Step 2: Setting the Mouse Data Format
  • Step 3: Setting the Mouse Behavior
  • Step 4: Preparing for Buffered Input from the Mouse
  • Step 5: Managing Access to the Mouse
  • Step 6: Retrieving Buffered Data from the Mouse

Note When an application acquires the mouse at the exclusive cooperative level, Windows does not show a mouse pointer on the screen. For this, your application needs a simple sprite engine. The Scrawl sample application uses the Win32 function DrawIcon to display a crosshair cursor.


Step 1: Creating the DirectInput Mouse Device

After creating the DirectInput object, your application should retrieve a pointer to an IDirectInputDevice interface, which will be used to perform most mouse-related tasks. To do this, call the IDirectInput::CreateDevice method.

The CreateDevice method accepts three parameters.

The first parameter is the globally unique identifier (GUID) for the device your application is creating. In this case, since the system mouse will be used, your application should pass the predefined global variable GUID_SysMouse.

The second parameter is the address of a variable that will be initialized with a valid IDirectInputDevice interface pointer if the call succeeds.

The third parameter specifies the address of the controlling object's IUnknown interface for use in COM aggregation. Your application probably won't be using aggregation, in which case the parameter will be NULL.

The following sample from Scrawl.cpp attempts to retrieve a pointer to an IDirectInputDevice interface. If the call fails, an error message is displayed and FALSE is returned.

// LPDIRECTINPUT    g_pdi;    // This has been initialized
LPDIRECTINPUTDEVICE g_pMouse;
HRESULT             hr;

hr = g_pdi->CreateDevice(GUID_SysMouse, &g_pMouse, NULL);

if (FAILED(hr)) {
    Complain(hwnd, hr, "CreateDevice(SysMouse)");
    return FALSE;
}


Step 2: Setting the Mouse Data Format

After retrieving an IDirectInputDevice pointer, your application must set the device's data format. For mouse devices, this is a very simple task. Call the IDirectInputDevice::SetDataFormat method, specifying the data format provided for your convenience by DirectInput in the c_dfDIMouse global variable.

The following code attempts to set the device's data format. If the call fails, an error message is displayed and FALSE is returned.

hr = g_pMouse->SetDataFormat(&c_dfDIMouse);

if (FAILED(hr)) {
    Complain(hwnd, hr, "SetDataFormat(SysMouse, dfDIMouse)");
    return FALSE;
}


Step 3: Setting the Mouse Behavior

Before it can gain access to the mouse, your application must set the mouse device's behavior using the IDirectInputDevice::SetCooperativeLevel method. This method accepts the handle to the window to be associated with the device. In Scrawl, the DISCL_EXCLUSIVE flag is included to ensure that this application is the only one that can have exclusive access to the device. This flag is combined with DISCL_FOREGROUND because Scrawl is not interested in what the mouse is doing when another application is in the foreground.

The following code from Scrawl.cpp attempts to set the device's cooperative level. If this attempt fails, an error message is displayed and FALSE is returned.

hr = g_pMouse->SetCooperativeLevel(hwnd,
               DISCL_EXCLUSIVE | DISCL_FOREGROUND);

if (FAILED(hr)) {
    Complain(hwnd, hr, "SetCooperativeLevel(SysMouse)");
    return FALSE;
}


Step 4: Preparing for Buffered Input from the Mouse

The Scrawl application demonstrates how to use event notification to find out about mouse activity, and how to read buffered input from the mouse. Both these techniques require some setup. You can perform these steps at any time after creating the mouse device and before acquiring it.

First, create an event and associate it with the mouse device. You are instructing DirectInput to notify the mouse device object whenever a hardware interrupt indicates that new data is available.

This is how it's done in Scrawl. As usual, the Complain sample function informs the user of any errors.

// HANDLE  g_hevtMouse;   // This is global

g_hevtMouse = CreateEvent(0, 0, 0, 0);

if (g_hevtMouse == NULL) {
    Complain(hwnd, GetLastError(), "CreateEvent");
    return FALSE;
}

hr = g_pMouse->SetEventNotification(g_hevtMouse);

if (FAILED(hr)) {
    Complain(hwnd, hr, "SetEventNotification(SysMouse)");
    return FALSE;
}

Now you need to set the buffer size so that DirectInput can store any input data until you're ready to look at it. Remember, by default the buffer size is zero, so this step is essential if you want to use buffered data.

It's not necessary to used buffered data with event notification; if you prefer, you can retrieve immediate data when an event is signaled.

To set the buffer size you need to initialize a DIPROPDWORD structure with information about itself and about the property you wish to set. Most of the values are boilerplate; the key value is the last one, dwData, which is initialized with the number of items you want the buffer to hold.

#define DINPUT_BUFFERSIZE  16

DIPROPDWORD dipdw =
    {
        // the header
        {
            sizeof(DIPROPDWORD),        // diph.dwSize
            sizeof(DIPROPHEADER),       // diph.dwHeaderSize
            0,                          // diph.dwObj
            DIPH_DEVICE,                // diph.dwHow
        },
        // the data
        DINPUT_BUFFERSIZE,              // dwData
    };

You then pass the address of the header (the DIPROPHEADER structure within the DIPROPDWORD structure), along with the identifier of the property you want to change, to the IDirectInputDevice::SetProperty method, as follows:

hr = g_pMouse->SetProperty(DIPROP_BUFFERSIZE, &dipdw.diph);

if (FAILED(hr)) {
    Complain(hwnd, hr, "Set buffer size(SysMouse)");
    return FALSE;
 }

The setup is now complete, and you're ready to acquire the mouse and start collecting data.


Step 5: Managing Access to the Mouse

DirectInput provides the IDirectInputDevice::Acquire and IDirectInputDevice::Unacquire methods to manage device access. Your application must call the Acquire method to gain access to the device before requesting mouse information with the IDirectInputDevice::GetDeviceState and IDirectInputDevice::GetDeviceData methods.

Most of the time your application will have the device acquired. However, if you have only foreground access the mouse will automatically be unacquired whenever your application moves to the background. You are responsible for reacquiring it when you get the focus back again. This can be done in response to a WM_ACTIVATE message.

Scrawl handles this message by setting a global variable, g_fActive, according to whether the application is gaining or losing the focus. It then calls a helper function, Scrawl_SyncAcquire, which acquires the mouse if g_fActive is TRUE and unacquires it otherwise.

case WM_ACTIVATE:
        g_fActive = wParam == WA_ACTIVE || wParam == WA_CLICKACTIVE;
        Scrawl_SyncAcquire(hwnd);
        break;

If you have exclusive access, your application may need to let go of the mouse to let the user interact with Windows—for example, to access a menu or a dialog box. In Scrawl this can happen when the user opens the system menu with ALT+SPACEBAR.

The Scrawl window procedure has a handler for WM_ENTERMENULOOP that responds by setting the global variable g_fActive to FALSE and calling the Scrawl_SyncAcquire function. This handler allows Windows to have the mouse and display its own cursor.

When the user is done using a menu, Windows sends the application a WM_EXITMENULOOP message. In this case, the Scrawl window process posts an application-defined message, WM_SYNCACQUIRE, to its own message queue. This allows other pending messages to be processed before the mouse is reacquired with the Scrawl_SyncAcquire function.

Scrawl also unacquires the mouse in response to a right button click, which opens up a context menu. Although the mouse would get unacquired later, in the WM_ENTERMENULOOP handler, it's done here first so that the position of the Windows cursor can be set before the menu appears.

Finally, Scrawl tries to reacquire the mouse if it receives a DIERR_INPUTLOST error after an attempt to retrieve data. This is just in case the device has been unacquired by some mechanism not covered elsewhere; for instance, if the user has pressed CTRL+ALT+DEL.

In summary, your application needs to acquire the mouse before it can get data from it. This needs to be done only once, as long as nothing happens to force your application to give up access to it. In exclusive mode, you are responsible for giving up control of the mouse when Windows needs it. You are also responsible for reacquiring the mouse whenever your program needs access to it after losing it to Windows or another application.


Step 6: Retrieving Buffered Data from the Mouse

Once the mouse is acquired, your application can begin to retrieve data from it.

In the Scrawl sample, retrieval is triggered by a signaled event. In the WinMain function, the application sleeps until MsgWaitForMultipleObjects indicates that there is either a signal or a message. If there's a signal associated with the mouse, the Scrawl_OnMouseInput function is called. This function is a good illustration of how buffered input is handled, so we'll look at it in detail.

First the function makes sure the old cursor position will be cleaned up. Remember, Scrawl is maintaining its own cursor and is wholly responsible for drawing and erasing it.

void Scrawl_OnMouseInput(HWND hwnd)
{
    /* Invalidate the old cursor so it will be erased */
    InvalidateCursorRect(hwnd);

Now the function enters a loop to read and respond to the entire contents of the buffer. Because it retrieves just one item at a time, it needs only a single DIDEVICEOBJECTDATA structure to hold the data.

Another way to go about handling input would be to read the entire buffer at once and then loop through the retrieved items, responding to each one in turn. In that case, dwElements would be the size of the buffer, and od would be an array with the same number of elements.

    while (!fDone) {
        DIDEVICEOBJECTDATA od;
        DWORD dwElements = 1;   // number of items to be retrieved

The application calls the IDirectInputDevice::GetDeviceData method in order to fetch the data. The second parameter tells DirectInput where to put the data, and the third tells it how many items are wanted. The final parameter would be DIGDD_PEEK if the data was to be left in the buffer, but in this case the data is not going to be needed again, so it is removed.

        HRESULT hr = g_pMouse->GetDeviceData(
                             sizeof(DIDEVICEOBJECTDATA),
                             &od,
                             &dwElements, 0);

Now the application checks to see if access to the device has been lost and, if so, tells itself to try to reacquire the mouse at the first opportunity. This step was discussed in Step 5: Managing Access to the Mouse.

        if (hr == DIERR_INPUTLOST) {
            PostMessage(hwnd, WM_SYNCACQUIRE, 0, 0L);
            break;
        }

Next the application makes sure the call to the GetDeviceData method succeeded and that there was actually data to be retrieved. Remember, after the call to GetDeviceData the dwElements variable shows how many items were actually retrieved.

        /* Unable to read data or no data available */
        if (FAILED(hr) || dwElements == 0) {
            break;
        }

If execution has proceeded to this point, everything is fine: the call succeeded and there is an item of data in the buffer. Now the application looks at the dwOfs member of the DIDEVICEOBJECTDATA structure to determine which object on the device reported a change of state, and calls helper functions to respond appropriately. The value of the dwData member, which gives information about what happened, is passed to these functions.

        /* Look at the element to see what happened */

        switch (od.dwOfs) {

        /* DIMOFS_X: Mouse horizontal motion */
        case DIMOFS_X: UpdateCursorPosition(od.dwData, 0); break;

        /* DIMOFS_Y: Mouse vertical motion */
        case DIMOFS_Y: UpdateCursorPosition(0, od.dwData); break;

        /* DIMOFS_BUTTON0: Button 0 pressed or released */
        case DIMOFS_BUTTON0:

            if (od.dwData & 0x80) { /* Button pressed */
                fDone = 1;
                Scrawl_OnButton0Down(hwnd); /* Go into button-down
                                               mode */
            }
            break;

        /* DIMOFS_BUTTON1: Button 1 pressed or released */
        case DIMOFS_BUTTON1:

            if (!(od.dwData & 0x80)) {    /* Button released */
                fDone = 1;
                Scrawl_OnButton1Up(hwnd); /* Context menu time */
            }
        }

    }

Finally, the Scrawl_OnMouseInput sample function invalidates the screen rectangle occupied by the cursor, in case the cursor has been moved by one of the helper functions.

    /* Invalidate the new cursor so it will be drawn */
    InvalidateCursorRect(hwnd);
}

Scrawl also collects mouse data in the Scrawl_OnButton0Down function. This is where the application keeps track of mouse movements while the primary button is being held down — that is, while the user is drawing. This function does not rely on event notification, but repeatedly polls the DirectInput buffer until the button is released.

A key point to note in the Scrawl_OnButton0Down function is that no actual drawing is done until all pending data has been read. The reason is that each horizontal or vertical movement of the mouse is reported as a separate event. (Both events are, however, placed in the buffer at the same time.) If a line were immediately drawn in response to each separate axis movement, a diagonal movement of the mouse would produce two lines at right angles.

Another way you can be sure that the movement in both axes is taken into account before responding in your application is to check the sequence numbers of the x-axis item and the y-axis item. If the numbers are the same, the two events took place simultaneously. For more information, see Time Stamps and Sequence Numbers.


Tutorial 3: Using the Joystick

This tutorial shows you how to enumerate joysticks on a system and set up two or more joysticks for input. Code samples are based on the Space Donuts sample. The method calls are in the C form.

The preliminary step of setting up the DirectInput system and the final step of closing it down are the same for any application and are covered in Tutorial 1: Using the Keyboard.

The first step in the tutorial is to enumerate devices; that is, to see what joysticks are available. As part of this process you initialize each joystick device and set its desired characteristics. You then use the IDirectInputDevice interface methods to retrieve data from each joystick.

The tutorial breaks down the required tasks into the following steps:

  • Step 1: Enumerating the Joysticks
  • Step 2: Creating the DirectInput Joystick Device
  • Step 3: Setting the Joystick Data Format
  • Step 4: Setting the Joystick Behavior
  • Step 5: Gaining Access to the Joystick
  • Step 6: Retrieving Data from the Joystick


Step 1: Enumerating the Joysticks

After creating the DirectInput system, call the IDirectInput::EnumDevices method to enumerate the joysticks. The following code from Input.c in the Space Donuts source directory accomplishes this.

//  LPDIRECTINPUT  pdi;  // previously initialized

pdi->lpVtbl->EnumDevices(pdi, DIDEVTYPE_JOYSTICK,
                         InitJoystickInput, pdi, DIEDFL_ATTACHEDONLY);

The method call is in the C form. Note that you could use the IDirectInput_EnumDevices macro to simplify the call. All DirectInput methods have corresponding macros defined in Dinput.h that expand to the appropriate C or C++ syntax.

The DIDEVTYPE_JOYSTICK constant, passed as the second parameter, specifies the type of device to be enumerated.

InitJoystickInput is the address of a callback function to be called each time a joystick is found; this is where the individual devices will be initialized in the following steps of the tutorial.

The fourth parameter can be any 32-bit value that you want to make available to the callback function. In this case it's a pointer to the DirectInput interface, which the callback function needs to know so it can call the IDirectInput::CreateDevice method.

The last parameter, DIEDFL_ATTACHEDONLY, is a flag that restricts enumeration to devices that are attached to the computer.


Step 2: Creating the DirectInput Joystick Device

After creating the DirectInput object, the application must retrieve a pointer to an IDirectInputDevice interface, which will be used to perform most joystick-related tasks. In the Space Donuts sample, this is done in the callback function InitJoystickInput, which is called each time a joystick is enumerated.

Here is the first part of the callback function:

BOOL FAR PASCAL InitJoystickInput(LPCDIDEVICEINSTANCE pdinst,
                                  LPVOID pvRef)
{
   LPDIRECTINPUT pdi = pvRef;
   LPDIRECTINPUTDEVICE pdev;

   // create the DirectInput joystick device
   if (pdi->lpVtbl->CreateDevice(pdi, &pdinst->guidInstance,
                                 &pdev, NULL) != DI_OK)
   {
      OutputDebugString("IDirectInput::CreateDevice FAILED\n");
      return DIENUM_CONTINUE;
   }

The parameters to the callback function InitJoystickInput are:

  • A pointer to the device instance, supplied by the DirectInput system when the device is enumerated.
  • A pointer to the DirectInput interface, which you supplied as an parameter to IDirectInput::EnumDevices. This parameter could have been any 32-bit value but in this case you want the DirectInput interface so that you can call the IDirectInput::CreateDevice method.

The InitJoystickInput sample function declares a local pointer to the DirectInput object, pdi, and assigns it the value passed into the callback. It also declares a local pointer to a DirectInput device, pdev, which is initialized when the device is created. This device starts life as an instance of the IDirectInputDevice interface, but when it is added to the application's list of input devices it is converted to an IDirectInputDevice2 object so that it can use the IDirectInputDevice2::Poll method.

The first task of the callback function, then, is to create the device. The IDirectInput::CreateDevice method accepts four parameters.

The first, unnecessary in C++, is a this pointer to the calling DirectInput interface.

The second parameter is a reference to the globally unique identifier (GUID) for the instance of the device. In this case, the GUID is taken from the DIDEVICEINSTANCE structure supplied by DirectInput when it enumerated the device.

The third parameter is the address of the variable that will be initialized with a valid IDirectInputDevice interface pointer if the call succeeds.

The fourth parameter specifies the address of the controlling object's IUnknown interface for use in COM aggregation. Space Donuts doesn't use aggregation, so the parameter is NULL.

Note that if for some reason the device interface cannot be created, DIENUM_CONTINUE is returned from the callback function. This flag instructs DirectInput to keep enumerating as long as there are devices to be enumerated.


Step 3: Setting the Joystick Data Format

Now that the application has a pointer to a DirectInput device, it can call the IDirectInputDevice methods to manipulate that device. The first step, which is an essential one, is to set the data format for the joystick. This step tells DirectInput how to format the input data.

The Space Donuts sample performs this action inside the callback function introduced in the previous step.

   if (pdev->lpVtbl->SetDataFormat(pdev, &c_dfDIJoystick) != DI_OK)
   {
      OutputDebugString("IDirectInputDevice::SetDataFormat FAILED\n");
      pdev->lpVtbl->Release(pdev);
      return DIENUM_CONTINUE;
   }

The pdev variable is a pointer to the device interface created by IDirectInput::CreateDevice.

The IDirectInputDevice::SetDataFormat method takes two parameters. The first is a this pointer to the calling instance of the interface and is unnecessary in C++. The second is a pointer to a DIDATAFORMAT structure containing information about how the data for the device is to be formatted. For the joystick, the predefined global variable c_dfDIJoystick can be used here.

As in the previous step, the callback function returns DIENUM_CONTINUE if it fails to initialize the device. This flag instructs DirectInput to keep enumerating as long as there are devices to be enumerated.


Step 4: Setting the Joystick Behavior

The joystick device has been created, and its data format has been set. The next step is to set its cooperative level. In the Space Donuts sample, this is done in the callback function called when the device is enumerated. As in the previous step, pdev is a pointer to the device interface.

   if(pdev->lpVtbl->SetCooperativeLevel(pdev, hWndMain,
      DISCL_NONEXCLUSIVE | DISCL_FOREGROUND) != DI_OK)
   {
      OutputDebugString("IDirectInputDevice::SetCooperativeLevel
                         FAILED\n");
      pdev->lpVtbl->Release(pdev);
      return DIENUM_CONTINUE;
   }

Once again, the first parameter to IDirectInputDevice::SetCooperativeLevel is a this pointer.

The second parameter is a window handle. In this case the handle to the main program window is passed in.

The final parameter is a combination of flags describing the desired cooperative level. Space Donuts requires input from the joystick only when it is the foreground application, and does not care whether another program is using the joystick in exclusive mode, so the flags are set to DISCL_NONEXCLUSIVE | DISCL_FOREGROUND. (See Cooperative Levels for a full explanation of these flags.)

The final step carried out for each joystick enumerated in the callback function is to set the properties of the device. In the sample, the properties changed include the range and the dead zone for both the x-axis and y-axis.

By setting the range, you are telling DirectInput what maximum and minimum values you want returned for an axis. If you set a range of -1,000 to +1,000 for the x-axis, as in the example, you are asking that a value of -1,000 be returned when the stick is at the extreme left, +1,000 when it is at the extreme right, and zero when it is in the middle.

The dead zone is a region of tolerance in the middle of the axis, measured in ten-thousandths of the physical range of axis travel. If you set a dead zone of 1,000 for the x-axis, you are saying that the stick can travel one-tenth of its range to the left or right of center before a non-center value will be returned. For more information on the dead zone, see Interpreting Joystick Axis Data.

Here's the code to set the range of the x-axis:

   DIPROPRANGE diprg;

   diprg.diph.dwSize       = sizeof(diprg);
   diprg.diph.dwHeaderSize = sizeof(diprg.diph);
   diprg.diph.dwObj        = DIJOFS_X;
   diprg.diph.dwHow        = DIPH_BYOFFSET;
   diprg.lMin              = -1000;
   diprg.lMax              = +1000;

   if FAILED(pdev->lpVtbl->SetProperty(pdev,
                   DIPROP_RANGE, &diprg.diph))
   {
      OutputDebugString("IDirectInputDevice::SetProperty(DIPH_RANGE)
                         FAILED\n");
      pdev->lpVtbl->Release(pdev);
      return FALSE;
   }

The first task here is to set up the DIPROPRANGE structure diprg, whose address will be passed into the IDirectInputDevice::SetProperty method. Actually, it's not the address of the structure itself that is passed but rather the address of its first member, which is a DIPROPHEADER structure. For more information,see Device Properties.

The property header is initialized with the following values:

  • The size of the property structure
  • The size of the header structure
  • The value returned by the DIJOFS_X joystick device constant macro, which points to the object whose property is being changed
  • A flag to indicate how the third parameter is to be interpreted

The lmin and lmax members of the DIPROPRANGE structure are assigned the desired range values.

The application now calls the IDirectInputDevice::SetProperty method. As usual, the first parameter is a this pointer. The second parameter is a flag indicating which property is being changed. The third parameter is the address of the DIPROPHEADER member of the property structure.

Setting the dead zone of the x-axis requires a similar procedure. The Space Donuts sample uses a helper function, SetDIDwordProperty, to initialize a DIPROPDWORD property structure. Unlike DIPROPRANGE, this structure contains only one data member, which in the example is set to 5,000, indicating that the stick must move half of its range from the center before the axis is reported to be off-center.

   // set X axis dead zone to 50% (to avoid accidental turning)
   if FAILED(SetDIDwordProperty(pdev, DIPROP_DEADZONE, DIJOFS_X,
                                DIPH_BYOFFSET, 5000))
   {
      OutputDebugString("IDirectInputDevice::
                           SetProperty(DIPH_DEADZONE) FAILED\n");
      pdev->lpVtbl->Release(pdev);
      return FALSE;
   }


Step 5: Gaining Access to the Joystick

After your application sets a joystick's behavior, it can acquire access to the device by calling the IDirectInputDevice::Acquire method. The application must acquire the device before retrieving data from it. The Acquire method accepts no parameters.

The Space Donuts application takes care of acquisition in the ReacquireInput function. This function does double duty, serving both to acquire the device on startup and to reacquire it if for some reason a DIERR_INPUTLOST error is returned when the application tries to get input data.

In the following code, g_pdevCurrent is a global pointer to whatever DirectInput device is currently in use.

BOOL ReacquireInput(void)
{
    HRESULT hRes;

    // if we have a current device
    if (g_pdevCurrent)
    {
        // acquire the device
        hRes = IDirectInputDevice_Acquire(g_pdevCurrent);
        // The call above is a macro that expands to:
        // g_pdevCurrent->lpVtbl->Acquire(g_pdevCurrent);

        if (SUCCEEDED(hRes))
        {
            // acquisition successful
            return TRUE;
        }
        else
        {
            // acquisition failed
            return FALSE;
        }
    }
    else
    {
        // we don't have a current device
        return FALSE;
    }
}

In this example, acquisition is effected by a call to IDirectInputDevice_Acquire, a macro defined in Dinput.h that simplifies the C call to the IDirectInputDevice::Acquire method.


Step 6: Retrieving Data from the Joystick

Since your application is more likely concerned with the position of the joystick axes than with their movement, you will probably want to retrieve immediate rather than buffered data from the device. You can do this by polling with IDirectInputDevice::GetDeviceState. Remember, not all device drivers will notify DirectInput when the state of the device changes, so it's always good policy to call the IDirectInputDevice2::Poll method before checking the device state.

The Space Donuts application calls the following function on each pass through the rendering loop, provided the joystick is the active input device.

DWORD ReadJoystickInput(void)
{
    DWORD                   dwKeyState;
    HRESULT                 hRes;
    DIJOYSTATE              js;

    // poll the joystick to read the current state
    hRes = IDirectInputDevice2_Poll(g_pdevCurrent);

    // get data from the joystick
    hRes = IDirectInputDevice_GetDeviceState(g_pdevCurrent,
                                            sizeof(DIJOYSTATE), &js);

    if (hRes != DI_OK)
    {
        // did the read fail because we lost input for some reason?
        // if so, then attempt to reacquire. If the second acquire
        // fails, then the error from GetDeviceData will be
        // DIERR_NOTACQUIRED, so we won't get stuck an infinite loop.
        if(hRes == DIERR_INPUTLOST)
            ReacquireInput();

        // return the fact that we did not read any data
        return 0;
    }

    // Now study the position of the stick and the buttons.

    dwKeyState = 0;
    if (js.lX < 0) {
        dwKeyState |= KEY_LEFT;
    } else if (js.lX > 0) {
        dwKeyState |= KEY_RIGHT;
    }

    if (js.lY < 0) {
        dwKeyState |= KEY_UP;
    } else if (js.lY > 0) {
          dwKeyState |= KEY_DOWN;
   }

    if (js.rgbButtons[0] & 0x80) {
        dwKeyState |= KEY_FIRE;
    }

    if (js.rgbButtons[1] & 0x80) {
        dwKeyState |= KEY_SHIELD;
    }

    if (js.rgbButtons[2] & 0x80) {
        dwKeyState |= KEY_STOP;
    }

    return dwKeyState;
}

Note the calls to IDirectInputDevice2_Poll and IDirectInputDevice_GetDeviceState. These are macros that expand to C calls to the corresponding methods, similar to the macro in the previous step of this tutorial. The parameters to the macro are the same as those you would pass to the method. Here is what the call to GetDeviceState looks like:

    hRes = IDirectInputDevice_GetDeviceState(g_pdevCurrent,
                                             sizeof(DIJOYSTATE), &js);

The first parameter is the this pointer; that is, a pointer to the calling object. The second parameter is the size of the structure in which the data will be returned, and the last parameter is the address of this structure, which is of type DIJOYSTATE. This structure holds data for up to six axes, 32 buttons, and a point-of-view hat. The sample program looks at the state of two axes and three buttons.

If the position of an axis is reported as nonzero, that axis is outside the dead zone, and the function responds by setting the dwKeyState variable appropriately. This variable holds the current set of user commands as entered with either the keyboard or the joystick. For example, if the x-axis of the stick is greater than zero, that is considered the same as the RIGHT ARROW key being down.

Joystick buttons work just like keys or mouse buttons: if the high bit of the returned byte is set, the button is down.


Tutorial 4: Using Force Feedback

This tutorial takes you through the process of creating, playing, and modifying a simple effect on a force-feedback joystick. The effect is something like a balky chain saw that you're trying to get started. The sample code uses C++ syntax.

The preliminary step of setting up the DirectInput system and the final step of closing it down are essentially the same for any application and are covered in Tutorial 1: Using the Keyboard. However, when closing down the DirectInput force-feedback system you must take the additional step of releasing any effects you have created.

The tutorial breaks down the required tasks into the following steps:

  • Step 1: Enumerating Force Feedback Devices
  • Step 2: Creating the DirectInput Force Feedback Device
  • Step 3: Enumerating Supported Effects
  • Step 4: Creating an Effect
  • Step 5: Playing an Effect
  • Step 6: Changing an Effect


Step 1: Enumerating Force Feedback Devices

The first step is to ensure that a force-feedback device is available on the system. You do this by calling the IDirectInput::EnumDevices method. In the following example, the global pointer to the game device interface is initialized only if the enumeration has succeeded in finding at least one suitable device:

LPDIRECTINPUTDEVICE2  g_lpdid2Game = NULL;

lpdi->EnumDevices(DIDEVTYPE_JOYSTICK,
                  DIEnumDevicesProc,
                  NULL,
                  DIEDFL_FORCEFEEDBACK | DIEDFL_ATTACHEDONLY);
if (g_lpdid2Game == NULL)
  {
  // no force-feedback joystick available; take appropriate action
  }

In the example, lpdi is an initialized pointer to the IDirectInput interface. The first parameter to EnumDevices restricts the enumeration to joystick-type devices. The second parameter is the callback function that's going to be called each time DirectInput identifies a device that qualifies for enumeration. The third parameter is for user-defined data to be passed in or out of the callback function; in this case it's not used. Finally, the flags restrict the enumeration further to devices actually attached to the system that support force feedback.

The callback function is a convenient place to initialize the device as soon as it has been found. (It's assumed that the first device found is the one you want to use.) You'll do this in Step 2: Creating the DirectInput Force Feedback Device.


Step 2: Creating the DirectInput Force Feedback Device

In order to have DirectInput enumerate devices, you must create a callback function of the same type as DIEnumDevicesProc. In Step 1 you passed the address of this function to the IDirectInput::EnumDevices method.

DirectInput passes into the callback, as the first parameter, a pointer to a DIDEVICEINSTANCE structure that tells you what you need to know about the device. The structure member of chief interest in the example is guidInstance, the unique identifier for the particular piece of hardware on the user's system. You will need to pass this GUID to the IDirectInput::CreateDevice method.

Here's the first part of the callback, which extracts the GUID and creates the device object:

BOOL CALLBACK DIEnumDevicesProc(LPCDIDEVICEINSTANCE lpddi,
                                LPVOID pvRef)
  {
  HRESULT hr1, hr2;
  LPDIRECTINPUTDEVICE lpdidGame;
  GUID DeviceGuid = lpddi->guidInstance;

  // create game device

  hr1 = lpdi->CreateDevice(DeviceGuid, &lpdidGame, NULL);

Note that the pointer to the IDirectInputDevice object, lpdidGame, is a local variable. You're not going to keep it, because in order to create force-feedback effects you need to obtain a pointer to the IDirectInputDevice2 interface, as follows:

  if (SUCCEEDED(hr1))
    {
    hr2 = lpdidGame->QueryInterface(IID_IDirectInputDevice2,
                                   (void **) &g_lpdid2Game);
    lpdidGame->Release();
    }
  else
    {
    OutputDebugString("Failed to create device.\n");
    return DIENUM_STOP;
    }
  if (FAILED(hr2))
    {
    OutputDebugString("Failed to obtain interface.\n");
    return DIENUM_STOP;
    }

The next steps, still within the callback function, are similar to those for setting up any input device. Note that you need the exclusive cooperative level for any force-feedback device. Since the joystick will be used for input as well as force feedback, you also need to set the data format.

  // set cooperative level
  if (FAILED(g_lpdid2Game->SetCooperativeLevel(hMainWindow,
         DISCL_EXCLUSIVE | DISCL_FOREGROUND)))
    {
    OutputDebugString(
      "Failed to set cooperative level.\n");
    lpdid2Game->Release();
    lpdi2Game = NULL;
    return DIENUM_STOP;
    }

  // set game data format
  if (FAILED(g_lpdid2Game->SetDataFormat(&c_dfDIJoystick)))
    {
    OutputDebugString("Failed to set game device data format.\n");
    lpdid2Game->Release();
    lpdid2Game = NULL;
    return DIENUM_STOP;
    }

Finally. you may want to turn off the device's autocenter feature. Autocenter is essentially a condition effect that uses the motors to simulate the springs in a standard joystick. Turning it off gives you more control over the device.

  DIPROPDWORD DIPropAutoCenter;

  DIPropAutoCenter.diph.dwSize = sizeof(DIPropAutoCenter);
  DIPropAutoCenter.diph.dwHeaderSize = sizeof(DIPROPHEADER);
  DIPropAutoCenter.diph.dwObj = 0;
  DIPropAutoCenter.diph.dwHow = DIPH_DEVICE;
  DIPropAutoCenter.dwData = 0;

  if (FAILED(lpdid2Game->SetProperty(DIPROP_AUTOCENTER,
                                       &DIPropAutoCenter.diph)))
    {
    OutputDebugString("Failed to change device property.\n");
    }

  return DIENUM_STOP;   // One is enough.
  } // end DIEnumDevicesProc

Before using the device, you must acquire it. See Step 5: Gaining Access to the Joystick in the previous tutorial for an example of how to handle acquisition.


Step 3: Enumerating Supported Effects

Now that you've successfully enumerated and created a force-feedback device, you can enumerate the effect types it supports.

Effect enumeration is not strictly necessary if you want to create only standard effects that will be available on any device, such as constant forces. When creating the effect object, you can identify the desired effect type simply by using one of the predefined GUIDs, such as GUID_ConstantForce. (For a complete list of these identifiers, see IDirectInputDevice2::CreateEffect.)

Another, more flexible approach is to enumerate supported effects of a particular type, and obtain the GUID for the effect from the callback function. This is the approach taken in the FFDonuts sample, and you'll adopt it here as well. You could, of course, use the callback to obtain more information about the device's support for the effect— for example, whether it supports an envelope—but in this tutorial you'll get only the effect GUID.

First, create the callback function that will be called by DirectInput for each effect enumerated. For information on this standard callback, see DIEnumEffectsProc. You can give the function any name you like.

BOOL  EffectFound = FALSE;  // global flag

BOOL CALLBACK DIEnumEffectsProc(LPCDIEFFECTINFO pei, LPVOID pv)
  {
  *((GUID *)pv) = pei->guid;
  EffectFound = TRUE;
  return DIENUM_STOP;  // one is enough
  }

The GUID variable pointed to by the application-defined value pv is assigned the value passed in the DIEFFECTINFO structure created by DirectInput for the effect.

In order to obtain the effect GUID, you set the callback in motion by calling the IDirectInputDevice2::EnumEffects method, as follows:

HRESULT  hr;
GUID     guidEffect;

hr = g_lpdid2Game->EnumEffects(
     (LPDIENUMEFFECTSCALLBACK) DIEnumEffectsProc,
     &guidEffect,
     DIEFT_PERIODIC);
if (FAILED(hr))
  {
  OutputDebugString("Effect enumeration failed\n");
  // Note: success doesn't mean any effects were found,
  // only that the process went smoothly.
  }

Note that you pass the address of a GUID variable, guidEffect, to the EnumEffects method. This address is passed in turn to the callback as the pv parameter. You also restrict the enumeration to periodic effects by setting the flag DIEFT_PERIODIC.


Step 4: Creating an Effect

If the EffectFound flag is no longer FALSE after effect enumeration, you can safely assume that DirectInput has found support for at least one effect of the type you requested. (Of course, in real life you would probably not be content with finding just any periodic effect; you would want to use a particular kind such as a sine or sawtooth.) Armed with the effect GUID, you can now create the effect object.

Before calling the IDirectInputDevice2::CreateEffect method, you need to set up the following arrays and structures:

  • An array of axes that will be involved in the effect. For a joystick this array will normally consist of the identifiers for the x-axis and the y-axis.
  • An array of values for setting the direction. The values will differ according to the number of axes, and according to whether you want to use polar, spherical, or Cartesian coordinates. For a full explanation of this rather complicated business, see Effect Direction.
  • A structure of type-specific parameters. In the example, since you are creating a periodic effect, this will be of type DIPERIODIC.
  • A DIENVELOPE structure for defining the envelope to be applied to the effect.
  • Finally, a DIEFFECT structure to contain the basic parameters for the effect.

First, declare the arrays and structures. You can initialize the arrays at the same time:

DWORD      dwAxes[2] = { DIJOFS_X, DIJOFS_Y };
LONG       lDirection[2] = { 0, 0 };

DIPERIODIC diPeriodic;      // type-specific parameters
DIENVELOPE diEnvelope;      // envelope
DIEFFECT   diEffect;        // general parameters

Now initialize the type-specific parameters. If you use the values in the example, you will create a full-force periodic effect with a period of one-twentieth of a second.

diPeriodic.dwMagnitude = DI_FFNOMINALMAX;
diPeriodic.lOffset = 0;
diPeriodic.dwPhase = 0;
diPeriodic.dwPeriod = (DWORD) (0.05 * DI_SECONDS);

To get the effect of the chain-saw motor trying to start, briefly coughing into life, and then slowly dying, you will set an envelope with an attack time of half a second and a fade time of one second. You'll get to the sustain value in a moment.

diEnvelope.dwSize = sizeof(DIENVELOPE);
diEnvelope.dwAttackLevel = 0;
diEnvelope.dwAttackTime = (DWORD) (0.5 * DI_SECONDS);
diEnvelope.dwFadeLevel = 0;
diEnvelope.dwFadeTime = (DWORD) (1.0 * DI_SECONDS);

Now you set up the basic effect parameters. These include flags to determine how the directions and device objects (buttons and axes) are identified, the sample period and gain for the effect, and pointers to the other data that you have just prepared. You also associate the effect with the fire button of the joystick, so that it will automatically be played whenever that button is pressed.

diEffect.dwSize = sizeof(DIEFFECT);
diEffect.dwFlags = DIEFF_POLAR | DIEFF_OBJECTOFFSETS;
diEffect.dwDuration = (DWORD) (2 * DI_SECONDS);

diEffect.dwSamplePeriod = 0;               // = default
diEffect.dwGain = DI_FFNOMINALMAX;         // no scaling
diEffect.dwTriggerButton = DIJOFS_BUTTON0;
diEffect.dwTriggerRepeatInterval = 0;
diEffect.cAxes = 2;
diEffect.rgdwAxes = dwAxes;
diEffect.rglDirection = &lDirection[0];
diEffect.lpEnvelope = &diEnvelope;
diEffect.cbTypeSpecificParams = sizeof(diPeriodic);
diEffect.lpvTypeSpecificParams = &diPeriodic;

So much for the setup. At last you can create the effect:

LPDIEFFECT  g_lpdiEffect;  // global effect object

HRESULT hr = g_lpdid2Game->CreateEffect(
                     guidEffect,     // GUID from enumeration
                     &diEffect,      // where the data is
                     &g_lpdiEffect,  // where to put interface pointer
                     NULL);          // no aggregation
if (FAILED(hr))
  {
  OutputDebugString("Failed to create periodic effect");
  }

Remember that, by default, the effect is downloaded to the device as soon as it has been created, provided that the device is in an acquired state at the exclusive cooperative level. So if everything has gone according to plan, you should be able to compile, run, press the "fire" button, and feel the sputtering of a chain saw that's out of gas.


Step 5: Playing an Effect

The effect created in the previous step starts in response to the press of a button. In order to create an effect that is to be played in response to an explicit call, you need to go back to Step 4 and modify the dwTriggerButton member of the DIEFFECT structure, as follows:

diEffect.dwTriggerButton = DIEB_NOTRIGGER;

Now, suppose you want to make a chain saw that actually starts and keeps going. This is simply a matter of changing the dwDuration member as follows:

diEffect.dwDuration = INFINITE;

Starting the effect is very simple:

g_lpdiEffect->Start(1, 0);

The effect will keep running until you stop it:

g_lpdiEffect->Stop();

Note that you don't need to change the envelope you created in the previous step. The attack is played as the effect starts, but the fade value is ignored.


Step 6: Changing an Effect

Your chain saw is merrily rattling away, and now you want to modify the effect to simulate the slowing down of the engine as the saw bites into wood. Fortunately, DirectInput lets you modify the parameters of an effect while it is playing.

To change the effect, you need to set up a DIEFFECT structure or have access to the one you used to create the effect. If you are setting up a new structure with local scope, you need to initialize only the dwSize member and any members that contain or point to data that is to be changed.

In this case you want to change a type-specific parameter—the period of the effect—so you need to have access to the DIPERIODIC structure you used when creating the effect, or else create a local copy with all members initialized. Make sure that the address of the DIPERIODIC structure is in the lpvTypeSpecificParams member of the DIEFFECT structure.

Now set the new period of the effect:

diPeriodic.dwPeriod = (DWORD) (0.08 * DI_SECONDS);

Then call the method that actually makes the changes:

HRESULT hr = g_lpdiEffect->SetParameters(&diEffect,
                           DIEP_TYPESPECIFICPARAMS)

Note the flag that restricts the changes to a single member of the DIEFFECT structure.

You can control the way changes are handled by using other flags. For example, by using the DIEP_NODOWNLOAD flag you could change the parameters immediately after starting the effect but delay the implementation until the user actually started cutting wood. Then you would call the IDirectInputEffect::Download method. For more information on how to use the various control flags, see IDirectInputEffect::SetParameters.


DirectInput Reference

This section contains reference information for the API elements that DirectInput provides. Reference material is divided into the following categories:

  • Interfaces
  • Functions
  • Callback Functions
  • Macros
  • Structures
  • Device Constants
  • Return Values


Interfaces

This section contains references for methods of the following DirectInput interfaces:

  • IDirectInput
  • IDirectInputDevice
  • IDirectInputDevice2
  • IDirectInputEffect

Note All DirectInput methods have corresponding macros that expand to C or C++ syntax depending on which language is defined. These macros are found in Dinput.h and are not documented separately.


IDirectInput

Applications use the methods of the IDirectInput interface to enumerate, create, and retrieve the status of DirectInput devices, initialize the DirectInput object, and invoke an instance of the Windows Control Panel.

The IDirectInput interface is obtained by using the DirectInputCreate function.

The methods of the IDirectInput interface can be organized into the following groups.

Device Management | CreateDevice
 | EnumDevices
 | GetDeviceStatus
Miscellaneous | Initialize
 | RunControlPanel

The IDirectInput interface, like all COM interfaces, inherits the IUnknown interface methods. The IUnknown interface supports the following three methods:

IUnknown | AddRef
 | QueryInterface
 | Release

The LPDIRECTINPUT type is defined as a pointer to the IDirectInput interface:

typedef struct IDirectInput    *LPDIRECTINPUT;

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dinput.h.
Import Library: Use dinput.lib.


IDirectInput::CreateDevice

The IDirectInput::CreateDevice method creates and initializes an instance of a device based on a given GUID.

HRESULT CreateDevice(
  REFGUID rguid,
  LPDIRECTINPUTDEVICE *lplpDirectInputDevice,
  LPUNKNOWN pUnkOuter
);

Parameters

rguid
Reference to (C++) or address of (C) the instance GUID for the desired input device (see Remarks). The GUID is retrieved through the IDirectInput::EnumDevices method, or it can be one of the following predefined GUIDs:
GUID_SysKeyboard
The default system keyboard.
GUID_SysMouse
The default system mouse.

For the preceding GUID values to be valid, your application must define INITGUID before all other preprocessor directives at the beginning of the source file, or link to Dxguid.lib.

lplpDirectInputDevice
Address of a variable to receive the IDirectInputDevice interface pointer if successful.
pUnkOuter
Address of the controlling object's IUnknown interface for COM aggregation, or NULL if the interface is not aggregated. Most callers will pass NULL.

Return Values

If the method succeeds, the return value is DI_OK.

If the method fails, the return value may be one of the following:

DIERR_DEVICENOTREG
DIERR_INVALIDPARAM
DIERR_NOINTERFACE
DIERR_NOTINITIALIZED
DIERR_OUTOFMEMORY

Remarks

In C++ the rguid parameter must be passed by reference; in C, which does not have pass-by-reference, it must be passed by address. The following is an example of a C++ call:

lpdi->CreateDevice(GUID_SysKeyboard, &pdev, NULL);

The following shows the same call in C:

lpdi->lpVtbl->CreateDevice(lpdi, &GUID_SysKeyboard, &pdev, NULL);

Calling this method with pUnkOuter = NULL is equivalent to creating the object by CoCreateInstance(&CLSID_DirectInputDevice, NULL, CLSCTX_INPROC_SERVER, riid, lplpDirectInputDevice) and then initializing it with Initialize.

Calling this method with pUnkOuter != NULL is equivalent to creating the object by CoCreateInstance(&CLSID_DirectInputDevice, punkOuter, CLSCTX_INPROC_SERVER, &IID_IUnknown, lplpDirectInputDevice). The aggregated object must be initialized manually.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dinput.h.
Import Library: Use dinput.lib.


IDirectInput::EnumDevices

The IDirectInput::EnumDevice method enumerates devices that are either currently attached or could be attached to the computer.

HRESULT EnumDevices(
  DWORD dwDevType,
  LPDIENUMCALLBACK lpCallback,
  LPVOID pvRef,
  DWORD dwFlags
);

Parameters

dwDevType
Device type filter. If this parameter is zero, all device types are enumerated. Otherwise, it is a DIDEVTYPE_* value (see DIDEVICEINSTANCE), indicating the device type that should be enumerated.
lpCallback
Address of a callback function that will be called with a description of each DirectInput device.
pvRef
An application-defined 32-bit value that will be passed to the enumeration callback each time it is called.
dwFlags
Flag value that specifies the scope of the enumeration. This parameter can be one or more of the following values:
DIEDFL_ALLDEVICES
All installed devices will be enumerated. This is the default behavior.
DIEDFL_ATTACHEDONLY
Only attached and installed devices.
DIEDFL_FORCEFEEDBACK
Only devices that support force feedback.
DIEDFL_INCLUDEALIASES
Include devices that are aliases for other devices.
DIEDFL_INCLUDEPHANTOMS
Include phantom (placeholder) devices.

Return Values

If the method succeeds, the return value is DI_OK.

If the method fails, the return value may be one of the following error values:

DIERR_INVALIDPARAM
DIERR_NOTINITIALIZED

Remarks

Keep in mind that all installed devices can be enumerated, even if they are not present. For example, a flight stick may be installed on the system but not currently plugged into the computer. Set the dwFlags parameter to indicate whether only attached or all installed devices should be enumerated. If the DIEDFL_ATTACHEDONLY flag is not present, all installed devices will be enumerated.

A preferred device type can be passed as a dwDevType filter so that only the devices of that type are enumerated.

The lpCallback parameter specifies the address of a callback function of the type documented as DIEnumDevicesProc. DirectInput calls this function for every device that is enumerated. In the callback, the device type and friendly name, and the product GUID and friendly name, are given for each device. If a single input device can function as more than one DirectInput device type, it will be returned for each device type it supports. For example, a keyboard with a built-in mouse will be enumerated as a keyboard and as a mouse. The product GUID would be the same for each device, however.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dinput.h.
Import Library: Use dinput.lib.


IDirectInput::GetDeviceStatus

The IDirectInput::GetDeviceStatus method retrieves the status of a specified device.

HRESULT GetDeviceStatus(
  REFGUID rguidInstance
);

Parameters

rguidInstance
Instance identifier of the device whose status is being checked.

Return Values

If the method succeeds, the return value is DI_OK if the device is attached to the system, or DI_NOTATTACHED otherwise.

If the method fails, the return value may be one of the following error values:

DIERR_GENERIC
DIERR_INVALIDPARAM
DIERR_NOTINITIALIZED

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dinput.h.
Import Library: Use dinput.lib.


IDirectInput::Initialize

The IDirectInput::Initialize method initializes a DirectInput object. The DirectInputCreate function automatically initializes the DirectInput object device after creating it. Applications normally do not need to call this method.

HRESULT Initialize(
  HINSTANCE hinst,
  DWORD dwVersion
);

Parameters

hinst
Instance handle to the application or DLL that is creating the DirectInput object. DirectInput uses this value to determine whether the application or DLL has been certified and to establish any special behaviors that may be necessary for backwards compatibility.

It is an error for a DLL to pass the handle of the parent application. For example, an ActiveX control embedded in a Web page that uses DirectInput must pass its own instance handle and not the handle of the web browser. This ensures that DirectInput recognizes the control and can enable any special behaviors that may be necessary.

dwVersion
Version number of DirectInput for which the application is designed. This value will normally be DIRECTINPUT_VERSION. Passing the version number of a previous version will cause DirectInput to emulate that version. For more information, see Designing for Previous Versions of DirectInput.

Return Values

If the method succeeds, the return value is DI_OK.

If the method fails, the return value may be one of the following error values:

DIERR_BETADIRECTINPUTVERSION
DIERR_OLDDIRECTINPUTVERSION

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dinput.h.
Import Library: Use dinput.lib.


IDirectInput::RunControlPanel

The IDirectInput::RunControlPanel method runs the Windows Control Panel to allow the user to install a new input device or modify configurations.

HRESULT RunControlPanel(
  HWND hwndOwner,
  DWORD dwFlags
);

Parameters

hwndOwner
Handle to the window to be used as the parent window for the subsequent user interface. If this parameter is NULL, no parent window is used.
dwFlags
This parameter is currently not used and must be set to zero.

Return Values

If the method succeeds, the return value is DI_OK.

If the method fails, the return value may be one of the following error values:

DIERR_INVALIDPARAM
DIERR_NOTINITIALIZED

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dinput.h.
Import Library: Use dinput.lib.

See Also

IDirectInputDevice::RunControlPanel


IDirectInputDevice

Applications use the methods of the IDirectInputDevice interface to gain and release access to DirectInput devices, manage device properties and information, set behavior, perform initialization, and invoke a device's control panel.

The IDirectInputDevice interface is obtained by using the IDirectInput::CreateDevice method. For an example, see Creating a DirectInput Device.

The methods of the IDirectInputDevice interface can be organized into the following groups.

Accessing input devices | Acquire
 | Unacquire
Device information | GetCapabilities
 | GetDeviceData
 | GetDeviceInfo
 | GetDeviceState
 | SetDataFormat
 | SetEventNotification
Device objects | EnumObjects
 | GetObjectInfo
Device properties | GetProperty
 | SetProperty
Setting behavior | SetCooperativeLevel
Miscellaneous | Initialize
 | RunControlPanel

The IDirectInputDevice interface, like all COM interfaces, inherits the IUnknown interface methods. The IUnknown interface supports the following three methods:

IUnknown | AddRef
 | QueryInterface
 | Release

The LPDIRECTINPUTDEVICE type is defined as a pointer to the IDirectInputDevice interface:

typedef struct IDirectInputDevice    *LPDIRECTINPUTDEVICE;

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dinput.h.
Import Library: Use dinput.lib.

See Also

IDirectInputDevice2


IDirectInputDevice::Acquire

The IDirectInputDevice::Acquire method obtains access to the input device.

HRESULT Acquire();

Parameters

None.

Return Values

If the method succeeds, the return value is DI_OK or S_FALSE.

If the method fails, the return value may be one of the following error values:

DIERR_INVALIDPARAM
DIERR_NOTINITIALIZED
DIERR_OTHERAPPHASPRIO

If the method returns S_FALSE, the device has already been acquired.

Remarks

Before a device can be acquired, a data format must be set by using the IDirectInputDevice::SetDataFormat method.

Devices must be acquired before calling the IDirectInputDevice::GetDeviceState or IDirectInputDevice::GetDeviceData methods for that device.

Device acquisition does not use a reference count. Therefore, if an application calls the IDirectInputDevice::Acquire method twice, then calls the IDirectInputDevice::Unacquire method once, the device is unacquired.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dinput.h.
Import Library: Use dinput.lib.


IDirectInputDevice::EnumObjects

The IDirectInputDevice::EnumObjects method enumerates the input and force-feedback objects available on a device.

HRESULT EnumObjects(
  LPDIENUMDEVICEOBJECTSCALLBACK lpCallback,
  LPVOID pvRef,
  DWORD dwFlags
);

Parameters

lpCallback
Address of a callback function that receives DirectInputDevice objects. DirectInput provides a prototype of this function as DIEnumDeviceObjectsProc.
pvRef
Reference data (context) for callback.
dwFlags
Flags specifying the types of object to be enumerated. Each of the following values restricts the enumeration to objects of the described type:
DIDFT_ABSAXIS
An absolute axis.
DIDFT_ALL
All objects.
DIDFT_AXIS
An axis, either absolute or relative.
DIDFT_BUTTON
A push button or a toggle button.
DIDFT_COLLECTION
A HID link collection. HID link collections do not generate data of their own.
DIDFT_ENUMCOLLECTION(n)
An object that belongs to HID link collection number n.
DIDFT_FFACTUATOR
An object that contains a force-feedback actuator. In other words, forces may be applied to this object.
DIDFT_FFEFFECTTRIGGER
An object that can be used to trigger force-feedback effects.
DIDFT_NOCOLLECTION
An object that does not belong to any HID link collection; in other words, an object for which the wCollectionNumber member of the DIDEVICEOBJECTINSTANCE structure is 0.
DIDFT_NODATA
An object that does not generate data.
DIDFT_OUTPUT
An object to which data can be sent by using the the IDirectInputDevice2::SendDeviceData method.
DIDFT_POV
A point-of-view controller.
DIDFT_PSHBUTTON
A push button. A push button is reported as down when the user presses it and as up when the user releases it.
DIDFT_RELAXIS
A relative axis.
DIDFT_TGLBUTTON
A toggle button. A toggle button is reported as down when the user presses it and remains so until the user presses the button a second time.

Return Values

If the method succeeds, the return value is DI_OK.

If the method fails, the return value may be one of the following error values:

DIERR_INVALIDPARAM
DIERR_NOTINITIALIZED

Remarks

The DIDFT_FFACTUATOR and DIDFT_FFEFFECTTRIGGER flags in the dwFlags member restrict enumeration to objects that meet all the criteria defined by the included flags. For all the other flags, an object is enumerated if it meets the criterion defined by any included flag in this category. For example, (DIDFT_FFACTUATOR | DIDFT_FFEFFECTTRIGGER) restricts enumeration to force-feedback trigger objects, and (DIDFT_FFEFFECTRIGGER | DIDFT_TGLBUTTON | DIDFT_PSHBUTTON) restricts enumeration to buttons of any kind that can be used as effect triggers.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dinput.h.
Import Library: Use dinput.lib.


IDirectInputDevice::GetCapabilities

The IDirectInputDevice::GetCapabilities method obtains the capabilities of the DirectInputDevice object.

HRESULT GetCapabilities(
  LPDIDEVCAPS lpDIDevCaps
);

Parameters

lpDIDevCaps
Address of a DIDEVCAPS structure to be filled with the device capabilities. The dwSize member of this structure must be initialized before calling this method.

Return Values

If the method succeeds, the return value is DI_OK.

If the method fails, the return value may be one of the following error values:

DIERR_INVALIDPARAM
DIERR_NOTINITIALIZED

Remarks

For compatibility with DirectX 3, it is also valid to pass a DIDEVCAPS_DX3 structure with the dwSize member initialized to sizeof(DIDEVCAPS_DX3). For more information, see Designing for Previous Versions of DirectInput.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dinput.h.
Import Library: Use dinput.lib.


IDirectInputDevice::GetDeviceData

The IDirectInputDevice::GetDeviceData method retrieves buffered data from the device.

HRESULT GetDeviceData(
  DWORD cbObjectData,
  LPDIDEVICEOBJECTDATA rgdod,
  LPDWORD pdwInOut,
  DWORD dwFlags
);

Parameters

cbObjectData
Size of the DIDEVICEOBJECTDATA structure, in bytes.
rgdod
Array of DIDEVICEOBJECTDATA structures to receive the buffered data. The number of elements in this array must be equal to the value of the pdwInOut parameter. If this parameter is NULL, then the buffered data is not stored anywhere, but all other side-effects take place.
pdwInOut
On entry, the number of elements in the array pointed to by the rgdod parameter. On exit, the number of elements actually obtained.
dwFlags
Flags that control the manner in which data is obtained. This value may be zero or the following flag:
DIGDD_PEEK
Do not remove the items from the buffer. A subsequent IDirectInputDevice::GetDeviceData call will read the same data. Normally, data is removed from the buffer after it is read.

Return Values

If the method succeeds, the return value is DI_OK or DI_BUFFEROVERFLOW.

If the method fails, the return value may be one of the following error values:

DIERR_INPUTLOST
DIERR_INVALIDPARAM
DIERR_NOTACQUIRED
DIERR_NOTBUFFERED
DIERR_NOTINITIALIZED

Remarks

Before device data can be obtained, you must set the data format by using the IDirectInputDevice::SetDataFormat method, set the buffer size with IDirectInputDevice::SetProperty method, and acquire the device by using the IDirectInputDevice::Acquire method.

The following example reads up to ten buffered data elements, removing them from the device buffer as they are read.

DIDEVICEOBJECTDATA rgdod[10];
DWORD dwItems = 10;
hres = IDirectInputDevice_GetDeviceData(
    pdid,
    sizeof(DIDEVICEOBJECTDATA),
    rgdod,
    &dwItems,
    0);
if (SUCCEEDED(hres)) {
    // dwItems = number of elements read (could be zero)
    if (hres == DI_BUFFEROVERFLOW) {
    // Buffer had overflowed.
    }
}

Your application can flush the buffer and retrieve the number of flushed items by specifying NULL for the rgdod parameter and a pointer to a variable containing INFINITE for the pdwInOut parameter. The following example illustrates how this can be done:

dwItems = INFINITE;
hres = IDirectInputDevice_GetDeviceData(
            pdid,
            sizeof(DIDEVICEOBJECTDATA),
            NULL,
            &dwItems,
            0);
if (SUCCEEDED(hres)) {
    // Buffer successfully flushed.
    // dwItems = number of elements flushed
    if (hres == DI_BUFFEROVERFLOW) {
        // Buffer had overflowed.
    }
}

Your application can query for the number of elements in the device buffer by setting the rgdod parameter to NULL, setting pdwInOut to INFINITE and setting dwFlags to DIGDD_PEEK. The following code fragment illustrates how this can be done:

dwItems = INFINITE;
hres = IDirectInputDevice_GetDeviceData(
            pdid,
            sizeof(DIDEVICEOBJECTDATA),
            NULL,
            &dwItems,
            DIGDD_PEEK);
if (SUCCEEDED(hres)) {
    // dwItems = number of elements in buffer
    if (hres == DI_BUFFEROVERFLOW) {
        // Buffer overflow occurred; not all data
        // were successfully captured.
    }
}

To query about whether a buffer overflow has occurred, set the rgdod parameter to NULL and the pdwInOut parameter to zero. The following example illustrates how this can be done:

dwItems = 0;
hres = IDirectInputDevice_GetDeviceData(
            pdid,
            sizeof(DIDEVICEOBJECTDATA),
            NULL,
            &dwItems,
            0);
if (hres == DI_BUFFEROVERFLOW) {
    // Buffer overflow occurred
}

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dinput.h.
Import Library: Use dinput.lib.

See Also

IDirectInputDevice2::Poll, Polling and Events


IDirectInputDevice::GetDeviceInfo

The IDirectInputDevice::GetDeviceInfo method obtains information about the device's identity.

HRESULT GetDeviceInfo(
  LPDIDEVICEINSTANCE pdidi
);

Parameters

pdidi
Address of a DIDEVICEINSTANCE structure to be filled with information about the device's identity. An application must initialize the structure's dwSize member before calling this method.

Return Values

If the method succeeds, the return value is DI_OK.

If the method fails, the return value may be one of the following error values:

DIERR_INVALIDPARAM
DIERR_NOTINITIALIZED

Remarks

For compatibility with DirectX 3, it is also valid to pass a DIDEVICEINSTANCE_DX3 structure with the dwSize member initialized to sizeof(DIDEVICEINSTANCE_DX3). For more information, see Designing for Previous Versions of DirectInput.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dinput.h.
Import Library: Use dinput.lib.


IDirectInputDevice::GetDeviceState

The IDirectInputDevice::GetDeviceState method retrieves instantaneous data from the device.

HRESULT GetDeviceState(
  DWORD cbData,
  LPVOID lpvData
);

Parameters

cbData
Size of the buffer in the lpvData parameter, in bytes.
lpvData
Address of a structure that receives the current state of the device. The format of the data is established by a prior call to the IDirectInputDevice::SetDataFormat method.

Return Values

If the method succeeds, the return value is DI_OK.

If the method fails, the return value may be one of the following error values:

DIERR_INPUTLOST
DIERR_INVALIDPARAM
DIERR_NOTACQUIRED
DIERR_NOTINITIALIZED
E_PENDING

Remarks

Before device data can be obtained, set the cooperative level by using the IDirectInputDevice::SetCooperativeLevel method, then set the data format by using IDirectInputDevice::SetDataFormat, and acquire the device by using the IDirectInputDevice::Acquire method.

The four predefined data formats require corresponding device state structures according to the following table:

Data Format | State Structure
c_dfDIMouse | DIMOUSESTATE
c_dfDIKeyboard | array of 256 bytes
c_dfDIJoystick | DIJOYSTATE
c_dfDIJoystick2 | DIJOYSTATE2

For example, if you passed the c_dfDIMouse format to the IDirectInputDevice::SetDataFormat method, you must pass a DIMOUSESTATE structure to the IDirectInputDevice::GetDeviceState method.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dinput.h.
Import Library: Use dinput.lib.

See Also

IDirectInputDevice2::Poll, Polling and Events


IDirectInputDevice::GetObjectInfo

The IDirectInputDevice::GetObjectInfo method retrieves information about a device object such as a button or axis.

HRESULT GetObjectInfo(
  LPDIDEVICEOBJECTINSTANCE pdidoi,
  DWORD dwObj,
  DWORD dwHow
);

Parameters

pdidoi
Address of a DIDEVICEOBJECTINSTANCE structure to be filled with information about the object. The structure's dwSize member must be initialized before this method is called.
dwObj
Value that identifies the object whose information will be retrieved. The value set for this parameter depends on the value specified in the dwHow parameter.
dwHow
Value specifying how the dwObj parameter should be interpreted. This value can be one of the following:
Value | Meaning
DIPH_BYOFFSET | The dwObj parameter is the offset into the current data format of the object whose information is being accessed.
DIPH_BYID | The dwObj parameter is the object type/instance identifier. This identifier is returned in the dwType member of the DIDEVICEOBJECTINSTANCE structure returned from a previous call to the IDirectInputDevice::EnumObjects method.

Return Values

If the method succeeds, the return value is DI_OK.

If the method fails, the return value may be one of the following error values:

DIERR_INVALIDPARAM
DIERR_NOTINITIALIZED
DIERR_OBJECTNOTFOUND

Remarks

For compatibility with DirectX 3, it is also valid to pass a DIDEVICEOBJECTINSTANCE_DX3 structure with the dwSize member initialized to sizeof(DIDEVICEOBJECTINSTANCE_DX3). For more information, see Designing for Previous Versions of DirectInput.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dinput.h.
Import Library: Use dinput.lib.


IDirectInputDevice::GetProperty

The IDirectInputDevice::GetProperty method retrieves information about the input device.

HRESULT GetProperty(
  REFGUID rguidProp,
  LPDIPROPHEADER pdiph
);

Parameters

rguidProp
Identifier of the property to be retrieved. This can be one of the predefined values, or a pointer to a GUID that identifies the property. The following properties are predefined for an input device:
DIPROP_AUTOCENTER
Specifies whether device objects are self-centering. See IDirectInputDevice::SetProperty for more information.
DIPROP_AXISMODE
Retrieves the axis mode. The retrieved value (DIPROPAXISMODE_ABS or DIPROPAXISMODE_REL) is set in the dwData member of the associated DIPROPDWORD structure. See the description for the pdiph parameter for more information.
DIPROP_BUFFERSIZE
Retrieves the input-buffer size. The retrieved value is set in the dwData member of the associated DIPROPDWORD structure. See the description for the pdiph parameter for more information.

The buffer size determines the amount of data that the buffer can hold between calls to the IDirectInputDevice::GetDeviceData method before data is lost. This value may be set to zero to indicate that the application will not be reading buffered data from the device. If the buffer size in the dwData member of the DIPROPDWORD structure is too large to be supported by the device, the largest possible buffer size is set. To determine whether the requested buffer size was set, retrieve the buffer-size property and compare the result with the value you previously attempted to set.

DIPROP_DEADZONE
Retrieves a value for the dead zone of a joystick, in the range 0 to 10,000, where 0 indicates there is no dead zone, 5,000 indicates that the dead zone extends over 50 percent of the physical range of the axis on both sides of center, and 10,000 indicates that the entire physical range of the axis is dead. When the axis is within the dead zone, it is reported as being at the center of its range.
DIPROP_FFGAIN
Retrieves the gain of the device. See IDirectInputDevice::SetProperty for more information.
DIPROP_FFLOAD
Retrieves the memory load for the device. This setting applies to the entire device, rather than to any particular object, so the dwHow member of the associated DIPROPDWORD structure must be DIPH_DEVICE.

The dwData member contains a value in the range 0 to 100, indicating the percentage of device memory in use.

DIPROP_GRANULARITY
Retrieves the input granularity. The retrieved value is set in the dwData member of the associated DIPROPDWORD structure. See the description of the pdiph parameter for more information.

Granularity represents the smallest distance the object will report movement. Most axis objects have a granularity of one, meaning that all values are possible. Some axes may have a larger granularity. For example, the wheel axis on a mouse may have a granularity of 20, meaning that all reported changes in position will be multiples of 20. In other words, when the user turns the wheel slowly, the device reports a position of zero, then 20, then 40, and so on.

This is a read-only property; you cannot set its value by calling the IDirectInputDevice::SetProperty method.

DIPROP_RANGE
Retrieves the range of values an object can possibly report. The retrieved minimum and maximum values are set in the lMin and lMax members of the associated DIPROPRANGE structure. See the description of the pdiph parameter for more information.

For some devices, this is a read-only property; you cannot set its value by calling the IDirectInputDevice::SetProperty method.

DIPROP_SATURATION
Retrieves a value for the saturation zones of a joystick, in the range 0 to 10,000. The saturation level is the point at which the axis is considered to be at its most extreme position. For example, if the saturation level is set to 9,500, then the axis reaches the extreme of its range when it has moved 95 percent of the physical distance from its center position (or from the dead zone).
pdiph
Address of the DIPROPHEADER portion of a larger property-dependent structure that contains the DIPROPHEADER structure as a member. When retrieving object range information, this value is the address of the DIPROPHEADER structure contained within the DIPROPRANGE structure. For most other properties, this value is the address of the DIPROPHEADER structure contained within the DIPROPDWORD structure.

Return Values

If the method succeeds, the return value is DI_OK.

If the method fails, the return value may be one of the following error values:

DIERR_INVALIDPARAM
DIERR_NOTINITIALIZED
DIERR_OBJECTNOTFOUND
DIERR_UNSUPPORTED

Remarks

The following C example illustrates how to obtain the value of the DIPROP_BUFFERSIZE property:

DIPROPDWORD dipdw;  // DIPROPDWORD contains a DIPROPHEADER structure.
HRESULT hr;
dipdw.diph.dwSize       = sizeof(DIPROPDWORD);
dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
dipdw.diph.dwObj        = 0; // device property
dipdw.diph.dwHow        = DIPH_DEVICE;

hr = IDirectInputDevice_GetProperty(pdid, DIPROP_BUFFERSIZE, &dipdw.diph);
if (SUCCEEDED(hr)) {
    // The dipdw.dwData member contains the buffer size.
}

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dinput.h.
Import Library: Use dinput.lib.

See Also

IDirectInputDevice::SetProperty


IDirectInputDevice::Initialize

The IDirectInputDevice::Initialize method initializes a DirectInputDevice object. The IDirectInput::CreateDevice method automatically initializes a device after creating it; applications normally do not need to call this method.

HRESULT Initialize(
  HINSTANCE hinst,
  DWORD dwVersion,
  REFGUID rguid
);

Parameters

hinst
Instance handle to the application or DLL that is creating the DirectInput device object. DirectInput uses this value to determine whether the application or DLL has been certified and to establish any special behaviors that may be necessary for backwards compatibility.

It is an error for a DLL to pass the handle to the parent application. For example, an ActiveX control embedded in a Web page that uses DirectInput must pass its own instance handle and not the handle to the web browser. This ensures that DirectInput recognizes the control and can enable any special behaviors that may be necessary.

dwVersion
Version number of DirectInput for which the application is designed. This value will normally be DIRECTINPUT_VERSION. Passing the version number of a previous version will cause DirectInput to emulate that version. For more information, see Designing for Previous Versions of DirectInput.
rguid
Identifier for the instance of the device for which the interface should be associated. The IDirectInput::EnumDevices method can be used to determine which instance GUIDs are supported by the system.

Return Values

If the method succeeds, the return value is DI_OK or S_FALSE.

If the method fails, the return value may be one of the following error values:

DIERR_ACQUIRED
DIERR_DEVICENOTREG

If the method returns S_FALSE, the device had already been initialized with the instance GUID passed in though rGUID.

Remarks

If this method fails, the underlying object should be considered to be in an indeterminate state and must be reinitialized before use.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dinput.h.
Import Library: Use dinput.lib.


IDirectInputDevice::RunControlPanel

The IDirectInputDevice::RunControlPanel method runs the DirectInput control panel associated with this device. If the device does not have a control panel associated with it, the default device control panel is launched.

HRESULT RunControlPanel(
  HWND hwndOwner,
  DWORD dwFlags
);

Parameters

hwndOwner
Parent window handle. If this parameter is NULL, no parent window is used.
dwFlags
Not currently used. Zero is the only valid value.

Return Values

If the method succeeds, the return value is DI_OK.

If the method fails, the return value may be one of the following error values:

DIERR_INVALIDPARAM
DIERR_NOTINITIALIZED

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dinput.h.
Import Library: Use dinput.lib.


IDirectInputDevice::SetCooperativeLevel

The IDirectInputDevice::SetCooperativeLevel method establishes the cooperative level for this instance of the device. The cooperative level determines how this instance of the device interacts with other instances of the device and the rest of the system.

HRESULT SetCooperativeLevel(
  HWND hwnd,
  DWORD dwFlags
);

Parameters

hwnd
Window handle to be associated with the device. This parameter must be a valid top-level window handle that belongs to the process. The window associated with the device must not be destroyed while it is still active in a DirectInput device.
dwFlags
Flags that describe the cooperative level associated with the device. The following flags are defined:
DISCL_BACKGROUND
The application requires background access. If background access is granted, the device may be acquired at any time, even when the associated window is not the active window.
DISCL_EXCLUSIVE
The application requires exclusive access. If exclusive access is granted, no other instance of the device may obtain exclusive access to the device while it is acquired. Note, however, non-exclusive access to the device is always permitted, even if another application has obtained exclusive access.

An application that acquires the mouse or keyboard device in exclusive mode should always unacquire the devices when it receives WM_ENTERSIZEMOVE and WM_ENTERMENULOOP messages. Otherwise, the user will not be able to manipulate the menu or move and resize the window.

DISCL_FOREGROUND
The application requires foreground access. If foreground access is granted, the device is automatically unacquired when the associated window moves to the background.
DISCL_NONEXCLUSIVE
The application requires non-exclusive access. Access to the device will not interfere with other applications that are accessing the same device.

Applications must specify either DISCL_FOREGROUND or DISCL_BACKGROUND; it is an error to specify both or neither. Similarly, applications must specify either DISCL_EXCLUSIVE or DISCL_NONEXCLUSIVE.

Return Values

If the method succeeds, the return value is DI_OK.

If the method fails, the return value may be one of the following error values:

DIERR_INVALIDPARAM
DIERR_NOTINITIALIZED

Remarks

If the system mouse is acquired in exclusive mode, then the pointer will be removed from the screen until the device is unacquired.

Applications must call this method before acquiring the device by using the IDirectInputDevice::Acquire method.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dinput.h.
Import Library: Use dinput.lib.


IDirectInputDevice::SetDataFormat

The IDirectInputDevice::SetDataFormat method sets the data format for the DirectInput device.

HRESULT SetDataFormat(
  LPCDIDATAFORMAT lpdf
);

Parameters

lpdf
Address of a structure that describes the format of the data the DirectInputDevice should return. An application can define its own DIDATAFORMAT structure or use one of the following predefined global variables:
  • c_dfDIKeyboard
  • c_dfDIMouse
  • c_dfDIJoystick
  • c_dfDIJoystick2

Return Values

If the method succeeds, the return value is DI_OK.

If the method fails, the return value may be one of the following error values:

DIERR_ACQUIRED
DIERR_INVALIDPARAM
DIERR_NOTINITIALIZED

Remarks

The data format must be set before the device can be acquired by using the IDirectInputDevice::Acquire method. It is necessary to set the data format only once. The data format cannot be changed while the device is acquired.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dinput.h.
Import Library: Use dinput.lib.

See Also

IDirectInputDevice::GetDeviceState


IDirectInputDevice::SetEventNotification

The IDirectInputDevice::SetEventNotification method sets the event notification status. This method specifies an event that is to be set when the device state changes. It is also used to turn off event notification.

HRESULT SetEventNotification(
  HANDLE hEvent
);

Parameters

hEvent
Handle to the event that is to be set when the device state changes. DirectInput will use the Win32 SetEvent function on the handle when the state of the device changes. If the hEvent parameter is NULL, then notification is disabled.

The application may create the handle as either a manual-reset or automatic-reset event by using the Win32 CreateEvent function. If the event is created as an automatic-reset event, then the operating system will automatically reset the event once a wait has been satisfied. If the event is created as a manual-reset event, then it is the application's responsibility to call the Win32 ResetEvent function to reset it. DirectInput will not call the Win32 ResetEvent function for event notification handles. Most applications will create the event as an automatic-reset event.

Return Values

If the method succeeds, the return value is DI_OK or DI_POLLEDDEVICE.

If the method fails, the return value may be one of the following error values:

DIERR_ACQUIRED
DIERR_HANDLEEXISTS
DIERR_INVALIDPARAM
DIERR_NOTINITIALIZED

Remarks

A device state change is defined as any of the following:

  • A change in the position of an axis
  • A change in the state (pressed or released) of a button
  • A change in the direction of a POV control
  • Loss of acquisition

Do not call the Win32 CloseHandle function on the event while it has been selected into a DirectInputDevice object. You must call this method with the hEvent parameter set to NULL before closing the event handle.

The event notification handle cannot be changed while the device is acquired. If the function is successful, then the application can use the event handle in the same manner as any other Win32 event handle.

The following example checks if the handle is currently set without blocking:

dwResult = WaitForSingleObject(hEvent, 0);
if (dwResult == WAIT_OBJECT_0) {
    // Event is set. If the event was created as
    // automatic-reset, then it has also been reset.
}

The following example illustrates blocking indefinitely until the event is set. Note that this behavior is strongly discouraged because the thread will not respond to the system until the wait is satisfied. In particular, the thread will not respond to Windows messages.

dwResult = WaitForSingleObject(hEvent, INFINITE);
if (dwResult == WAIT_OBJECT_0) {
    // Event has been set. If the event was created
    // as automatic-reset, then it has also been reset.
}

The following example illustrates a typical message loop for a message-based application that uses two events:.

HANDLE ah[2] = { hEvent1, hEvent2 };

while (TRUE) {

    dwResult = MsgWaitForMultipleObjects(2, ah, FALSE,
                        INFINITE, QS_ALLINPUT);
    switch (dwResult) {
    case WAIT_OBJECT_0:
        // Event 1 has been set. If the event was created as
        // automatic-reset, then it has also been reset.
        ProcessInputEvent1();
        break;

    case WAIT_OBJECT_0 + 1:
        // Event 2 has been set. If the event was created as
        // automatic-reset, then it has also been reset.
        ProcessInputEvent2();
        break;

    case WAIT_OBJECT_0 + 2:
        // A Windows message has arrived. Process
        // messages until there aren't any more.
        while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)){
            if (msg.message == WM_QUIT) {
                goto exitapp;
            }
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        break;

    default:
        // Unexpected error.
        Panic();
        break;
    }
}

The following example illustrates a typical application loop for a non-message-based application that uses two events:

HANDLE ah[2] = { hEvent1, hEvent2 };
DWORD dwWait = 0;

while (TRUE) {

    dwResult = MsgWaitForMultipleObjects(2, ah, FALSE,
                                         dwWait, QS_ALLINPUT);
    dwWait = 0;

    switch (dwResult) {
    case WAIT_OBJECT_0:
        // Event 1 has been set. If the event was
        // created as automatic-reset, then it has also
        // been reset.
        ProcessInputEvent1();
        break;

    case WAIT_OBJECT_0 + 1:
        // Event 2 has been set. If the event was
        // created as automatic-reset, then it has also
        // been reset.
        ProcessInputEvent2();
        break;

    case WAIT_OBJECT_0 + 2:
        // A Windows message has arrived. Process
        // messages until there aren't any more.
        while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)){
            if (msg.message == WM_QUIT) {
                goto exitapp;
            }
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        break;

    default:
        // No input or messages waiting.
        // Do a frame of the game.
        // If the game is idle, then tell the next wait
        // to wait indefinitely for input or a message.
        if (!DoGame()) {
            dwWait = INFINITE;
        }
        break;
    }
}

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dinput.h.
Import Library: Use dinput.lib.

See Also

Polling and Events


IDirectInputDevice::SetProperty

The IDirectInputDevice::SetProperty method sets properties that define the device behavior. These properties include input buffer size and axis mode.

HRESULT SetProperty(
  REFGUID rguidProp,
  LPCDIPROPHEADER pdiph
);

Parameters

rguidProp
Identifier of the property to be set. This can be one of the predefined values, or a pointer to a GUID that identifies the property. The following property values are predefined for an input device:
DIPROP_AUTOCENTER
Specifies whether device objects are self-centering. This setting applies to the entire device, rather than to any particular object, so the dwHow member of the associated DIPROPDWORD structure must be DIPH_DEVICE.

The dwData member may be one of the following values:

DIPROPAUTOCENTER_OFF: The device should not automatically center when the user releases the device. An application that uses force-feedback should disable the auto-centering spring before playing effects.

DIPROPAUTOCENTER_ON: The device should automatically center when the user releases the device. For example, in this mode, a joystick would engage the self-centering spring.

Note that the use of force-feedback effects may interfere with the auto-centering spring. Some devices disable the auto-centering spring when a force-feedback effect is played.

Not all devices support the auto-center property.

DIPROP_AXISMODE
Sets the axis mode. The value being set (DIPROPAXISMODE_ABS or DIPROPAXISMODE_REL) must be specified in the dwData member of the associated DIPROPDWORD structure. See the description of the pdiph parameter for more information.

This setting applies to the entire device, so the dwHow member of the associated DIPROPDWORD structure must be set to DIPH_DEVICE.

DIPROP_BUFFERSIZE
Sets the input-buffer size. The value being set must be specified in the dwData member of the associated DIPROPDWORD structure. See the description of the pdiph parameter for more information.

This setting applies to the entire device, so the dwHow member of the associated DIPROPDWORD structure must be set to DIPH_DEVICE.

DIPROP_CALIBRATIONMODE
Allows the application to specify whether DirectInput should retrieve calibrated or uncalibrated data from an axis. By default, DirectInput retrieves calibrated data.

Setting the calibration mode for the entire device is equivalent to setting it for each axis individually.

The dwData member of the DIPROPDWORD structure may be one of the following values:

DIPROPCALIBRATIONMODE_COOKED: DirectInput should return data after applying calibration information. This is the default mode.

DIPROPCALIBRATIONMODE_RAW: DirectInput should return raw, uncalibrated data. This mode is typically used only by Control Panel–type applications.

Note that setting a device into raw mode causes the dead zone, saturation, and range settings to be ignored.

DIPROP_DEADZONE
Sets the value for the dead zone of a joystick, in the range 0 to 10,000, where 0 indicates there is no dead zone, 5,000 indicates that the dead zone extends over 50 percent of the physical range of the axis on both sides of center, and 10,000 indicates that the entire physical range of the axis is dead. When the axis is within the dead zone, it is reported as being at the center of its range.

This setting can be applied to either the entire device or to a specific axis.

DIPROP_FFGAIN
Sets the gain for the device. This setting applies to the entire device, rather than to any particular object, so the dwHow member of the associated DIPROPDWORD structure must be DIPH_DEVICE.

The dwData member contains a gain value that is applied to all effects created on the device. The value is an integer in the range 0 to 10,000, specifying the amount by which effect magnitudes should be scaled for the device. For example, a value of 10,000 indicates that all effect magnitudes are to be taken at face value. A value of 9,000 indicates that all effect magnitudes are to be reduced to 90% of their nominal magnitudes.

Setting a gain value is useful when an application wishes to scale down the strength of all force-feedback effects uniformly, based on user preferences.

Unlike other properties, the gain can be set when the device is in an acquired state.

DIPROP_RANGE
Sets the range of values an object can possibly report. The minimum and maximum values are taken from the lMin and lMax members of the associated DIPROPRANGE structure.

For some devices, this is a read-only property.

You cannot set a reverse range; lMax must be greater than lMin.

DIPROP_SATURATION
Sets the value for the saturation zones of a joystick, in the range 0 to 10,000. The saturation level is the point at which the axis is considered to be at its most extreme position. For example, if the saturation level is set to 9,500, then the axis reaches the extreme of its range when it has moved 95 percent of the physical distance from its center position (or from the dead zone).

This setting can be applied to either the entire device or to a specific axis.

pdiph
Address of the DIPROPHEADER structure contained within the type-specific property structure.

Return Values

If the method succeeds, the return value is DI_OK or DI_PROPNOEFFECT.

If the method fails, the return value may be one of the following error values:

DIERR_INVALIDPARAM
DIERR_NOTINITIALIZED
DIERR_OBJECTNOTFOUND
DIERR_UNSUPPORTED

Remarks

The buffer size determines the amount of data that the buffer can hold between calls to the IDirectInputDevice::GetDeviceData method before data is lost. This value may be set to zero to indicate that the application will not be reading buffered data from the device. If the buffer size in the dwData member of the DIPROPDWORD structure is too large to be supported by the device, the largest possible buffer size is set. To determine whether the requested buffer size was set, retrieve the buffer-size property and compare the result with the value you previously attempted to set.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dinput.h.
Import Library: Use dinput.lib.

See Also

IDirectInputDevice::GetProperty


IDirectInputDevice::Unacquire

The IDirectInputDevice::Unacquire method releases access to the device.

HRESULT Unacquire();

Parameters

None.

Return Values

The return value is DI_OK is the device was unacquired, or DI_NOEFFECT if the device was not in an acquired state.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dinput.h.
Import Library: Use dinput.lib.


IDirectInputDevice2

The IDirectInputDevice2 interface inherits all the methods of IDirectInputDevice, and adds methods for polling devices and using force feedback. The inherited methods are unchanged, and it is unnecessary to obtain this interface unless you want to use the new methods.

The IDirectInputDevice2 interface is obtained by calling the IDirectInputDevice::QueryInterface method. For an example, see Creating a DirectInput Device.

The new methods of the IDirectInputDevice2 interface can be grouped as follows:

Polling | Poll
Effects | CreateEffect
 | EnumCreatedEffectObjects
 | EnumEffects
 | GetEffectInfo
Control | Escape
 | SendDeviceData
 | SendForceFeedbackCommand
Status | GetForceFeedbackState

The IDirectInputDevice2 interface, like all COM interfaces, inherits the IUnknown interface methods. The IUnknown interface supports the following three methods:

IUnknown | AddRef
 | QueryInterface
 | Release

The LPDIRECTINPUTDEVICE2 type is defined as a pointer to the IDirectInputDevice2 interface:

typedef struct IDirectInputDevice2   *LPDIRECTINPUTDEVICE2;

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dinput.h.
Import Library: Use dinput.lib.


IDirectInputDevice2::CreateEffect

The IDirectInputDevice2::CreateEffect method creates and initializes an instance of an effect identified by the effect GUID.

HRESULT CreateEffect(
  REFGUID rguid,
  LPCDIEFFECT lpeff,
  LPDIRECTINPUTEFFECT * ppdeff,
  LPUNKNOWN punkOuter
);

Parameters

rguid
The identity of the effect to be created. This can be a predefined effect GUID, or it can be a GUID obtained from IDirectInputDevice2::EnumEffects.

The following effect GUIDs are defined:

GUID_ConstantForce
GUID_RampForce
GUID_Square
GUID_Sine
GUID_Triangle
GUID_SawtoothUp
GUID_SawtoothDown
GUID_Spring
GUID_Damper
GUID_Inertia
GUID_Friction
GUID_CustomForce

lpeff
A DIEFFECT structure that provides parameters for the created effect. This parameter is optional. If it is NULL, then the effect object is created without parameters. The application must then call the IDirectInputEffect::SetParameters method to set the parameters of the effect before it can download the effect.
ppdeff
Address of a variable to receive a pointer to the IDirectInputEffect interface, if successful.
punkOuter
The controlling unknown for COM aggregation. The value is NULL if the interface is not aggregated. Most callers will pass NULL.

Return Values

If the method succeeds, the return value is DI_OK or S_FALSE.

If the method fails, the return value may be one of the following error values:

DIERR_DEVICENOTREG
DIERR_DEVICEFULL
DIERR_INVALIDPARAM
DIERR_NOTINITIALIZED

If the return value is S_FALSE, the effect was created and the parameters of the effect were updated, but the effect could not be downloaded because the associated device is not acquired in exclusive mode.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dinput.h.
Import Library: Use dinput.lib.


IDirectInputDevice2::EnumCreatedEffectObjects

The IDirectInputDevice2::EnumCreatedEffectObjects method enumerates all of the currently created effects for this device. Effects created by IDirectInputDevice2::CreateEffect are enumerated.

HRESULT EnumCreatedEffectObjects(
  LPDIENUMCREATEDEFFECTOBJECTSCALLBACK lpCallback,
  LPVOID pvRef,
  DWORD fl
);

Parameters

lpCallback
Address of an application-defined callback function. DirectInput provides the prototype function DIEnumCreatedEffectObjectsProc.
pvRef
Reference data (context) for callback.
fl
No flags are currently defined. This parameter must be 0.

Return Values

If the method succeeds, the return value is DI_OK.

If the method fails, the return value may be one of the following error values:

DIERR_INVALIDPARAM
DIERR_NOTINITIALIZED

Remarks

The results will be unpredictable if you create or destroy an effect while an enumeration is in progress. However, the callback function can safely release the effect passed to it.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dinput.h.
Import Library: Use dinput.lib.


IDirectInputDevice2::EnumEffects

The IDirectinputDevice2::EnumEffects method enumerates all of the effects supported by the force-feedback system on the device. The enumerated GUIDs may represent predefined effects as well as effects peculiar to the device manufacturer.

HRESULT EnumEffects(
  LPDIENUMEFFECTSCALLBACK lpCallback,
  LPVOID pvRef,
  DWORD dwEffType
);

Parameters

lpCallback
Address of an application-defined callback function. DirectInput provides the prototype function DIEnumEffectsProc.
pvRef
A 32-bit application-defined value to be passed to the callback function. This parameter may be any 32-bit value; it is declared as LPVOID for convenience.
dwEffType
Effect type filter. Use one of the DIEFT_* values to indicate the effect type to be enumerated, or DIEFT_ALL to enumerate all effect types. For a list of these values, see DIEFFECTINFO.

Return Values

If the method succeeds, the return value is DI_OK.

If the method fails, the return value may be one of the following error values:

DIERR_INVALIDPARAM
DIERR_NOTINITIALIZED

If the callback stops the enumeration prematurely, the enumeration is considered to have succeeded.

Remarks

An application can use the dwEffType member of the DIEFFECTINFO structure to obtain general information about the effect, such as its type and which envelope and condition parameters are supported by the effect.

In order to exploit an effect to its fullest, you must contact the device manufacturer to obtain information on the semantics of the effect and its effect-specific parameters.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dinput.h.
Import Library: Use dinput.lib.


IDirectInputDevice2::Escape

The IDirectInputDevice2::Escape method sends a hardware-specific command to the driver.

HRESULT Escape(
  LPDIEFFESCAPE pesc
);

Parameters

pesc
A DIEFFESCAPE structure that describes the command to be sent. On success, the cbOutBuffer member contains the number of bytes of the output buffer actually used.

Return Values

If the method succeeds, the return value is DI_OK.

If the method fails, the return value may be one of the following error values:

DIERR_DEVICEFULL
DIERR_NOTINITIALIZED

Other device-specific error codes are also possible. Ask the hardware manufacturer for details.

Remarks

Since each driver implements different escapes, it is the application's responsibility to ensure that it is sending the escape to the correct driver by comparing the value of the guidFFDriver member of the DIDEVICEINSTANCE structure against the value the application is expecting.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dinput.h.
Import Library: Use dinput.lib.


IDirectInputDevice2::GetEffectInfo

The IDirectInputDevice2::GetEffectInfo method obtains information about an effect.

HRESULT GetEffectInfo(
  LPDIEFFECTINFO pdei,
  REFGUID rguid
);

Parameters

pdei
A DIEFFECTINFO structure that receives information about the effect. The caller must initialize the dwSize member of the structure before calling this method.
rguid
Identifier of the effect for which information is being requested.

Return Values

If the method succeeds, the return value is DI_OK.

If the method fails, the return value may be one of the following error values:

DIERR_DEVICENOTREG
DIERR_INVALIDPARAM
DIERR_NOTINITIALIZED

Remarks

In C++ the rguid parameter must be passed by reference; in C, which does not have pass-by-reference, it must be passed by address. The following is an example of a C++ call:

lpdev2->GetEffectInfo(&dei, GUID_Effect);

The following shows the same call in C:

lpdev2->lpVtbl->GetEffectInfo(lpdev2, &dei, &GUID_Effect);

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dinput.h.
Import Library: Use dinput.lib.


IDirectInputDevice2::GetForceFeedbackState

The IDirectInputDevice2::GetForceFeedbackState method retrieves the state of the device's force-feedback system.

HRESULT GetForceFeedbackState(
  LPDWORD pdwOut
);

Parameters

pdwOut
Location for flags that describe the current state of the device's force-feedback system.

The value is a combination of the following constants:

DIGFFS_ACTUATORSOFF
The device's force-feedback actuators are disabled.
DIGFFS_ACTUATORSON
The device's force-feedback actuators are enabled.
DIGFFS_DEVICELOST
The device suffered an unexpected failure and is in an indeterminate state. It must be reset either by unacquiring and reacquiring the device, or by sending a DISFFC_RESET command.
DIGFFS_EMPTY
The device has no downloaded effects.
DIGFFS_PAUSED
Playback of all active effects has been paused.
DIGFFS_POWEROFF
The force-feedback system is not currently available. If the device cannot report the power state, then neither DIGFFS_POWERON nor DIGFFS_POWEROFF will be returned.
DIGFFS_POWERON
Power to the force-feedback system is currently available. If the device cannot report the power state, then neither DIGFFS_POWERON nor DIGFFS_POWEROFF will be returned.
DIGFFS_SAFETYSWITCHOFF
The safety switch is currently off, meaning that the device cannot operate. If the device cannot report the state of the safety switch, then neither DIGFFS_SAFETYSWITCHON nor DIGFFS_SAFETYSWITCHOFF will be returned.
DIGFFS_SAFETYSWITCHON
The safety switch is currently on, meaning that the device can operate. If the device cannot report the state of the safety switch, then neither DIGFFS_SAFETYSWITCHON nor DIGFFS_SAFETYSWITCHOFF will be returned.
DIGFFS_STOPPED
No effects are playing and the device is not paused.
DIGFFS_USERFFSWITCHOFF
The user force-feedback switch is currently off, meaning that the device cannot operate. If the device cannot report the state of the user force-feedback switch, then neither DIGFFS_USERFFSWITCHON nor DIGFFS_USERFFSWITCHOFF will be returned.
DIGFFS_USERFFSWITCHON
The user force-feedback switch is currently on, meaning that the device can operate. If the device cannot report the state of the user force-feedback switch, then neither DIGFFS_USERFFSWITCHON nor DIGFFS_USERFFSWITCHOFF will be returned.

Future versions of DirectInput may define additional flags. Applications should ignore any flags that are not currently defined.

Return Values

If the method succeeds, the return value is DI_OK.

If the method fails, the return value may be one of the following error values:

DIERR_INPUTLOST
DIERR_INVALIDPARAM
DIERR_NOTEXCLUSIVEACQUIRED
DIERR_NOTINITIALIZED
DIERR_UNSUPPORTED

Remarks

The device must be acquired at the exclusive cooperative level for this method to succeed.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dinput.h.
Import Library: Use dinput.lib.


IDirectInputDevice2::Poll

The IDirectInputDevice2::Poll method retrieves data from polled objects on a DirectInput device. If the device does not require polling, then calling this method has no effect. If a device that requires polling is not polled periodically, no new data will be received from the device. Calling this method causes DirectInput to update the device state, generate input events (if buffered data is enabled), and set notification events (if notification is enabled).

HRESULT Poll()

Parameters

None.

Return Values

If the method succeeds, the return value is DI_OK, or DI_NOEFFECT if the device does not require polling.

If the method fails, the return value may be one of the following error values:

DIERR_INPUTLOST
DIERR_NOTACQUIRED
DIERR_NOTINITIALIZED

Remarks

Before a device data can be polled, the data format must be set by using the IDirectInputDevice::SetDataFormat method, and the device must be acquired by using the IDirectInputDevice::Acquire method.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dinput.h.
Import Library: Use dinput.lib.

See Also

Polling and Events


IDirectInputDevice2::SendDeviceData

The IDirectInputDevice2::SendDeviceData method sends data to a device that accepts output. The device must be in an acquired state.

HRESULT SendDeviceData(
  DWORD cbObjectData,
  LPCDIDEVICEOBJECTDATA rgdod,
  LPDWORD pdwInOut,
  DWORD fl
);

Parameters

cbObjectData
Size in bytes of a single DIDEVICEOBJECTDATA structure.
rgdod
Array of DIDEVICEOBJECTDATA structures containing the data to send to the device. It must consist of *pdwInOut elements.

The dwOfs field of each DIDEVICEOBJECTDATA structure must contain the device object identifier (as obtained from the dwType field of the DIDEVICEOBJECTINSTANCE structure) for the device object to which the data is directed. The dwTimeStamp and dwSequence members must be zero.

pdwInOut
On entry, the variable pointed to by this parameter contains the number of elements in the array pointed to by rgdod. On exit, it contains the number of elements actually sent to the device.
fl
Flags controlling the manner in which data is sent. This may be zero or the following value:
DISDD_CONTINUE
The device data sent will be overlaid on the previously sent device data. See Remarks.

Return Values

If the method succeeds, the return value is DI_OK.

If the method fails, the return value may be one of the following error values:

DIERR_INPUTLOST
DIERR_NOTACQUIRED
DIERR_REPORTFULL
DIERR_UNPLUGGED

Remarks

There is no guarantee that the individual data elements will be sent in a particular order. However, data sent by successive calls to IDirectInputDevice2::SendDeviceData will not be interleaved. Furthermore, if multiple pieces of data are sent to the same object with a single call, it is unspecified which piece of data is sent.

Consider, for example, a device that can be sent data in packets, each packet describing two pieces of information, call them A and B. Suppose the application attempts to send three data elements: B = 2, A = 1, and B = 0.

The actual device will be sent a single packet. The A field of the packet will contain the value 1, and the B field of the packet will be either 2 or 0.

If the data must to be sent to the device exactly as specified, then three calls to IDirectInputDevice2::SendDeviceData should be performed, each call sending one data element.

In response to the first call, the device will be sent a packet where the A field is blank and the B field contains the value 2.

In response to the second call, the device will be sent a packet where the A field contains the value 1, and the B field is blank.

Finally, in response to the third call, the device will be sent a packet where the A field is blank and the B field contains the value 0.

If the DISDD_CONTINUE flag is set, then the device data sent will be overlaid on the previously sent device data. Otherwise, the device data sent will start from scratch.

For example, suppose a device supports two button outputs, Button0 and Button1. If an application first calls IDirectInputDevice2::SendDeviceData passing "Button0 pressed", then a packet of the form "Button0 pressed, Button1 not pressed" is sent to the device. If the application then makes another call, passing "Button1 pressed" and the DISDD_CONTINUE flag, then a packet of the form "Button0 pressed, Button1 pressed" is sent to the device. However, if the application had not passed the DISDD_CONTINUE flag, the packet sent to the device would have been "Button0 not pressed, Button1 pressed".

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dinput.h.
Import Library: Use dinput.lib.


IDirectInputDevice2::SendForceFeedbackCommand

The IDirectInputDevice2::SendForceFeedbackCommand method sends a command to the device's force-feedback system.

HRESULT SendForceFeedbackCommand(
  DWORD dwFlags
);

Parameters

dwFlags
A single value indicating the desired change in state. The value may be one of the following:
DISFFC_CONTINUE
Paused playback of all active effects is to be continued. It is an error to send this command when the device is not in a paused state.
DISFFC_PAUSE
Playback of all active effects is to be paused. This command also stops the clock on effects, so that they continue playing to their full duration when restarted.

While the device is paused, new effects may not be started and existing ones may not be modified. Doing so may result in the subsequent DISFFC_CONTINUE command failing to perform properly.

To abandon a pause and stop all effects, use the DISFFC_STOPALL or DISFCC_RESET commands.

DISFFC_RESET
The device's force-feedback system is to be put in its startup state. All effects are removed from the device, are no longer valid, and must be recreated if they are to be used again. The device's actuators are disabled.
DISFFC_SETACTUATORSOFF
The device's force-feedback actuators are to be disabled. While the actuators are off, effects continue to play but are ignored by the device. Using the analogy of a sound playback device, they are muted rather than paused.
DISFFC_SETACTUATORSON
The device's force-feedback actuators are to be enabled.
DISFFC_STOPALL
Playback of any active effects is to be stopped. All active effects will be reset, but are still being maintained by the device and are still valid. If the device is in a paused state, that state is lost.

This command is equivalent to calling the IDirectInputEffect::Stop method for each effect playing.

Return Values

If the method succeeds, the return value is DI_OK.

If the method fails, the return value may be one of the following error values:

DIERR_INPUTLOST
DIERR_INVALIDPARAM
DIERR_NOTEXCLUSIVEACQUIRED
DIERR_NOTINITIALIZED
DIERR_UNSUPPORTED

Remarks

The device must be acquired at the exclusive cooperative level for this method to succeed.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dinput.h.
Import Library: Use dinput.lib.


IDirectInputEffect

Applications use the methods of the IDirectInputEffect interface to manage effects of force-feedback devices.

The interface is obtained by using the IDirectInputDevice2::CreateEffect method.

The methods of the IDirectInputEffect interface can be organized into the following groups.

Effect information | GetEffectGuid
 | GetEffectStatus
 | GetParameters
Effect manipulation | Download
 | Initialize
 | SetParameters
 | Start
 | Stop
 | Unload
Miscellaneous | Escape

The IDirectInputEffect interface, like all COM interfaces, inherits the IUnknown interface methods. The IUnknown interface supports the following three methods:

IUnknown | AddRef
 | QueryInterface
 | Release

The LPDIRECTINPUTEFFECT type is defined as a pointer to the IDirectInputEffect interface:

typedef struct IDirectInputEffect    *LPDIRECTINPUTEFFECT;

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dinput.h.
Import Library: Use dinput.lib.


IDirectInputEffect::Download

The IDirectinputEffect::Download method places the effect on the device. If the effect is already on the device, then the existing effect is updated to match the values set by the IDirectInputEffect::SetParameters method.

HRESULT Download(void);

Return Values

If the method succeeds, the return value is DI_OK or S_FALSE.

If the method fails, the return value may be one of the following error values:

DIERR_NOTINITIALIZED
DIERR_DEVICEFULL
DIERR_INCOMPLETEEFFECT
DIERR_INPUTLOST
DIERR_NOTEXCLUSIVEACQUIRED
DIERR_INVALIDPARAM
DIERR_EFFECTPLAYING

If the method returns S_FALSE, the effect has already been downloaded to the device.

Remarks

It is valid to update an effect while it is playing. The semantics of such an operation are explained in the reference for IDirectInputEffect::SetParameters.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dinput.h.
Import Library: Use dinput.lib.


IDirectInputEffect::Escape

The IDirectInputEffect::Escape method sends a hardware-specific command to the driver.

HRESULT Escape(
  LPDIEFFESCAPE pesc
);

Parameters

pesc
A DIEFFESCAPE structure that describes the command to be sent. On success, the cbOutBuffer member contains the number of bytes of the output buffer actually used.

Return Values

If the method succeeds, the return value is DI_OK.

If the method fails, the return value may be one of the following error values:

DIERR_NOTINITIALIZED
DIERR_DEVICEFULL

Other device-specific error codes are also possible. Ask the hardware manufacturer for details.

Remarks

Since each driver implements different escapes, it is the application's responsibility to ensure that it is sending the escape to the correct driver by comparing the value of the guidFFDriver member of the DIDEVICEINSTANCE structure against the value the application is expecting.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dinput.h.
Import Library: Use dinput.lib.


IDirectInputEffect::GetEffectGuid

The IDirectInputEffect::GetEffectGuid method retrieves the GUID for the effect represented by the IDirectInputEffect object.

HRESULT GetEffectGuid(
  LPGUID pguid
);

Parameters

pguid
A GUID structure that is filled by the method.

Return Values

If the method succeeds, the return value is DI_OK.

If the method fails, the return value may be one of the following error values:

DIERR_INVALIDPARAM
DIERR_NOTINITIALIZED

Remarks

Additional information about the effect can be obtained by passing the GUID to IDirectInputDevice2::GetEffectInfo.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dinput.h.
Import Library: Use dinput.lib.


IDirectInputEffect::GetEffectStatus

The IDirectInputEffect::GetEffectStatus method retrieves the status of an effect.

HRESULT GetEffectStatus(
  LPDWORD pdwFlags
);

Parameters

pdwFlags
Status flags for the effect. The value may be zero, or one or more of the following constants:
DIEGES_PLAYING
The effect is playing.
DIEGES_EMULATED
The effect is emulated.

Return Values

If the method succeeds, the return value is DI_OK.

If the method fails, the return value may be one of the following error values:

DIERR_INVALIDPARAM
DIERR_NOTINITIALIZED

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dinput.h.
Import Library: Use dinput.lib.


IDirectInputEffect::GetParameters

The IDirectInputEffect::GetParameters method retrieves information about an effect.

HRESULT GetParameters(
  LPDIEFFECT peff,
  DWORD dwFlags
);

Parameters

peff
Address of a DIEFFECT structure that receives effect information. The dwSize member must be filled in by the application before calling this method.
dwFlags
Flags specifying which portions of the effect information is to be retrieved. The value may be zero, or one or more of the following constants:
DIEP_ALLPARAMS
The union of all other DIEP_* flags, indicating that all members of the DIEFFECT structure are being requested.
DIEP_ALLPARAMS_DX5
The union of all other DIEP_* flags.
DIEP_AXES
The cAxes and rgdwAxes members should receive data. The cAxes member on entry contains the sizes (in DWORDs) of the buffer pointed to by the rgdwAxes member. If the buffer is too small, then the method returns DIERR_MOREDATA and sets cAxes to the necessary size of the buffer.
DIEP_DIRECTION
The cAxes and rglDirection members should receive data. The cAxes member on entry contains the size (in DWORDs) of the buffer pointed to by the rglDirection member. If the buffer is too small, then the GetParameters method returns DIERR_MOREDATA and sets cAxes to the necessary size of the buffer.

The dwFlags member must include at least one of the coordinate system flags (DIEFF_CARTESIAN, DIEFF_POLAR, or DIEFF_SPHERICAL). DirectInput will return the direction of the effect in one of the coordinate systems you specified, converting between coordinate systems as necessary. On exit, exactly one of the coordinate system flags will be set in the dwFlags member, indicating which coordinate system DirectInput used. In particular, passing all three coordinate system flags will retrieve the coordinates in exactly the same format in which they were set.

DIEP_DURATION
The dwDuration member should receive data.
DIEP_ENVELOPE
The lpEnvelope member points to a DIENVELOPE structure that should receive data. If the effect does not have an envelope associated with it, then the lpEnvelope member will be set to NULL.
DIEP_GAIN
The dwGain member should receive data.
DIEP_SAMPLEPERIOD
The dwSamplePeriod member should receive data.
DIEP_TRIGGERBUTTON
The dwTriggerButton member should receive data.
DIEP_TRIGGERREPEATINTERVAL
The dwTriggerRepeatInterval member should receive data.
DIEP_TYPESPECIFICPARAMS
The lpvTypeSpecificParams member points to a buffer whose size is specified by the cbTypeSpecificParams member. On return, the buffer will be filled in with the type-specific data associated with the effect, and the cbTypeSpecificParams member will contain the number of bytes copied. If the buffer supplied by the application is too small to contain all the type-specific data, then the method returns DIERR_MOREDATA, and the cbTypeSpecificParams member will contain the required size of the buffer in bytes.

Return Values

If the method succeeds, the return value is DI_OK.

If the method fails, the return value may be one of the following error values:

DIERR_INVALIDPARAM
DIERR_MOREDATA
DIERR_NOTINITIALIZED

Remarks

Common errors resulting in a DIERR_INVALIDPARAM error include not setting the dwSize member of the DIEFFECT structure, passing invalid flags, or not setting up the members in the DIEFFECT structure properly in preparation for receiving the effect information. For example, if information is to be retrieved in the dwTriggerButton member, the dwFlags member must be set to either DIEFF_OBJECTIDS or DIEFF_OBJECTOFFSETS, so that DirectInput knows how to describe the button.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dinput.h.
Import Library: Use dinput.lib.


IDirectInputEffect::Initialize

The IDirectInputEffect::Initialize method initializes a DirectInputEffect object.

HRESULT Initialize(
  HINSTANCE hinst,
  DWORD dwVersion,
  REFGUID rguid
);

Parameters

hinst
Instance handle to the application or DLL that is creating the DirectInputEffect object. DirectInput uses this value to determine whether the application or DLL has been certified and to establish any special behaviors that may be necessary for backwards compatibility. It is an error for a DLL to pass the handle to the parent application.
dwVersion
Version number of DirectInput for which the application is designed. This value will normally be DIRECTINPUT_VERSION. Passing the version number of a previous version will cause DirectInput to emulate that version. For more information, see Designing for Previous Versions of DirectInput.
rguid
Identifier of the effect with which the interface is associated. The IDirectInputDevice2::EnumEffects method can be used to determine which effect GUIDs are supported by the device.

Return Values

If the method succeeds, the return value is DI_OK.

If the method fails, the return value may be DIERR_DEVICENOTREG.

Remarks

If this method fails, the underlying object should be considered to be an indeterminate state and needs to be reinitialized before it can be subsequently used.

The IDirectInputDevice2::CreateEffect method automatically initializes the effect after creating it. Applications normally do not need to call the Initialize method.

In C++ the rguid parameter must be passed by reference; in C, which does not have pass-by-reference, it must be passed by address. The following is an example of a C++ call:

lpeff->Initialize(g_hinstDll, DIRECTINPUT_VERSION, GUID_Effect);

The following shows the same call in C:

lpeff->lpVtbl->Initialize(lpeff, g_hinstDll,
                          DIRECTINPUT_VERSION, &GUID_Effect);

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dinput.h.
Import Library: Use dinput.lib.


IDirectInputEffect::SetParameters

The IDirectInputEffect::SetParameters method sets information about an effect.

HRESULT SetParameters(
  LPCDIEFFECT peff,
  DWORD dwFlags
);

Parameters

peff
A DIEFFECT structure that contains effect information. The dwSize member must be filled in by the application before calling this method, as well as any members specified by corresponding bits in the dwFlags parameter.
dwFlags
Flags specifying which portions of the effect information are to be set and how the downloading of the parameters should be handled. The value may be zero, or one or more of the following constants:
DIEP_AXES
The cAxes and rgdwAxes members contain data.
DIEP_DIRECTION
The cAxes and rglDirection members contain data. The dwFlags member specifies (with DIEFF_CARTESIAN or DIEFF_POLAR) the coordinate system in which the values should be interpreted.
DIEP_DURATION
The dwDuration member contains data.
DIEP_ENVELOPE
The lpEnvelope member points to a DIENVELOPE structure that contains data. To detach any existing envelope from the effect, pass this flag and set the lpEnvelope member to NULL.
DIEP_GAIN
The dwGain member contains data.
DIEP_NODOWNLOAD
Suppress the automatic IDirectInputEffect::Download that is normally performed after the parameters are updated. See Remarks.
DIEP_NORESTART
Suppress the stopping and restarting of the effect in order to change parameters. See Remarks.
DIEP_SAMPLEPERIOD
The dwSamplePeriod member contains data.
DIEP_START
The effect is to be started (or restarted if it is currently playing) after the parameters are updated. By default, the play state of the effect is not altered.
DIEP_TRIGGERBUTTON
The dwTriggerButton member contains data.
DIEP_TRIGGERDELAY
The dwTriggerDelay member contains data.
DIEP_TRIGGERREPEATINTERVAL
The dwTriggerRepeatInterval member contains data.
DIEP_TYPESPECIFICPARAMS
The lpvTypeSpecificParams and cbTypeSpecificParams members of the DIEFFECT structure contain the address and size of type-specific data for the effect.

Return Values

If the method succeeds, the return value is one of the following:

DI_OK
DI_EFFECTRESTARTED
DI_DOWNLOADSKIPPED
DI_TRUNCATED
DI_TRUNCATEDANDRESTARTED

If the method fails, the return value may be one of the following error values:

DIERR_NOTINITIALIZED
DIERR_INCOMPLETEEFFECT
DIERR_INPUTLOST
DIERR_INVALIDPARAM
DIERR_EFFECTPLAYING

Remarks

The dwDynamicParams member of the DIEFFECTINFO structure for the effect specifies which parameters can be dynamically updated while the effect is playing.

The IDirectInputEffect::SetParameters method automatically downloads the effect, but this behavior can be suppressed by setting the DIEP_NODOWNLOAD flag. If automatic download has been suppressed, then you can manually download the effect by invoking the IDirectInputEffect::Download method.

If the effect is playing while the parameters are changed, then the new parameters take effect as if they were the parameters when the effect started.

For example, suppose a periodic effect with a duration of three seconds is started. After two seconds, the direction of the effect is changed. The effect will then continue for one additional second in the new direction. The envelope, phase, amplitude, and other parameters of the effect continue smoothly as if the direction had not changed.

In the same scenario, if after two seconds the duration of the effect were changed to 1.5 seconds, then the effect would stop.

Normally, if the driver cannot update the parameters of a playing effect, the driver is permitted to stop the effect, update the parameters, and then restart the effect. Passing the DIEP_NORESTART flag suppresses this behavior. If the driver cannot update the parameters of an effect while it is playing, the error code DIERR_EFFECTPLAYING is returned and the parameters are not updated.

No more than one of the DIEP_NODOWNLOAD, DIEP_START, and DIEP_NORESTART flags should be set. (It is also valid to pass none of them.)

These three flags control download and playback behavior as follows:

If DIEP_NODOWNLOAD is set, the effect parameters are updated but not downloaded to the device.

If the DIEP_START flag is set, the effect parameters are updated and downloaded to the device, and the effect is started just as if the IDirectInputEffect::Start method had been called with the dwIterations parameter set to 1 and with no flags. (Combining the update with DIEP_START is slightly faster than calling Start separately, because it requires less information to be transmitted to the device.)

If neither DIEP_NODOWNLOAD nor DIEP_START is set and the effect is not playing, then the parameters are updated and downloaded to the device.

If neither DIEP_NODOWNLOAD nor DIEP_START is set and the effect is playing, then the parameters are updated if the device supports on-the-fly updating. Otherwise the behavior depends on the state of the DIEP_NORESTART flag. If it is set, the error code DIERR_EFFECTPLAYING is returned. If it is clear, the effect is stopped, the parameters are updated, and the effect is restarted.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dinput.h.
Import Library: Use dinput.lib.


IDirectInputEffect::Start

The IDirectInputEffect::Start method begins playing an effect. If the effect is already playing, it is restarted from the beginning. If the effect has not been downloaded or has been modified since its last download, then it will be downloaded before being started. This default behavior can be suppressed by passing the DIES_NODOWNLOAD flag.

HRESULT Start(
  DWORD dwIterations,
  DWORD dwFlags
);

Parameters

dwIterations
Number of times to play the effect in sequence. The envelope is re-articulated with each iteration.

To play the effect exactly once, pass 1. To play the effect repeatedly until explicitly stopped, pass INFINITE. To play the effect until explicitly stopped without re-articulating the envelope, modify the effect parameters with the IDirectInputEffect::SetParameters method and change its dwDuration member to INFINITE.

dwFlags
Flags that describe how the effect should be played by the device. The value may be zero or one or more of the following values:
DIES_SOLO
All other effects on the device should be stopped before the specified effect is played. If this flag is omitted, then the effect is mixed with existing effects already started on the device.
DIES_NODOWNLOAD
Do not automatically download the effect.

Return Values

If the method succeeds, the return value is DI_OK.

If the method fails, the return value may be one of the following error values:

DIERR_INVALIDPARAM
DIERR_INCOMPLETEEFFECT
DIERR_NOTEXCLUSIVEACQUIRED
DIERR_NOTINITIALIZED
DIERR_UNSUPPORTED

Remarks

The device must be acquired at the exclusive cooperative level for this method to succeed.

Not all devices support multiple iterations.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dinput.h.
Import Library: Use dinput.lib.


IDirectInputEffect::Stop

The IDirectInputEffect::Stop method stops playing an effect. The parent device must be acquired.

HRESULT Stop(void);

Return Values

If the method succeeds, the return value is DI_OK.

If the method fails, the return value may be one of the following error values:

DIERR_NOTEXCLUSIVEACQUIRED
DIERR_NOTINITIALIZED

Remarks

The device must be acquired at the exclusive cooperative level for this method to succeed.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dinput.h.
Import Library: Use dinput.lib.


IDirectInputEffect::Unload

The IDirectInputEffect::Unload method removes the effect from the device. If the effect is playing, it is automatically stopped before it is unloaded.

HRESULT Unload(void);

Return Values

If the method succeeds, the return value is DI_OK.

If the method fails, the return value may be one of the following error values:

DIERR_INPUTLOST
DIERR_INVALIDPARAM
DIERR_NOTEXCLUSIVEACQUIRED
DIERR_NOTINITIALIZED

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dinput.h.
Import Library: Use dinput.lib.


Functions

This section is a reference for DirectInput functions other than COM interface methods and callback functions.

The following is the only function that falls into this category:

  • DirectInputCreate is used to create the DirectInput system.


DirectInputCreate

The DirectInputCreate function creates a DirectInput object that supports the IDirectInput COM interface.

HRESULT WINAPI DirectInputCreate(
  HINSTANCE hinst,
  DWORD dwVersion,
  LPDIRECTINPUT * lplpDirectInput,
  LPUNKNOWN punkOuter
);

Parameters

hinst
Instance handle to the application or DLL that is creating the DirectInput object. DirectInput uses this value to determine whether the application or DLL has been certified and to establish any special behaviors that may be necessary for backwards compatibility.

It is an error for a DLL to pass the handle to the parent application. For example, an ActiveX control embedded in a Web page that uses DirectInput must pass its own instance handle and not the handle to the web browser. This ensures that DirectInput recognizes the control and can enable any special behaviors that may be necessary.

dwVersion
Version number of DirectInput for which the application is designed. This value will normally be DIRECTINPUT_VERSION. Passing the version number of a previous version will cause DirectInput to emulate that version. For more information, see Designing for Previous Versions of DirectInput.
lplpDirectInput
Address of a variable to receive a valid IDirectInput interface pointer if the call succeeds.
punkOuter
Pointer to the address of the controlling object's IUnknown interface for COM aggregation, or NULL if the interface is not aggregated. Most callers will pass NULL. If aggregation is requested, the object returned in *lplpDirectInput will be a pointer to the IUnknown rather than an IDirectInput interface, as required by COM aggregation.

Return Values

If the function succeeds, the return value is DI_OK.

If the function fails, the return value may be one of the following error values:

DIERR_BETADIRECTINPUTVERSION
DIERR_INVALIDPARAM
DIERR_OLDDIRECTINPUTVERSION
DIERR_OUTOFMEMORY

Remarks

Calling this function with punkOuter = NULL is equivalent to creating the object through CoCreateInstance(&CLSID_DirectInput, punkOuter, CLSCTX_INPROC_SERVER, &IID_IDirectInput, lplpDirectInput), then initializing it with Initialize.

Calling this function with punkOuter != NULL is equivalent to creating the object through CoCreateInstance(&CLSID_DirectInput, punkOuter, CLSCTX_INPROC_SERVER, &IID_IUnknown, lplpDirectInput). The aggregated object must be initialized manually.

There are separate ANSI and Unicode versions of this service. The ANSI version creates an object that supports the IDirectInputA interface, whereas the Unicode version creates an object that supports the IDirectInputW interface. As with other system services that are sensitive to character set issues, macros in the header file map DirectInputCreate to the appropriate character set variation.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dinput.h.
Import Library: Use dinput.lib.


Callback Functions

The following four functions are prototype callback functions for use with various enumeration methods. Applications can declare one of these callback functions under any name and define it in any way, but the parameter and return types must be the same as in the prototype.

  • DIEnumCreatedEffectObjectsProc
  • DIEnumDeviceObjectsProc
  • DIEnumDevicesProc
  • DIEnumEffectsProc


DIEnumCreatedEffectObjectsProc

The DIEnumCreatedEffectObjectsProc function is an application-defined callback function that receives DirectInputDevice effects as a result of a call to the IDirectInputDevice2::EnumCreatedEffectObjects method.

BOOL CALLBACK DIEnumCreatedEffectObjectsProc(
  LPDIRECTINPUTEFFECT peff,
  LPVOID pvRef
);

Parameters

peff
Pointer to an effect object that has been created.
pvRef
The application-defined value given in the IDirectInputDevice2::EnumCreatedEffectObjects method.

Return Values

Returns DIENUM_CONTINUE to continue the enumeration or DIENUM_STOP to stop the enumeration.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dinput.h.
Import Library: User-defined.


DIEnumDeviceObjectsProc

The DIEnumDeviceObjectsProc function is an application-defined callback function that receives DirectInputDevice objects as a result of a call to the IDirectInputDevice::EnumObjects method.

BOOL CALLBACK DIEnumDeviceObjectsProc(
  LPCDIDEVICEOBJECTINSTANCE lpddoi,
  LPVOID pvRef
);

Parameters

lpddoi
A DIDEVICEOBJECTINSTANCE structure that describes the object being enumerated.
pvRef
The application-defined value given in the IDirectInputDevice::EnumObjects method.

Return Values

Returns DIENUM_CONTINUE to continue the enumeration or DIENUM_STOP to stop the enumeration.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dinput.h.
Import Library: User-defined.


DIEnumDevicesProc

The DIEnumDevicesProc function is an application-defined callback function that receives DirectInput devices as a result of a call to the IDirectInput::EnumDevices method.

BOOL CALLBACK DIEnumDevicesProc(
  LPCDIDEVICEINSTANCE lpddi,
  LPVOID pvRef
);

Parameters

lpddi
Address of a DIDEVICEINSTANCE structure that describes the device instance.
pvRef
The application-defined value given in the IDirectInput::EnumDevices method.

Return Values

Returns DIENUM_CONTINUE to continue the enumeration or DIENUM_STOP to stop the enumeration.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dinput.h.
Import Library: User-defined.


DIEnumEffectsProc

The DIEnumEffectsProc function is an application-defined callback function used with the IDirectInputDevice2::EnumEffects method.

BOOL CALLBACK DIEnumEffectsProc(
  LPCDIEFFECTINFO pdei,
  LPVOID pvRef
);

Parameters

pdei
A DIEFFECTINFO structure that describes the enumerated effect.
pvRef
Address of application-defined data given to the IDirectInputDevice2::EnumEffects method.

Return Values

Returns DIENUM_CONTINUE to continue the enumeration, or DIENUM_STOP to stop it.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dinput.h.
Import Library: User-defined.


Macros

This section describes the following macros used in DirectInput:

  • DIDFT_GETINSTANCE
  • DIDFT_GETTYPE
  • DIDFT_MAKEINSTANCE
  • DIEFT_GETTYPE
  • DISEQUENCE_COMPARE
  • GET_DIDEVICE_SUBTYPE
  • GET_DIDEVICE_TYPE

Dinput.h also defines macros for C calls to all the methods of the IDirectInput and IDirectInputDevice interfaces. These macros eliminate the need for pointers to method tables. For example, here is a C call to the IDirectInputDevice::Release method:

lpdid->lpVtbl->Release(lpdid));

The equivalent macro call looks like this:

IDirectInputDevice_Release(lpdid);

All these macros take the same parameters as the method calls themselves.


DIDFT_GETINSTANCE

The DIDFT_GETINSTANCE macro extracts the object instance number code from a data format type.

DIDFT_GETINSTANCE(n) LOWORD((n) >> 8)

Parameters

n
The DirectInput data format type. The possible values for this parameter are identical to those found in the dwType member of the DIOBJECTDATAFORMAT structure.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dinput.h.

See Also

DIDFT_MAKEINSTANCE, DIDFT_GETTYPE


DIDFT_GETTYPE

The DIDFT_GETTYPE macro extracts the object type code from a data format type.

DIDFT_GETTYPE(n)  LOBYTE(n)

Parameters

n
The DirectInput data format type. The possible values for this parameter are identical to those found in the dwType member of the DIOBJECTDATAFORMAT structure.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dinput.h.

See Also

DIDFT_GETINSTANCE


DIDFT_MAKEINSTANCE

The DIDFT_MAKEINSTANCE macro creates an instance identifier of a device object for packing in the dwType member of the DIOBJECTDATAFORMAT structure.

DIDFT_MAKEINSTANCE(n) ((WORD)(n) << 8)

Parameters

n
Instance of the object; for example, 1 for button 1 of a mouse.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dinput.h.

See Also

DIDFT_GETINSTANCE


DIEFT_GETTYPE

The DIEFT_GETTYPE macro extracts the effect type code from an effect format type.

DIEFT_GETTYPE(n)  LOBYTE(n)

Parameters

n
The DirectInput effect format type. The possible values for this parameter are identical to those found in the dwEffType member of the DIEFFECTINFO structure.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dinput.h.


DISEQUENCE_COMPARE

The DISEQUENCE_COMPARE macro compares two DirectInput sequence numbers, compensating for wraparound.

DISEQUENCE_COMPARE(dwSequence1, cmp, dwSequence2) \
                  ((int)((dwSequence1) - (dwSequence2)) cmp 0)

Parameters

dwSequence1
First sequence number to compare.
cmp
One of the following comparison operators: ==, !=, <, >, <=, or >=.
dwSequence2
Second sequence number to compare.

Return Values

Returns a nonzero value if the result of the comparison specified by the cmp parameter is true, or zero otherwise.

Remarks

The following example checks whether the dwSequence1 parameter value precedes the dwSequence2 parameter value chronologically:

BOOL Sooner = (DISEQUENCE_COMPARE(dwSequence1, <, dwSequence2));

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dinput.h.


GET_DIDEVICE_SUBTYPE

The GET_DIDEVICE_SUBTYPE macro extracts the device subtype code from a device type description code.

GET_DIDEVICE_SUBTYPE(dwDevType)  HIBYTE(dwDevType)

Parameters

dwDevType
DirectInput device type description code. The possible values for this parameter are identical to those found in the dwDevType member of the DIDEVICEINSTANCE structure.

Remarks

The interpretation of the subtype code depends on the primary type.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dinput.h.

See Also

GET_DIDEVICE_TYPE, DIDEVICEINSTANCE


GET_DIDEVICE_TYPE

The GET_DIDEVICE_TYPE macro extracts the device primary type code from a device type description code.

GET_DIDEVICE_TYPE(dwDevType)  LOBYTE(dwDevType)

Parameters

dwDevType
DirectInput device type description code. Possible values for this parameter are identical to those found in the dwDevType member of the DIDEVICEINSTANCE structure.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dinput.h.

See Also

GET_DIDEVICE_SUBTYPE, DIDEVICEINSTANCE


Structures

This section contains information on the following structures used with DirectInput:

  • DICONDITION
  • DICONSTANTFORCE
  • DICUSTOMFORCE
  • DIDATAFORMAT
  • DIDEVCAPS
  • DIDEVICEINSTANCE
  • DIDEVICEOBJECTDATA
  • DIDEVICEOBJECTINSTANCE
  • DIEFFECT
  • DIEFFECTINFO
  • DIEFFESCAPE
  • DIENVELOPE
  • DIJOYSTATE
  • DIJOYSTATE2
  • DIMOUSESTATE
  • DIOBJECTDATAFORMAT
  • DIPERIODIC
  • DIPROPDWORD
  • DIPROPHEADER
  • DIPROPRANGE
  • DIRAMPFORCE

Note The memory for all DirectX structures must be initialized to zero before use. In addition, all structures that contain a dwSize member should set the member to the size of the structure, in bytes, before use. The following example performs these tasks on a common structure, DIDEVCAPS:

DIDEVCAPS didevcaps; // Can't use this yet.

ZeroMemory(&didevcaps, sizeof(didevcaps));
didevcaps.dwSize = sizeof(didevcaps);

// Now the structure can be used.
.
.


DICONDITION

The DICONDITION structure contains type-specific information for effects that are marked as DIEFT_CONDITION.

A pointer to an array of DICONDITION structures for an effect is passed in the lpvTypeSpecificParams member of the DIEFFECT structure. The number of elements in the array must be either one, or equal to the number of axes associated with the effect.

typedef struct DICONDITION {
    LONG lOffset;
    LONG lPositiveCoefficient;
    LONG lNegativeCoefficient;
    DWORD dwPositiveSaturation;
    DWORD dwNegativeSaturation;
    LONG lDeadBand;
} DICONDITION, *LPDICONDITION;

typedef const DICONDITION *LPCDICONDITION;

Members

lOffset
The offset for the condition, in the range -10,000 to +10,000.
lPositiveCoefficient
The coefficient constant on the positive side of the offset, in the range -10,000 to +10,000.
lNegativeCoefficient
The coefficient constant on the negative side of the offset, in the range -10,000 to +10,000.

If the device does not support separate positive and negative coefficients, then the value of lNegativeCoefficient is ignored and the value of lPositiveCoefficient is used as both the positive and negative coefficients.

dwPositiveSaturation
The maximum force output on the positive side of the offset, in the range 0 to 10,000.

If the device does not support force saturations, then the value of this member is ignored.

dwNegativeSaturation
The maximum force output on the negative side of the offset, in the range 0 to 10,000.

If the device does not support force saturations, then the value of this member is ignored.

If the device does not support separate positive and negative saturations, then the value of dwNegativeSaturation is ignored and the value of dwPositiveSaturation is used as both the positive and negative saturations.

lDeadBand
The region around lOffset where the condition is not active, in the range 0 to 10,000. In other words, the condition is not active between lOffset - lDeadBand and lOffset + lDeadBand.

Remarks

Different types of conditions will interpret the parameters differently, but the basic idea is that force resulting from a condition is equal to A(q - q0) where A is a scaling coefficient, q is some metric, and q0 is the neutral value for that metric.

The preceding simplified formula must be adjusted if a nonzero dead band is provided. If the metric is less than lOffset - lDeadBand, then the resulting force is given by the following formula:

force = lNegativeCoefficient * (q - (lOffset - lDeadBand))

Similarly, if the metric is greater than lOffset + lDeadBand, then the resulting force is given by the following formula:

force = lPositiveCoefficient * (q - (lOffset + lDeadBand))

A spring condition uses axis position as the metric.

A damper condition uses axis velocity as the metric.

An inertia condition uses axis acceleration as the metric.

If the number of DICONDITION structures in the array is equal to the number of axes for the effect, then the first structure applies to the first axis, the second applies to the second axis,and so on. For example, a two-axis spring condition with lOffset set to zero in both DICONDITION structures would have the same effect as the joystick self-centering spring. When a condition is defined for each axis in this way, the effect must not be rotated.

If there is a single DICONDITION structure for an effect with more than one axis, then the direction along which the parameters of the DICONDITION structure are in effect is determined by the direction parameters passed in the rglDirection field of the DIEFFECT structure. For example, a friction condition rotated 45 degrees (in polar coordinates) would resist joystick motion in the northeast-southwest direction but would have no effect on joystick motion in the northwest-southeast direction.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dinput.h.


DICONSTANTFORCE

The DICONSTANTFORCE structure contains type-specific information for effects that are marked as DIEFT_CONSTANTFORCE.

The structure describes a constant force effect.

A pointer to a single DICONSTANTFORCE structure for an effect is passed in the lpvTypeSpecificParams member of the DIEFFECT structure.

typedef struct DICONSTANTFORCE {
    LONG lMagnitude;
} DICONSTANTFORCE, *LPDICONSTANTFORCE;

typedef const DICONSTANTFORCE *LPCDICONSTANTFORCE;

Members

lMagnitude
The magnitude of the effect, in the range -10,000 to +10,000. If an envelope is applied to this effect, then the value represents the magnitude of the sustain. If no envelope is applied, then the value represents the amplitude of the entire effect.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dinput.h.


DICUSTOMFORCE

The DICUSTOMFORCE structure contains type-specific information for effects that are marked as DIEFT_CUSTOMFORCE.

The structure describes a custom or user-defined force.

A pointer to a DICUSTOMFORCE structure for an effect is passed in the lpvTypeSpecificParams member of the DIEFFECT structure.

typedef struct DICUSTOMFORCE {
    DWORD cChannels;
    DWORD dwSamplePeriod;
    DWORD cSamples;
    LPLONG rglForceData;
} DICUSTOMFORCE, *LPDICUSTOMFORCE;

typedef const DICUSTOMFORCE *LPCDICUSTOMFORCE;

Members

cChannels
The number of channels (axes) affected by this force.

The first channel is applied to the first axis associated with the effect, the second to the second, and so on. If there are fewer channels than axes, then nothing is associated with the extra axes.

If there is but a single channel, then the effect will be rotated in the direction specified by the rglDirection member of the DIEFFECT structure. If there is more than one channel, then rotation is not allowed.

Not all devices support rotation of custom effects.

dwSamplePeriod
The sample period in microseconds.
cSample
The total number of samples in the rglForceData. It must be an integral multiple of the cChannels.
rglForceData
Pointer to an array of force values representing the custom force. If multiple channels are provided, then the values are interleaved. For example, if cChannels is 3, then the first element of the array belongs to the first channel, the second to the second, and the third to the third.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dinput.h.


DIDATAFORMAT

The DIDATAFORMAT structure carries information describing a device's data format. This structure is used with the IDirectInputDevice::SetDataFormat method.

typedef struct DIDATAFORMAT {
    DWORD dwSize;
    DWORD dwObjSize;
    DWORD dwFlags;
    DWORD dwDataSize;
    DWORD dwNumObjs;
    LPDIOBJECTDATAFORMAT rgodf;
} DIDATAFORMAT, *LPDIDATAFORMAT;

typedef const DIDATAFORMAT *LPCDIDATAFORMAT;

Members

dwSize
Size of this structure, in bytes.
dwObjSize
Size of the DIOBJECTDATAFORMAT structure, in bytes.
dwFlags
Flags describing other attributes of the data format. This value can be one of the following:
DIDF_ABSAXIS
The axes are in absolute mode. Setting this flag in the data format is equivalent to manually setting the axis mode property using the IDirectInputDevice::SetProperty method. This may not be combined with DIDF_RELAXIS flag.
DIDF_RELAXIS
The axes are in relative mode. Setting this flag in the data format is equivalent to manually setting the axis mode property using the IDirectInputDevice::SetProperty method. This may not be combined with the DIDF_ABSAXIS flag.
dwDataSize
Size of a data packet returned by the device, in bytes. This value must be a multiple of 4 and must exceed the largest offset value for an object's data within the data packet.
dwNumObjs
Number of objects in the rgodf array.
rgodf
Address to an array of DIOBJECTDATAFORMAT structures. Each structure describes how one object's data should be reported in the device data. Typical errors include placing two pieces of information in the same location and placing one piece of information in more than one location.

Remarks

Applications do not typically need to create a DIDATAFORMAT structure. An application can use one of the predefined global data format variables, c_dfDIMouse, c_dfDIKeyboard, c_dfDIJoystick, or c_dfDIJoystick2.

The following declarations set a data format that can be used by applications that need two axes (reported in absolute coordinates) and two buttons.

// Suppose an application uses the following
// structure to read device data.

typedef struct MYDATA {
    LONG  lX;                   // x-axis goes here
    LONG  lY;                   // y-axis goes here
    BYTE  bButtonA;             // One button goes here
    BYTE  bButtonB;             // Another button goes here
    BYTE  bPadding[2];          // Must be dword multiple in size
} MYDATA;

// Then it can use the following data format.

DIOBJECTDATAFORMAT rgodf[ ] = {
  { &GUID_XAxis, FIELD_OFFSET(MYDATA, lX),
    DIDFT_AXIS | DIDFT_ANYINSTANCE, 0, },
  { &GUID_YAxis, FIELD_OFFSET(MYDATA, lY),
    DIDFT_AXIS | DIDFT_ANYINSTANCE, 0, },
  { &GUID_Button, FIELD_OFFSET(MYDATA, bButtonA),
    DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0, },
  { &GUID_Button, FIELD_OFFSET(MYDATA, bButtonB),
    DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0, },
};
#define numObjects (sizeof(rgodf) / sizeof(rgodf[0]))

DIDATAFORMAT df = {
    sizeof(DIDATAFORMAT),       // this structure
    sizeof(DIOBJECTDATAFORMAT), // size of object data format
    DIDF_ABSAXIS,               // absolute axis coordinates
    sizeof(MYDATA),             // device data size
    numObjects,                 // number of objects
    rgodf,                      // and here they are
};

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dinput.h.


DIDEVCAPS

The DIDEVCAPS structure contains information about a DirectInput device's capabilities. This structure is used with the IDirectInputDevice::GetCapabilities method.

typedef struct DIDEVCAPS {
    DWORD dwSize;
    DWORD dwFlags;
    DWORD dwDevType;
    DWORD dwAxes;
    DWORD dwButtons;
    DWORD dwPOVs;
    DWORD dwFFSamplePeriod;
    DWORD dwFFMinTimeResolution;
    DWORD dwFirmwareRevision;
    DWORD dwHardwareRevision;
    DWORD dwFFDriverVersion;
} DIDEVCAPS, *LPDIDEVCAPS;

Members

dwSize
Size of this structure, in bytes. This member must be initialized by the application before a call to the IDirectInputDevice::GetCapabilities method.
dwFlags
Flags associated with the device. This value can be a combination of the following:
DIDC_ALIAS
The device is a duplicate of another DirectInput device. Alias devices are by default not enumerated by IDirectInput::EnumDevices.
DIDC_PHANTOM
The device does not really exist. It is a placeholder for a device which may exist in the future. Phantom devices are by default not enumerated by IDirectInput::EnumDevices.
DIDC_ATTACHED
The device is physically attached.
DIDC_DEADBAND
The device supports deadband for at least one force-feedback condition.
DIDC_EMULATED
Device functionality is emulated.
DIDC_FORCEFEEDBACK
The device supports force feedback.
DIDC_FFFADE
The force-feedback system supports the fade parameter for at least one effect. If the device does not support fade then the fade level and fade time parameters of the DIENVELOPE structure will be ignored by the device.

After a call to the IDirectInputDevice2::GetEffectInfo method, an individual effect will set the DIEFT_FFFADE flag if fade is supported for that effect.

DIDC_FFATTACK
The force-feedback system supports the attack envelope parameter for at least one effect. If the device does not support attack then the attack level and attack time parameters of the DIENVELOPE structure will be ignored by the device.

After a call to the IDirectInputDevice2::GetEffectInfo method, an individual effect will set the DIEFT_FFATTACK flag if attack is supported for that effect.

DIDC_POLLEDDATAFORMAT
At least one object in the current data format is polled rather than interrupt-driven. For these objects, the application must explicitly call the IDirectInputDevice2::Poll method in order to obtain data.
DIDC_POLLEDDEVICE
At least one object on the device is polled rather than interrupt-driven. For these objects, the application must explicitly call the IDirectInputDevice2::Poll method in order to obtain data. HID devices may contain a mixture of polled and non-polled objects.
DIDC_POSNEGCOEFFICIENTS
The force-feedback system supports two coefficient values for conditions (one for the positive displacement of the axis and one for the negative displacement of the axis) for at least one condition. If the device does not support both coefficients, then the negative coefficient in the DICONDITION structure will be ignored.

After a call to the IDirectInputDevice2::GetEffectInfo method, an individual condition will set the DIEFT_POSNEGCOEFFICIENTS flag if separate positive and negative coefficients are are supported for that condition.

DIDC_POSNEGSATURATION
The force-feedback system supports a maximum saturation for both positive and negative force output for at least one condition. If the device does not support both saturation values, then the negative saturation in the DICONDITION structure will be ignored.

After a call to the IDirectInputDevice2::GetEffectInfo method, an individual condition will set the DIEFT_POSNEGSATURATION flag if separate positive and negative saturations are are supported for that condition.

DIDC_SATURATION
The force-feedback system supports the saturation of condition effects for at least one condition. If the device does not support saturation, then the force generated by a condition is limited only by the maximum force which the device can generate.

After a call to the IDirectInputDevice2::GetEffectInfo method, an individual condition will set the DIEFT_SATURATION flag if saturation is supported for that condition.

dwDevType
Device type specifier. This member can contain values identical to those in the dwDevType member of the DIDEVICEINSTANCE structure.
dwAxes
Number of axes available on the device.
dwButtons
Number of buttons available on the device.
dwPOVs
Number of point-of-view controllers available on the device.
dwFFSamplePeriod
The minimum time between playback of consecutive raw force commands.
dwFFMinTimeResolution
The minimum amount of time, in microseconds, that the device can resolve. The device rounds any times to the nearest supported increment. For example, if the value of dwFFMinTimeResolution is 1000, then the device would round any times to the nearest millisecond.
dwFirmwareRevision
Specifies the firmware revision of the device.
dwHardwareRevision
The hardware revision of the device.
dwFFDriverVersion
The version number of the device driver.

Remarks

The semantics of version numbers are left to the manufacturer of the device. The only guarantee is that newer versions will have larger numbers.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dinput.h.

See Also

DIDEVICEINSTANCE


DIDEVICEINSTANCE

The DIDEVICEINSTANCE structure contains information about an instance of a DirectInput device. This structure is used with the IDirectInput::EnumDevices and IDirectInputDevice::GetDeviceInfo methods.

typedef struct DIDEVICEINSTANCE {
    DWORD dwSize;
    GUID  guidInstance;
    GUID  guidProduct;
    DWORD dwDevType;
    TCHAR tszInstanceName[MAX_PATH];
    TCHAR tszProductName[MAX_PATH];
    GUID guidFFDriver;
    WORD wUsagePage;
    WORD wUsage;
} DIDEVICEINSTANCE, *LPDIDEVICEINSTANCE;

typedef const DIDEVICEINSTANCE  *LPCDIDEVICEINSTANCE;

Members

dwSize
Size of this structure, in bytes. This member must be initialized before the structure is used.
guidInstance
Unique identifier for the instance of the device. An application may save the instance GUID into a configuration file and use it at a later time. Instance GUIDs are specific to a particular computer. An instance GUID obtained from one computer is unrelated to instance GUIDs on another.
guidProduct
Unique identifier for the product. This identifier is established by the manufacturer of the device.
dwDevType
Device type specifier. The least-significant byte of the device type description code specifies the device type. The next-significant byte specifies the device subtype. This value can be one of the following types combined with their respective subtypes and optionally with DIDEVTYPE_HID, which specifies a Human Interface Device.
Device Types
DIDEVTYPE_MOUSE
A mouse or mouse-like device (such as a trackball).
DIDEVTYPE_KEYBOARD
A keyboard or keyboard-like device.
DIDEVTYPE_JOYSTICK
A joystick or similar device, such as a steering wheel.
DIDEVTYPE_DEVICE
A device that does not fall into the previous categories.
Mouse subtypes
DIDEVTYPEMOUSE_UNKNOWN
The subtype could not be determined.
DIDEVTYPEMOUSE_TRADITIONAL
The device is a traditional mouse.
DIDEVTYPEMOUSE_FINGERSTICK
The device is a fingerstick.
DIDEVTYPEMOUSE_TOUCHPAD
The device is a touchpad.
DIDEVTYPEMOUSE_TRACKBALL
The device is a trackball.
Keyboard subtypes
DIDEVTYPEKEYBOARD_UNKNOWN
The subtype could not be determined.
DIDEVTYPEKEYBOARD_PCXT
IBM PC/XT 83-key keyboard.
DIDEVTYPEKEYBOARD_OLIVETTI
Olivetti 102-key keyboard.
DIDEVTYPEKEYBOARD_PCAT
IBM PC/AT 84-key keyboard.
DIDEVTYPEKEYBOARD_PCENH
IBM PC Enhanced 101/102-key or Microsoft Natural® keyboard.
DIDEVTYPEKEYBOARD_NOKIA1050
Nokia 1050 keyboard.
DIDEVTYPEKEYBOARD_NOKIA9140
Nokia 9140 keyboard.
DIDEVTYPEKEYBOARD_NEC98
Japanese NEC PC98 keyboard.
DIDEVTYPEKEYBOARD_NEC98LAPTOP
Japanese NEC PC98 laptop keyboard.
DIDEVTYPEKEYBOARD_NEC98106
Japanese NEC PC98 106-key keyboard.
DIDEVTYPEKEYBOARD_JAPAN106
Japanese 106-key keyboard.
DIDEVTYPEKEYBOARD_JAPANAX
Japanese AX keyboard.
DIDEVTYPEKEYBOARD_J3100
Japanese J3100 keyboard.
Joystick Subtypes
DIDEVTYPEJOYSTICK_UNKNOWN
The subtype could not be determined.
DIDEVTYPEJOYSTICK_TRADITIONAL
A traditional joystick.
DIDEVTYPEJOYSTICK_FLIGHTSTICK
A joystick optimized for flight simulation.
DIDEVTYPEJOYSTICK_GAMEPAD
A device whose primary purpose is to provide button input.
DIDEVTYPEJOYSTICK_RUDDER
A device for yaw control.
DIDEVTYPEJOYSTICK_WHEEL
A steering wheel.
DIDEVTYPEJOYSTICK_HEADTRACKER
A device that tracks the movement of the user's head.

Flags in the High Word

DIDEVTYPE_HID
The device uses the Human Interface Device (HID) protocol.
tszInstanceName[MAX_PATH]
Friendly name for the instance. For example, "Joystick 1."
tszProductName[MAX_PATH]
Friendly name for the product.
guidFFDriver
Unique identifier for the driver being used for force feedback. This identifier is established by the manufacturer of the driver.
wUsagePage
If the device is a HID device, then this member contains the HID usage page code.
wUsage
If the device is a HID, then this member contains the HID usage code.

Remarks

For compatibility with previous versions of DirectX, a DIDEVICEINSTANCE_DX3 structure is also defined, containing only the first six members of the DIDEVICEINSTANCE structure.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dinput.h.


DIDEVICEOBJECTDATA

The DIDEVICEOBJECTDATA structure contains raw buffered device information. This structure is used with the IDirectInputDevice::GetDeviceData and IDirectInputDevice2::SendDeviceData methods.

typedef struct DIDEVICEOBJECTDATA {
    DWORD dwOfs;
    DWORD dwData;
    DWORD dwTimeStamp;
    DWORD dwSequence;
} DIDEVICEOBJECTDATA, *LPDIDEVICEOBJECTDATA;

typedef const DIDEVICEOBJECTDATA *LPCDIDEVICEOBJECTDATA;

Members

dwOfs
For GetDeviceData, the offset into the current data format of the object whose data is being reported; that is, the location where the dwData would have been stored if the data had been obtained by a call to the IDirectInputDevice::GetDeviceState method. If the device is accessed as a mouse, keyboard, or joystick, the dwOfs member will be one of the mouse device constants, keyboard device constants, or joystick device constants. If a custom data format has been set, then it will be an offset relative to the custom data format.

For SendDeviceData, the instance ID of the object to which the data is being sent, as obtained from the dwType member of a DIDEVICEOBJECTINSTANCE structure.

dwData
Data obtained from or sent to the device.

For axis input, if the device is in relative axis mode, then the relative axis motion is reported. If the device is in absolute axis mode, then the absolute axis coordinate is reported.

For button input, only the low byte of dwData is significant. The high bit of the low byte is set if the button went down; it is clear if the button went up.

dwTimeStamp
Tick count at which the input event was generated, in milliseconds. The current system tick count can be obtained by calling the Win32 GetTickCount function. Remember that this value wraps around approximately every 50 days.

When the structure is used with the SendDeviceData method, this member must be zero.

dwSequence
DirectInput sequence number for this event. All input events are assigned an increasing sequence number. This allows events from different devices to be sorted chronologically. Since this value can wrap around, care must be taken when comparing two sequence numbers. The DISEQUENCE_COMPARE macro can be used to perform this comparison safely.

When the structure is used with the SendDeviceData method, this member must be zero.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dinput.h.


DIDEVICEOBJECTINSTANCE

The DIDEVICEOBJECTINSTANCE structure contains information about a device object instance. This structure is used with the IDirectInputDevice::EnumObjects method to provide the DIEnumDeviceObjectsProc callback function with information about a particular object associated with a device, like an axis or button. It is also used with the IDirectInputDevice::GetObjectInfo method to retrieve information about a device object.

typedef struct DIDEVICEOBJECTINSTANCE {
    DWORD dwSize;
    GUID  guidType;
    DWORD dwOfs;
    DWORD dwType;
    DWORD dwFlags;
    TCHAR tszName[MAX_PATH];
    DWORD dwFFMaxForce;
    DWORD dwFFForceResolution;
    WORD wCollectionNumber;
    WORD wDesignatorIndex;
    WORD wUsagePage;
    WORD wUsage;
    DWORD dwDimension;
    WORD wExponent;
    WORD wReserved;
} DIDEVICEOBJECTINSTANCE, *LPDIDEVICEOBJECTINSTANCE;

typedef const DIDEVICEOBJECTINSTANCE *LPCDIDEVICEOBJECTINSTANCE;

Members

dwSize
Size of the structure, in bytes. During enumeration, the application may inspect this value to determine how many members of the structure are valid. When the structure is passed to the IDirectInputDevice::GetObjectInfo method, this member must be initialized to sizeof(DIDEVICEOBJECTINSTANCE).
guidType
Unique identifier that indicates the object type. This member is optional. If present, it can be one of the following values:
GUID_XAxis
The horizontal axis. For example, it may represent the left-right motion of a mouse.
GUID_YAxis
The vertical axis. For example, it may represent the forward-backward motion of a mouse.
GUID_ZAxis
The z-axis. For example, it may represent rotation of the wheel on a mouse, or movement of a throttle control on a joystick.
GUID_RxAxis
Rotation around the x-axis.
GUID_RyAxis
Rotation around the y-axis.
GUID_RzAxis
Rotation around the z-axis (often a rudder control).
GUID_Slider
A slider axis.
GUID_Button
A button on a mouse.
GUID_Key
A key on a keyboard.
GUID_POV
A point-of-view indicator or "hat".
GUID_Unknown
Unknown.

Other object types may be defined in the future.

dwOfs
Offset within the data format at which data is reported for this object. This value can be used to identify the object in method calls and structures that accept the DIPH_BYOFFSET flag.
dwType
Device type that describes the object. It is a combination of DIDFT_* flags that describe the object type (axis, button, and so forth) and contains the object instance number in the middle 16 bits. Use the DIDFT_GETINSTANCE macro to extract the object instance number. For the DIDFT_* flags, see IDirectInputDevice::EnumObjects.
dwFlags
Flags describing other attributes of the data format. This value can be one of the following:
DIDOI_ASPECTACCEL
The object reports acceleration information.
DIDOI_ASPECTFORCE
The object reports force information.
DIDOI_ASPECTMASK
The bits that are used to report aspect information. An object can represent at most one aspect.
DIDOI_ASPECTPOSITION
The object reports position information.
DIDOI_ASPECTVELOCITY
The object reports velocity information.
DIDOI_FFACTUATOR
The object can have force-feedback effects applied to it.
DIDOI_FFEFFECTTRIGGER
The object can trigger playback of force-feedback effects.
DIDOI_POLLED
The object does not return data until the IDirectInputDevice2::Poll method is called.
tszName[MAX_PATH]
Name of the object; for example, "X-Axis" or "Right Shift."
dwFFMaxForce
The magnitude of the maximum force that can be created by the actuator associated with this object. Force is expressed in newtons and measured in relation to where the hand would be during normal operation of the device.
dwFFForceResolution
The force resolution of the actuator associated with this object. The returned value represents the number of gradations, or subdivisions, of the maximum force that can be expressed by the force-feedback system from 0 (no force) to maximum force.
wCollectionNumber
The HID link collection to which the object belongs.
wDesignatorIndex
An index that refers to a designator in the HID physical descriptor. This number can be passed to functions in the HID parsing library (Hidpi.h) to obtain additional information about the device object.
wUsagePage
The HID usage page associated with the object, if known. Human Interface Devices will always report a usage page. Non-HID devices may optionally report a usage page; if they do not, then the value of this member will be zero.
wUsage
The HID usage associated with the object, if known. Human Interface Devices will always report a usage. Non-HID devices may optionally report a usage; if they do not, then the value of this member will be zero.
dwDimension
The dimensional units in which the object's value is reported, if known, or zero if not known. Applications can use this field to distinguish between, for example, the position and velocity of a control.
wExponent
The exponent to associate with the dimension, if known.
wReserved
Reserved.

Remarks

Applications can use the wUsagePage and wUsage members to obtain additional information about how the object was designed to be used. For example, if wUsagePage has the value 0x02 (vehicle controls) and wUsage has the value 0xB9 (elevator trim), then the object was designed to be the elevator trim control on a flightstick. A flight simulator application can use this information to provide more reasonable defaults for objects on the device. HID usage codes are determined by the USB standards committee.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dinput.h.


DIEFFECT

The DIEFFECT structure is used by the IDirectInputDevice2::CreateEffect method to initialize a new IDirectInputEffect object. It is also used by the IDirectInputEffect::SetParameters and IDirectInputEffect::GetParameters methods.

typedef struct DIEFFECT {
    DWORD dwSize;
    DWORD dwFlags;
    DWORD dwDuration;
    DWORD dwSamplePeriod;
    DWORD dwGain;
    DWORD dwTriggerButton;
    DWORD dwTriggerRepeatInterval;
    DWORD cAxes;
    LPDWORD rgdwAxes;
    LPLONG rglDirection;
    LPDIENVELOPE lpEnvelope;
    DWORD cbTypeSpecificParams;
    LPVOID lpvTypeSpecificParams;
 } DIEFFECT, *LPDIEFFECT;

typedef const DIEFFECT *LPCDIEFFECT;

Members

dwSize
Specifies the size, in bytes, of the structure. This member must be initialized before the structure is used.
dwFlags
Flags associated with the effect. This value can be a combination of one or more of the following values:
DIEFF_CARTESIAN
The values of rglDirection are to be interpreted as Cartesian coordinates.
DIEFF_OBJECTIDS
The values of dwTriggerButton and rgdwAxes are object identifiers as obtained by IDirectInputDevice::EnumObjects.
DIEFF_OBJECTOFFSETS
The values of dwTriggerButton and rgdwAxes are data format offsets, relative to the data format selected by IDirectInput::SetDataFormat.
DIEFF_POLAR
The values of rglDirection are to be interpreted as polar coordinates.
DIEFF_SPHERICAL
The values of rglDirection are to be interpreted as spherical coordinates.
dwDuration
The total duration of the effect in microseconds. If this value is INFINITE, then the effect has infinite duration. If an envelope has been applied to the effect, then the attack will be applied, followed by an infinite sustain.
dwSamplePeriod
The period at which the device should play back the effect, in microseconds. A value of zero indicates that the default playback sample rate should be used.

If the device is not capable of playing back the effect at the specified rate, it will choose the supported rate that is closest to the requested value.

Setting a custom dwSamplePeriod can be used for special effects. For example, playing a sine wave at an artificially large sample period results in a rougher texture.

dwGain
The gain to be applied to the effect, in the range 0 to 10,000. The gain is a scaling factor applied to all magnitudes of the effect and its envelope.
dwTriggerButton
The identifier or offset of the button to be used to trigger playback of the effect. The flags DIEFF_OBJECTIDS and DIEFF_OBJECTOFFSETS determine the semantics of the value. If this member is set to DIEB_NOTRIGGER, then no trigger button is associated with the effect.
dwTriggerRepeatInterval
The interval, in microseconds, between the end of one playback and the start of the next when the effect is triggered by a button press and the button is held down. Setting this value to INFINITE suppresses repetition.

Support for trigger repeat for an effect is indicated by the presence of the DIEP_TRIGGERREPEATINTERVAL flag in the dwStaticParams member of the DIEFFECTINFO structure.

cAxes
Number of axes involved in the effect. This member must be filled in by the caller if changing or setting the axis list or the direction list.

The number of axes for an effect cannot be changed once it has been set.

rgdwAxes
Pointer to a DWORD array (of cAxes elements) containing identifiers or offsets identifying the axes to which the effect is to be applied. The flags DIEFF_OBJECTIDS and DIEFF_OBJECTOFFSETS determine the semantics of the values in the array.

The list of axes associated with an effect cannot be changed once it has been set.

No more than 32 axes can be associated with a single effect.

rglDirection
Pointer to a LONG array (of cAxes elements) containing either Cartesian coordinates or polar coordinates. The flags DIEFF_CARTESIAN, DIEFF_POLAR, and DIEFF_SPHERICAL determine the semantics of the values in the array.

If Cartesian, then each value in rglDirection is associated with the corresponding axis in rgdwAxes.

If polar, then the angle is measured in hundredths of degrees from the (0, –1) direction, rotated in the direction of (1, 0). This usually means that "north" is away from the user, and "east" is to the user's right. The last element is not used.

If spherical, then the first angle is measured in hundredths of degrees from the (1, 0) direction, rotated in the direction of (0, 1). The second angle (if the number of axes is three or more) is measured in hundredths of degrees towards (0, 0, 1). The third angle (if the number of axes is four or more) is measured in hundredths of degrees towards (0, 0, 0, 1), and so on. The last element is not used.

Note The rglDirection array must contain cAxes entries, even if polar or spherical coordinates are given. In these cases the last element in the rglDirection array is reserved for future use and must be zero.

lpEnvelope
Optional pointer to a DIENVELOPE structure that describes the envelope to be used by this effect. Note that not all effect types use envelopes. If no envelope is to be applied, then the member should be set to NULL.
cbTypeSpecificParams
Number of bytes of additional type-specific parameters for the corresponding effect type.
lpvTypeSpecificParams
Pointer to type-specific parameters, or NULL if there are no type-specific parameters.

If the effect is of type DIEFT_CONDITION, then this member contains a pointer to an array of DICONDITION structures that define the parameters for the condition. A single structure may be used, in which case the condition is applied in the direction specified in the rglDirection array. Otherwise there must be one structure for each axis, in the same order as the axes in rgdwAxes array. If a structure is supplied for each axis, the effect should not be rotated; you should use the following values in the rglDirection array:

  • DIEFF_SPHERICAL: 0, 0, ...
  • DIEFF_POLAR: 9000, 0, ...
  • DIEFF_CARTESIAN: 1, 0, ...

If the effect is of type DIEFT_CUSTOMFORCE, then this member contains a pointer to a DICUSTOMFORCE structure that defines the parameters for the custom force.

If the effect is of type DIEFT_PERIODIC, then this member contains a pointer to a DIPERIODIC structure that defines the parameters for the effect.

If the effect is of type DIEFT_CONSTANTFORCE, then this member contains a pointer to a DICONSTANTFORCE structure that defines the parameters for the constant force.

If the effect is of type DIEFT_RAMPFORCE, then this member contains a pointer to a DIRAMPFORCE structure that defines the parameters for the ramp force.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dinput.h.


DIEFFECTINFO

The DIEFFECTINFO structure is used by the IDirectInputDevice2::EnumEffects and IDirectInputDevice2::GetEffectInfo methods to return information about a particular effect supported by a device.

typedef struct DIEFFECTINFO {
    DWORD dwSize;
    GUID guid;
    DWORD dwEffType;
    DWORD dwStaticParams;
    DWORD dwDynamicParams;
    TCHAR tszName[MAX_PATH];
} DIEFFECTINFO, *LPDIEFFECTINFO;

typedef const DIEFFECTINFO  *LPCDIEFFECTINFO;

Members

dwSize
The size of the structure in bytes. During enumeration, the application may inspect this value to determine how many members of the structure are valid. This member must be initialized before the structure is passed to the IDirectInputDevice2::GetEffectInfo method.
guid
Identifier of the effect.
dwEffType
Zero or more of the following values:
DIEFT_ALL
Valid only for IDirectInputDevice2::EnumEffects . Enumerate all effects, regardless of type. This flag may not be combined with any of the other flags.
DIEFT_CONDITION
The effect represents a condition. When creating or modifying a condition, the lpvTypeSpecificParams member of the DIEFFECT structure must point to an array of DICONDITION structures (one per axis) and the cbTypeSpecificParams member must be set to cAxis * sizeof(DICONDITION).

Not all devices support all the parameters of conditions. Check the effect capability flags to determine which capabilities are available.

The flag can be passed to IDirectInputDevice2::EnumEffects to restrict the enumeration to conditions.

DIEFT_CONSTANTFORCE
The effect represents a constant-force effect. When creating or modifying a constant-force effect, the lpvTypeSpecificParams member of the DIEFFECT must point to a DICONSTANTFORCE structure and the cbTypeSpecificParams member must be set to sizeof(DICONSTANTFORCE).

The flag can be passed to IDirectInputDevice2::EnumEffects to restrict the enumeration to constant-force effects.

DIEFT_CUSTOMFORCE
The effect represents a custom-force effect. When creating or modifying a custom-force effect, the lpvTypeSpecificParams member of the DIEFFECT structure must point to a DICUSTOMFORCE structure and the cbTypeSpecificParams member must be set to sizeof(DICUSTOMFORCE).

The flag can be passed to IDirectInputDevice2::EnumEffects to restrict the enumeration to custom-force effects.

DIEFT_DEADBAND
The effect generator for this condition effect supports the lDeadBand parameter.
DIEFT_FFATTACK
The effect generator for this effect supports the attack envelope parameter. If the effect generator does not support attack then the attack level and attack time parameters of the DIENVELOPE structure will be ignored by the effect.

If neither DIEFT_FFATTACK nor DIEFT_FFFADE is set, then the effect does not support an envelope, and any provided envelope will be ignored.

DIEFT_FFFADE
The effect generator for this effect supports the fade parameter. If the effect generator does not support fade then the fade level and fade time parameters of the DIENVELOPE structure will be ignored by the effect.

If neither DIEFT_FFATTACK nor DIEFT_FFFADE is set, then the effect does not support an envelope, and any provided envelope will be ignored.

DIEFT_HARDWARE
The effect represents a hardware-specific effect. For additional information on using a hardware-specific effect, consult the hardware documentation.

The flag can be passed to the IDirectInputDevice2::EnumEffects method to restrict the enumeration to hardware-specific effects.

DIEFT_PERIODIC
The effect represents a periodic effect. When creating or modifying a periodic effect, the lpvTypeSpecificParams member of the DIEFFECT structure must point to a DIPERIODIC structure and the cbTypeSpecificParams member must be set to sizeof(DIPERIODIC).

The flag can be passed to IDirectInputDevice2::EnumEffects to restrict the enumeration to periodic effects.

DIEFT_POSNEGCOEFFICIENTS
The effect generator for this effect supports two coefficient values for conditions, one for the positive displacement of the axis and one for the negative displacement of the axis. If the device does not support both coefficients, then the negative coefficient in the DICONDITION structure will be ignored and the positive coefficient will be used in both directions.
DIEFT_POSNEGSATURATION
The effect generator for this effect supports a maximum saturation for both positive and negative force output. If the device does not support both saturation values, then the negative saturation in the DICONDITION structure will be ignored and the positive saturation will be used in both directions.
DIEFT_RAMPFORCE
The effect represents a ramp-force effect. When creating or modifying a ramp-force effect, the lpvTypeSpecificParams member of the DIEFFECT structure must point to a DIRAMPFORCE structure and the cbTypeSpecificParams member must be set to sizeof(DIRAMPFORCE).

The flag can be passed to IDirectInputDevice2::EnumEffects to restrict the enumeration to ramp-force effects.

DIEFT_SATURATION
The effect generator for this effect supports the saturation of condition effects. If the effect generator does not support saturation, then the force generated by a condition is limited only by the maximum force that the device can generate.
dwStaticParams
Zero or more DIEP_* values describing the parameters supported by the effect. For example, if DIEP_ENVELOPE is set, then the effect supports an envelope. For a list of possible values, see IDirectInputEffect::GetParameters.

It is not an error for an application to attempt to use effect parameters which are not supported by the device. The unsupported parameters are merely ignored.

This information is provided to allow the application to tailor its use of force feedback to the capabilities of the specific device.

dwDynamicParams
Zero or more DIEP_* values denoting parameters of the effect that can be modified while the effect is playing. For a list of possible values, see IDirectInputEffect::GetParameters.

If an application attempts to change a parameter while the effect is playing, and the driver does not support modifying that effect dynamically, then driver is permitted to stop the effect, update the parameters, then restart it. For more information, see IDirectInputEffect::SetParameters.

tszName[MAX_PATH]
Name of the effect; for example, "Sawtooth up" or "Constant force".

Remarks

Use the DIEFT_GETTYPE macro to extract the effect type from the dwEffType flags.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dinput.h.


DIEFFESCAPE

The DIEFFESCAPE structure is used by the IDirectInputDevice2::Escape and IDirectInputEffect::Escape methods to pass hardware-specific data directly to the device driver.

typedef struct DIEFFESCAPE {
    DWORD dwSize;
    DWORD dwCommand;
    LPVOID lpvInBuffer;
    DWORD cbInBuffer;
    LPVOID lpvOutBuffer;
    DWORD cbOutBuffer;
} DIEFFESCAPE, *LPDIEFFESCAPE;

Members

dwSize
Size of the structure in bytes. This member must be initialized before the structure is used.
dwCommand
Driver-specific command number. Consult the driver documentation for a list of valid commands.
lpvInBuffer
Buffer containing the data required to perform the operation.
cbInBuffer
The size, in bytes, of the lpvInBuffer buffer.
lpvOutBuffer
Buffer in which the operation's output data is returned.
cbOutBuffer
On entry, the size in bytes of the lpvOutBuffer buffer. On exit, the number of bytes actually produced by the command.

Remarks

Since each driver implements different escapes, it is the application's responsibility to ensure that it is talking to the correct driver by comparing the guidFFDriver member in the DIDEVICEINSTANCE structure against the value the application is expecting.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dinput.h.


DIENVELOPE

The DIENVELOPE structure is used by the DIEFFECT structure to specify the optional envelope parameters for an effect. The sustain level for the envelope is represented by the dwMagnitude member of the DIPERIODIC structure and the lMagnitude member of the DICONSTANTFORCE structure. The sustain time is represented by dwDuration member of the DIEFFECT structure.

typedef struct DIENVELOPE {
    DWORD dwSize;
    DWORD dwAttackLevel;
    DWORD dwAttackTime;
    DWORD dwFadeLevel;
    DWORD dwFadeTime;
} DIENVELOPE, *LPDIENVELOPE;

typedef const DIENVELOPE *LPCDIENVELOPE;

Members

dwSize
The size, in bytes, of the structure. This member must be initialized before the structure is used.
dwAttackLevel
Amplitude for the start of the envelope, relative to the baseline, in the range 0 to 10,000. If the effect's type-specific data does not specify a baseline, then the amplitude is relative to zero.
dwAttackTime
The time, in microseconds, to reach the sustain level.
dwFadeLevel
Amplitude for the end of the envelope, relative to the baseline, in the range 0 to 10,000. If the effect's type-specific data does not specify a baseline, then the amplitude is relative to zero.
dwFadeTime
The time, in microseconds, to reach the fade level.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dinput.h.


DIJOYSTATE

The DIJOYSTATE structure contains information about the state of a joystick device. This structure is used with the IDirectInputDevice::GetDeviceState method.

typedef struct DIJOYSTATE {
    LONG    lX;
    LONG    lY;
    LONG    lZ;
    LONG    lRx;
    LONG    lRy;
    LONG    lRz;
    LONG    rglSlider[2];
    DWORD   rgdwPOV[4];
    BYTE    rgbButtons[32];
} DIJOYSTATE, *LPDIJOYSTATE;

Members

lX
Information about the joystick x-axis (usually the left-right movement of a stick).
lY
Information about the joystick y-axis (usually the forward-backward movement of a stick).
lZ
Information about the joystick z-axis (often the throttle control). If the joystick does not have this axis, the value is zero.
lRx
Information about the joystick x-axis rotation. If the joystick does not have this, the value is zero.
lRy
Information about the joystick y-axis rotation. If the joystick does not have this axis, the value is zero.
lRz
Information about the joystick z-axis rotation (often called the rudder). If the joystick does not have this axis, the value is zero.
rglSlider[2]
Two additional axis values (formerly called the u-axis and v-axis) whose semantics depend on the joystick. Use the IDirectInputDevice::GetObjectInfo method to obtain semantic information about these values.
rgdwPOV[4]
The current position of up to four direction controllers (such as point-of-view hats). The position is indicated in hundredths of degrees clockwise from north (away from the user). The center position is normally reported as -1; but see Remarks. For indicators that have only five positions, the value for a controller will be -1, 0, 9,000, 18,000, or 27,000.
rgbButtons[32]
Array of button states. The high-order bit of the byte is set if the corresponding button is down and clear if the button is up or does not exist.

Remarks

You must prepare the device for joystick-style access by calling the IDirectInputDevice::SetDataFormat method, passing the c_dfDIJoystick global data format variable.

If an axis is in relative mode, then the appropriate member contains the change in position. If it is in absolute mode, then the member contains the absolute axis position.

Some drivers report the centered position of the POV indicator as 65,535. Determine whether the indicator is centered as follows:

BOOL POVCentered = (LOWORD(dwPOV) == 0xFFFF);

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dinput.h.


DIJOYSTATE2

The DIJOYSTATE2 structure contains information about the state of a joystick device with extended capabilities. This structure is used with the IDirectInputDevice::GetDeviceState method.

typedef struct DIJOYSTATE2 {
    LONG    lX;
    LONG    lY;
    LONG    lZ;
    LONG    lRx;
    LONG    lRy;
    LONG    lRz;
    LONG    rglSlider[2];
    DWORD   rgdwPOV[4];
    BYTE    rgbButtons[128];
    LONG    lVX;
    LONG    lVY;
    LONG    lVZ;
    LONG    lVRx;
    LONG    lVRy;
    LONG    lVRz;
    LONG    rglVSlider[2];
    LONG    lAX;
    LONG    lAY;
    LONG    lAZ;
    LONG    lARx;
    LONG    lARy;
    LONG    lARz;
    LONG    rglASlider[2];
    LONG    lFX;
    LONG    lFY;
    LONG    lFZ;
    LONG    lFRx;
    LONG    lFRy;
    LONG    lFRz;
    LONG    rglFSlider[2];
} DIJOYSTATE2, *LPDIJOYSTATE2;
lX
Information about the joystick x-axis (usually the left-right movement of a stick).
lY
Information about the joystick y-axis (usually the forward-backward movement of a stick).
lZ
Information about the joystick z-axis (often the throttle control). If the joystick does not have this axis, the value is zero.
lRx
Information about the joystick x-axis rotation. If the joystick does not have this, the value is zero.
lRy
Information about the joystick y-axis rotation. If the joystick does not have this axis, the value is zero.
lRz
Information about the joystick z-axis rotation (often called the rudder). If the joystick does not have this axis, the value is zero.
rglSlider[2]
Two additional axis values (formerly called the u-axis and v-axis) whose semantics depend on the joystick. Use the IDirectInputDevice::GetObjectInfo method to obtain semantic information about these values.
rgdwPOV[4]
The current position of up to four direction controllers (such as point-of-view hats). The position is indicated in hundredths of degrees clockwise from north (away from the user). The center position is normally reported as -1; but see Remarks. For indicators that have only five positions, the value for a controller will be -1, 0, 9,000, 18,000, or 27,000.
rgbButtons[128]
Array of button states. The high-order bit of the byte is set if the corresponding button is down and clear if the button is up or does not exist.
lVX
Information about the x-axis velocity.
lVY
Information about the y-axis velocity.
lVZ
Information about the z-axis velocity.
lVRx
Information about the x-axis angular velocity.
lVRy
Information about the y-axis angular velocity.
lVRz
Information about the z-axis angular velocity.
rglVSlider[2]
Information about extra axis velocities.
lAX
Information about the x-axis acceleration.
lAY
Information about the y-axis acceleration.
lAZ
Information about the z-axis acceleration.
lARx
Information about the x-axis angular acceleration.
lARy
Information about the y-axis angular acceleration.
lARz
Information about the z-axis angular acceleration.
rglASlider[2]
Information about extra axis accelerations.
lFX
Information about the x-axis force.
lFY
Information about the y-axis force.
lFZ
Information about the z-axis force.
lFRx
Information about the x-axis torque.
lFRy
Information about the y-axis torque.
lFRz
Information about the z-axis torque.
rglFSlider[2]
Information about extra axis forces.

Remarks

You must prepare the device for access to a joystick with extended capabilities by calling the IDirectInputDevice::SetDataFormat method, passing the c_dfDIJoystick2 global data format variable.

The DIJOYSTATE2 structure has no special association with the IDirectInputDevice2 interface. You can use either DIJOYSTATE or DIJOYSTATE2 with either the IDirectInputDevice or the IDirectInputDevice2 interface.

If an axis is in relative mode, then the appropriate member contains the change in position. If it is in absolute mode, then the member contains the absolute axis position.

Some drivers report the centered position of the POV indicator as 65,535. Determine whether the indicator is centered as follows:

BOOL POVCentered = (LOWORD(dwPOV) == 0xFFFF);

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dinput.h.


DIMOUSESTATE

The DIMOUSESTATE structure contains information about the state of a mouse device or another device that is being accessed as if it were a mouse device. This structure is used with the IDirectInputDevice::GetDeviceState method.

typedef struct DIMOUSESTATE {
    LONG lX;
    LONG lY;
    LONG lZ;
    BYTE rgbButtons[4];
} DIMOUSESTATE, *LPDIMOUSESTATE;

Members

lX
Information about the mouse x-axis.
lY
Information about the mouse y-axis.
lZ
Information about the mouse z-axis (typically a wheel). If the mouse does not have a z-axis, then the value is zero.
rgbButtons[4]
Array of button states. The high-order bit of the byte is set if the corresponding button is down.

Remarks

You must prepare the device for mouse-style access by calling the IDirectInputDevice::SetDataFormat method, passing the c_dfDIMouse global data format variable.

The mouse is a relative-axis device, so the absolute axis positions for mouse axes are simply accumulated relative motion. As a result, the value of the absolute axis position is not meaningful except in comparison with other absolute axis positions.

If an axis is in relative mode, then the appropriate member contains the change in position. If it is in absolute mode, then the member contains the absolute axis position.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dinput.h.


DIOBJECTDATAFORMAT

The DIOBJECTDATAFORMAT structure contains information about a device object's data format for use with the IDirectInputDevice::SetDataFormat method.

typedef struct DIOBJECTDATAFORMAT {
    const GUID * pguid;
    DWORD        dwOfs;
    DWORD        dwType;
    DWORD        dwFlags;
} DIOBJECTDATAFORMAT, *LPDIOBJECTDATAFORMAT;

typedef const DIOBJECTDATAFORMAT *LPCDIOBJECTDATAFORMAT;

Members

pguid
Unique identifier for the axis, button, or other input source. When requesting a data format, making this member NULL indicates that any type of object is permissible.
dwOfs
Offset within the data packet where the data for the input source will be stored. This value must be a multiple of four for DWORD size data, such as axes. It can be byte-aligned for buttons.
dwType
Device type that describes the object. It is a combination of the following flags describing the object type (axis, button, and so forth) and containing the object-instance number in the middle 16 bits. When requesting a data format, the instance portion must be set to DIDFT_ANYINSTANCE to indicate that any instance is permissible, or to DIDFT_MAKEINSTANCE(n) to restrict the request to instance n. See the examples under Remarks.
DIDFT_ABSAXIS
The object selected by the IDirectInput::SetDataFormat method must be an absolute axis.
DIDFT_AXIS
The object selected by the SetDataFormat method must be an absolute or relative axis.
DIDFT_BUTTON
The object selected by the SetDataFormat method must be a push button or a toggle button.
DIDFT_FFACTUATOR
The object selected by the SetDataFormat method must contain a force-feedback actuator; in other words, it must be possible to apply forces to the object.
DIDFT_FFEFFECTTRIGGER
The object selected by the SetDataFormat method must be a valid force-feedback effect trigger.
DIDFT_POV
The object selected by the SetDataFormat method must be a point-of-view controller.
DIDFT_PSHBUTTON
The object selected by the SetDataFormat method must be a push button.
DIDFT_RELAXIS
The object selected by SetDataFormat must be a relative axis.
DIDFT_TGLBUTTON
The object selected by SetDataFormat must be a toggle button.
dwFlags
Zero or more of the following values:
DIDOI_ASPECTACCEL
The object selected by SetDataFormat must report acceleration information.
DIDOI_ASPECTFORCE
The object selected by SetDataFormat must report force information.
DIDOI_ASPECTPOSITION
The object selected by SetDataFormat must report position information.
DIDOI_ASPECTVELOCITY
The object selected by SetDataFormat must report velocity information.

Remarks

A data format is made up of several DIOBJECTDATAFORMAT structures, one for each object (axis, button, and so on). An array of these structures is contained in the DIDATAFORMAT structure that is passed to IDirectInputDevice::SetDataFormat. An application typically does not need to create an array of DIOBJECTDATAFORMAT structures; rather, it can use one of the predefined data formats, c_dfDIMouse, c_dfDIKeyboard, c_dfDIJoystick, or c_dfDIJoystick2, which have predefined settings for DIOBJECTDATAFORMAT.

The following object data format specifies that DirectInput should choose the first available axis and report its value in the DWORD at offset 4 in the device data.

DIOBJECTDATAFORMAT dfAnyAxis = {
    0,                              // Wildcard
    4,                              // Offset
    DIDFT_AXIS | DIDFT_ANYINSTANCE, // Any axis is okay
    0,                              // Don't care about aspect
};

The following object data format specifies that the x-axis of the device should be stored in the DWORD at offset 12 in the device data. If the device has more than one x-axis, the first available one should be selected.

DIOBJECTDATAFORMAT dfAnyXAxis = {
    &GUID_XAxis,                    // Must be an X axis
    12,                             // Offset
    DIDFT_AXIS | DIDFT_ANYINSTANCE, // Any X axis is okay
    0,                              // Don't care about aspect
};

The following object data format specifies that DirectInput should choose the first available button and report its value in the high bit of the byte at offset 16 in the device data.

DIOBJECTDATAFORMAT dfAnyButton = {
    0,                                // Wildcard
    16,                               // Offset
    DIDFT_BUTTON | DIDFT_ANYINSTANCE, // Any button is okay
    0,                                // Don't care about aspect
};

The following object data format specifies that button 0 of the device should be reported as the high bit of the byte stored at offset 18 in the device data.

If the device does not have a button 0, the attempt to set this data format will fail.

DIOBJECTDATAFORMAT dfButton0 = {
    0,                                    // Wildcard
    18,                                   // Offset
    DIDFT_BUTTON | DIDFT_MAKEINSTANCE(0), // Button zero
    0,                                    // Don't care about aspect
};

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dinput.h.


DIPERIODIC

The DIPERIODIC structure contains type-specific information for effects that are marked as DIEFT_PERIODIC.

The structure describes a periodic effect.

A pointer to a single DIPERIODIC structure for an effect is passed in the lpvTypeSpecificParams member of the DIEFFECT structure.

typedef struct DIPERIODIC {
    DWORD dwMagnitude;
    LONG lOffset;
    DWORD dwPhase;
    DWORD dwPeriod;
} DIPERIODIC, *LPDIPERIODIC;

typedef const DIPERIODIC *LPCDIPERIODIC;

Members

dwMagnitude
The magnitude of the effect, in the range 0 to 10,000. If an envelope is applied to this effect, then the value represents the magnitude of the sustain. If no envelope is applied, then the value represents the amplitude of the entire effect.
lOffset
The offset of the effect. The range of forces generated by the effect will be lOffset - dwMagnitude to lOffset + dwMagnitude. The value of the lOffset member is also the baseline for any envelope that is applied to the effect.
dwPhase
The position in the cycle of the periodic effect at which playback begins, in the range 0 to 35,999. See Remarks.
dwPeriod
The period of the effect in microseconds.

Remarks

A device driver may not provide support for all values in the dwPhase member. In this case the value will be rounded off to the nearest supported value.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dinput.h.


DIPROPDWORD

The DIPROPDWORD is a generic structure used to access DWORD properties.

typedef struct DIPROPDWORD {
    DIPROPHEADER     diph;
    DWORD            dwData;
} DIPROPDWORD, *LPDIPROPDWORD;

typedef const DIPROPDWORD *LPCDIPROPDWORD;

Members

diph
A DIPROPHEADER structure that must be initialized as follows:
Member | Value
dwSize | sizeof(DIPROPDWORD)
dwHeaderSize | sizeof(DIPROPHEADER)
dwObj If the dwHow member is DIPH_DEVICE, this member must be zero.

If the dwHow member is DIPH_BYID, this member must be the identifier for the object whose property setting is to be set or retrieved.

If the dwHow member is DIPH_BYOFFSET, this member must be a data format offset for the object whose property setting is to be set or retrieved. For example, if the c_dfDIMouse data format is selected, it must be one of the DIIMOFS_* values.
dwHow | Specifies how the dwObj member should be interpreted. If dwObj is DIPROP_AXISMODE or DIPROP_BUFFERSIZE, dwHow should be DIPH_DEVICE.

dwData
The property-specific value being set or retrieved.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dinput.h.

See Also

IDirectInputDevice::GetProperty, IDirectInputDevice::SetProperty


DIPROPHEADER

DIPROPHEADER is a generic structure placed at the beginning of all property structures.

typedef struct DIPROPHEADER {
    DWORD    dwSize;
    DWORD    dwHeaderSize;
    DWORD    dwObj;
    DWORD    dwHow;
} DIPROPHEADER, *LPDIPROPHEADER;

typedef const DIPROPHEADER *LPCDIPROPHEADER;

Members

dwSize
Size of the enclosing structure. This member must be initialized before the structure is used.
dwHeaderSize
Size of the DIPROPHEADER structure.
dwObj
Object for which the property is to be accessed. The value set for this member depends on the value specified in the dwHow member.
dwHow
Value specifying how the dwObj member should be interpreted. This value can be one of the following:
Value | Meaning
DIPH_DEVICE | The dwObj member must be zero.
DIPH_BYOFFSET | The dwObj member is the offset into the current data format of the object whose property is being accessed.
DIPH_BYID | The dwObj member is the object type/instance identifier. This identifier is returned in the dwType member of the DIDEVICEOBJECTINSTANCE structure returned from a previous call to the IDirectInputDevice::EnumObjects member.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dinput.h.


DIPROPRANGE

The DIPROPRANGE structure contains information about the range of an object within a device. This structure is used with the DIPROP_RANGE flag set in the IDirectInputDevice::GetProperty and IDirectInputDevice::SetProperty methods.

typedef struct DIPROPRANGE {
    DIPROPHEADER diph;
    LONG         lMin;
    LONG         lMax;
} DIPROPRANGE, *LPDIPROPRANGE;

typedef const DIPROPRANGE *LPCDIPROPRANGE;

Members

diph
A DIPROPHEADER structure that must be initialized as follows:
Member | Value
dwSize | sizeof(DIPROPRANGE)
dwHeaderSize | sizeof(DIPROPHEADER)
dwObj | Identifier of the object whose range is being retrieved or set.
dwHow | How the dwObj member should be interpreted.

lMin
The lower limit of the range, inclusive. If the range of the device is unrestricted, this value will be DIPROPRANGE_NOMIN when the IDirectInputDevice::GetProperty method returns.
lMax
The upper limit of the range, inclusive. If the range of the device is unrestricted, this value will be DIPROPRANGE_NOMAX when the IDirectInputDevice::GetProperty method returns.

Remarks

The range values for devices whose ranges are unrestricted will wrap around.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dinput.h.

See Also

IDirectInputDevice::GetProperty, IDirectInputDevice::SetProperty


DIRAMPFORCE

The DIRAMPFORCE structure contains type-specific information for effects that are marked as DIEFT_RAMPFORCE. The structure describes a ramp force effect.

A pointer to a single DIRAMPFORCE structure for an effect is passed in the lpvTypeSpecificParams member of the DIEFFECT structure.

typedef struct DIPROPRANGE {
    LONG lStart;
    LONG lEnd;
} DIRAMPFORCE, *LPDIRAMPFORCE;

typedef const DIRAMPFORCE *LPCDIRAMPFORCE;

Members

lStart
The magnitude at the start of the effect, in the range -10,000 to +10,000.
lEnd
The magnitude at the end of the effect, in the range -10,000 to +10,000.

Remarks

The dwDuration for a ramp force effect cannot be INFINITE.

QuickInfo

Windows NT/2000: Requires Windows 2000.
Windows 95/98: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dinput.h.


Device Constants

This section is a reference for constants used to interpret data for keys, buttons, and axes.

  • Keyboard Device Constants
  • DirectInput and Japanese Keyboards
  • Mouse Device Constants
  • Joystick Device Constants


Keyboard Device Constants

Keyboard device constants, defined in Dinput.h, represent offsets within a keyboard device's data packet, a 256-byte array. The data at a given offset is associated with a keyboard key. Typically, these values will be used in the dwOfs member of the DIDEVICEOBJECTDATA, DIOBJECTDATAFORMAT or DIDEVICEOBJECTINSTANCE structures, or as indices when accessing data within the array using array notation.

The standard keyboard device constants are the following (in ascending order):

Constant | Note
DIK_ESCAPE |
DIK_1 | On main keyboard
DIK_2 | On main keyboard
DIK_3 | On main keyboard
DIK_4 | On main keyboard
DIK_5 | On main keyboard
DIK_6 | On main keyboard
DIK_7 | On main keyboard
DIK_8 | On main keyboard
DIK_9 | On main keyboard
DIK_0 | On main keyboard
DIK_MINUS | On main keyboard
DIK_EQUALS | On main keyboard
DIK_BACK | The BACKSPACE key
DIK_TAB |
DIK_Q
DIK_W
DIK_E
DIK_R
DIK_T
DIK_Y
DIK_U
DIK_I
DIK_O
DIK_P
DIK_LBRACKET | The [ key
DIK_RBRACKET | The ] key
DIK_RETURN | ENTER key on main keyboard
DIK_LCONTROL | Left CTRL key
DIK_A |
DIK_S
DIK_D
DIK_F
DIK_G
DIK_H
DIK_J
DIK_K
DIK_L
DIK_SEMICOLON
DIK_APOSTROPHE
DIK_GRAVE | Grave accent (`) key
DIK_LSHIFT | Left SHIFT key
DIK_BACKSLASH |
DIK_Z
DIK_X
DIK_C
DIK_V
DIK_B
DIK_N
DIK_M
DIK_COMMA
DIK_PERIOD | On main keyboard
DIK_SLASH | Forward slash on main keyboard
DIK_RSHIFT | Right SHIFT key
DIK_MULTIPLY | The * key on numeric keypad
DIK_LMENU | Left ALT key
DIK_SPACE | SPACEBAR
DIK_CAPITAL | CAPS LOCK key
DIK_F1 |
DIK_F2
DIK_F3
DIK_F4
DIK_F5
DIK_F6
DIK_F7
DIK_F8
DIK_F9
DIK_F10
DIK_NUMLOCK
DIK_SCROLL | SCROLL LOCK
DIK_NUMPAD7 |
DIK_NUMPAD8
DIK_NUMPAD9
DIK_SUBTRACT | MINUS SIGN on numeric keypad
DIK_NUMPAD4 |
DIK_NUMPAD5
DIK_NUMPAD6
DIK_ADD | PLUS SIGN on numeric keypad
DIK_NUMPAD1 |
DIK_NUMPAD2
DIK_NUMPAD3
DIK_NUMPAD0
DIK_DECIMAL | PERIOD (decimal point) on numeric keypad
DIK_F11 |
DIK_F12
DIK_F13
DIK_F14
DIK_F15
DIK_KANA | On Japanese keyboard
DIK_CONVERT | On Japanese keyboard
DIK_NOCONVERT | On Japanese keyboard
DIK_YEN | On Japanese keyboard
DIK_NUMPADEQUALS | On numeric keypad (NEC PC98)
DIK_CIRCUMFLEX | On Japanese keyboard
DIK_AT | On Japanese keyboard
DIK_COLON | On Japanese keyboard
DIK_UNDERLINE | On Japanese keyboard
DIK_KANJI | On Japanese keyboard
DIK_STOP | On Japanese keyboard
DIK_AX | On Japanese keyboard
DIK_UNLABELED | On Japanese keyboard
DIK_NUMPADENTER |
DIK_RCONTROL | Right CTRL key
DIK_NUMPADCOMMA | COMMA on NEC PC98 numeric keypad
DIK_DIVIDE | Forward slash on numeric keypad
DIK_SYSRQ |
DIK_RMENU | Right ALT key
DIK_HOME |
DIK_UP | UP ARROW
DIK_PRIOR | PAGE UP
DIK_LEFT | LEFT ARROW
DIK_RIGHT | RIGHT ARROW
DIK_END |
DIK_DOWN | DOWN ARROW
DIK_NEXT | PAGE DOWN
DIK_INSERT |
DIK_DELETE
DIK_LWIN | Left Windows key
DIK_RWIN | Right Windows key
DIK_APPS | Application key
DIK_PAUSE |

The following alternate names are available:

Alternate name | Regular name | Note
DIK_BACKSPACE | DIK_BACK | BACKSPACE
DIK_NUMPADSTAR | DIK_MULTIPLY | * key on numeric keypad
DIK_LALT | DIK_LMENU | Left ALT
DIK_CAPSLOCK | DIK_CAPITAL | CAPSLOCK
DIK_NUMPADMINUS | DIK__SUBTRACT | Minus key on numeric keypad
DIK_NUMPADPLUS | DIK_ADD | Plus key on numeric keypad
DIK_NUMPADPERIOD | DIK_DECIMAL | Period key on numeric keypad
DIK_NUMPADSLASH | DIK__DIVIDE | Forward slash on numeric keypad
DIK_RALT | DIK_RMENU | Right ALT
DIK_UPARROW | DIK_UP | On arrow keypad
DIK_PGUP | DIK_PRIOR | On arrow keypad
DIK_LEFTARROW | DIK_LEFT | On arrow keypad
DIK_RIGHTARROW | DIK_RIGHT | On arrow keypad
DIK_DOWNARROW | DIK_DOWN | On arrow keypad
DIK_PGDN | DIK_NEXT | On arrow keypad

For information on Japanese keyboards, see DirectInput and Japanese Keyboards.


DirectInput and Japanese Keyboards

There are substantial differences between Japanese and U.S. keyboards. The chart below lists the additional keys that are available on each type of Japanese keyboard. It also lists the keys that are available on U.S. keyboards but are missing on the various Japanese keyboards.

Also note that on some NEC PC-98 keyboards, the DIK_CAPSLOCK and DIK_KANA keys are toggle buttons and not push buttons. These generate a down event when first pressed, then generate an up event when pressed a second time.

Keyboard | Additional Keys | Missing Keys
DOS/V 106 Keyboard, NEC PC-98 106 Keyboard | DIK_AT, DIK_CIRCUMFLEX, DIK_COLON, DIK_CONVERT, DIK_KANA, DIK_KANJI, DIK_NOCONVERT, DIK_YEN | DIK_APOSTROPHE, DIK_EQUALS, DIK_GRAVE
NEC PC-98 Standard Keyboard, NEC PC-98 Laptop Keyboard | DIK_AT, DIK_CIRCUMFLEX, DIK_COLON, DIK_F13, DIK_F14, DIK_F15, DIK_KANA, DIK_KANJI, DIK_NOCONVERT, DIK_NUMPADCOMMA, DIK_NUMPADEQUALS, DIK_STOP, DIK_UNDERLINE, DIK_YEN | DIK_APOSTROPHE, DIK_BACKSLASH, DIK_EQUALS, DIK_GRAVE, DIK_NUMLOCK, DIK_NUMPADENTER, DIK_RCONTROL, DIK_RMENU, DIK_RSHIFT, DIK_SCROLL
AX Keyboard | DIK_AX, DIK_CONVERT, DIK_KANJI, DIK_NOCONVERT, DIK_YEN | DIK_RCONTROL, DIK_RMENU
J-3100 Keyboard | DIK_KANA, DIK_KANJI, DIK_NOLABEL, DIK_YEN | DIK_RCONTROL, DIK_RMENU


Mouse Device Constants

Mouse device constants, defined in Dinput.h, represent offsets within a mouse device's data packet, the DIMOUSESTATE structure. The data at a given offset is associated with a device object (button or axis). Typically, these values will be used in the dwOfs member of the DIDEVICEOBJECTDATA, DIOBJECTDATAFORMAT or DIDEVICEOBJECTINSTANCE structures.

The mouse device constants are the following:

DIMOFS_BUTTON0 | Offset of the data representing the state of mouse button 0.
DIMOFS_BUTTON1 | Offset of the data representing the state of mouse button 1.
DIMOFS_BUTTON2 | Offset of the data representing the state of mouse button 2.
DIMOFS_BUTTON3 | Offset of the data representing the state of mouse button 3.
DIMOFS_X | Offset of the data representing the mouse's position on the x-axis.
DIMOFS_Y | Offset of the data representing the mouse's position on the y-axis.
DIMOFS_Z | Offset of the data representing the mouse's position on the z-axis.


Joystick Device Constants

Joystick device constants represent offsets within a joystick device's data packet, the DIJOYSTATE structure. The data at a given offset is associated with a device object; that is, a button or axis. Typically, these values will be used in the dwOfs member of the DIDEVICEOBJECTDATA, DIOBJECTDATAFORMAT or DIDEVICEOBJECTINSTANCE structures.

The following macros return a constant indicating the offset of the data for a particular button or axis relative to the beginning of the DIJOYSTATE structure:

DIJOFS_BUTTON0 to DIJOFS_BUTTON31 or DIJOFS_BUTTON(n) | A button.
DIJOFS_POV(n) | A point-of-view indicator.
DIJOFS_RX | The x-axis rotation.
DIJOFS_RY | The y-axis rotation.
DIJOFS_RZ | The z-axis rotation (rudder).
DIJOFS_X | The x-axis.
DIJOFS_Y | The y-axis.
DIJOFS_Z | The z-axis.
DIJOFS_SLIDER(n) | A slider axis.


Return Values

This table lists the HRESULT values that can be returned by DirectInput methods and functions. Errors are represented by negative values and cannot be combined.

For a list of the error values each method or function can return, see the individual descriptions. Lists of error codes in the documentation are necessarily incomplete. For example, any DirectInput method can return DIERR_OUTOFMEMORY even though the error code is not explicitly listed as a possible return value in the documentation for that method.

DI_BUFFEROVERFLOW
The device buffer overflowed and some input was lost. This value is equal to the S_FALSE standard COM return value.
DI_DOWNLOADSKIPPED
The parameters of the effect were successfully updated, but the effect could not be downloaded because the associated device was not acquired in exclusive mode.
DI_EFFECTRESTARTED
The effect was stopped, the parameters were updated, and the effect was restarted.
DI_NOEFFECT
The operation had no effect. This value is equal to the S_FALSE standard COM return value.
DI_NOTATTACHED
The device exists but is not currently attached. This value is equal to the S_FALSE standard COM return value.
DI_OK
The operation completed successfully. This value is equal to the S_OK standard COM return value.
DI_POLLEDDEVICE
The device is a polled device. As a result, device buffering will not collect any data and event notifications will not be signaled until the IDirectInputDevice2::Poll method is called.
DI_PROPNOEFFECT
The change in device properties had no effect. This value is equal to the S_FALSE standard COM return value.
DI_TRUNCATED
The parameters of the effect were successfully updated, but some of them were beyond the capabilities of the device and were truncated to the nearest supported value.
DI_TRUNCATEDANDRESTARTED
Equal to DI_EFFECTRESTARTED | DI_TRUNCATED.
DIERR_ACQUIRED
The operation cannot be performed while the device is acquired.
DIERR_ALREADYINITIALIZED
This object is already initialized
DIERR_BADDRIVERVER
The object could not be created due to an incompatible driver version or mismatched or incomplete driver components.
DIERR_BETADIRECTINPUTVERSION
The application was written for an unsupported prerelease version of DirectInput.
DIERR_DEVICEFULL
The device is full.
DIERR_DEVICENOTREG
The device or device instance is not registered with DirectInput. This value is equal to the REGDB_E_CLASSNOTREG standard COM return value.
DIERR_EFFECTPLAYING
The parameters were updated in memory but were not downloaded to the device because the device does not support updating an effect while it is still playing.
DIERR_HASEFFECTS
The device cannot be reinitialized because there are still effects attached to it.
DIERR_GENERIC
An undetermined error occurred inside the DirectInput subsystem. This value is equal to the E_FAIL standard COM return value.
DIERR_HANDLEEXISTS
The device already has an event notification associated with it. This value is equal to the E_ACCESSDENIED standard COM return value.
DIERR_INCOMPLETEEFFECT
The effect could not be downloaded because essential information is missing. For example, no axes have been associated with the effect, or no type-specific information has been supplied.
DIERR_INPUTLOST
Access to the input device has been lost. It must be reacquired.
DIERR_INVALIDPARAM
An invalid parameter was passed to the returning function, or the object was not in a state that permitted the function to be called. This value is equal to the E_INVALIDARG standard COM return value.
DIERR_MOREDATA
Not all the requested information fitted into the buffer.
DIERR_NOAGGREGATION
This object does not support aggregation.
DIERR_NOINTERFACE
The specified interface is not supported by the object. This value is equal to the E_NOINTERFACE standard COM return value.
DIERR_NOTACQUIRED
The operation cannot be performed unless the device is acquired.
DIERR_NOTBUFFERED
The device is not buffered. Set the DIPROP_BUFFERSIZE property to enable buffering.
DIERR_NOTDOWNLOADED
The effect is not downloaded.
DIERR_NOTEXCLUSIVEACQUIRED
The operation cannot be performed unless the device is acquired in DISCL_EXCLUSIVE mode.
DIERR_NOTFOUND
The requested object does not exist.
DIERR_NOTINITIALIZED
This object has not been initialized.
DIERR_OBJECTNOTFOUND
The requested object does not exist.
DIERR_OLDDIRECTINPUTVERSION
The application requires a newer version of DirectInput.
DIERR_OTHERAPPHASPRIO
Another application has a higher priority level, preventing this call from succeeding. This value is equal to the E_ACCESSDENIED standard COM return value. This error can be returned when an application has only foreground access to a device but is attempting to acquire the device while in the background.
DIERR_OUTOFMEMORY
The DirectInput subsystem couldn't allocate sufficient memory to complete the call. This value is equal to the E_OUTOFMEMORY standard COM return value.
DIERR_READONLY
The specified property cannot be changed. This value is equal to the E_ACCESSDENIED standard COM return value.
DIERR_REPORTFULL
More information was requested to be sent than can be sent to the device.
DIERR_UNPLUGGED
The operation could not be completed because the device is not plugged in.
DIERR_UNSUPPORTED
The function called is not supported at this time. This value is equal to the E_NOTIMPL standard COM return value.
E_PENDING
Data is not yet available.


DirectInput Samples

The following sample programs demonstrate the use and capabilities of DirectInput:

  • FFDonuts Sample
  • JoyFFeed Sample
  • JoystImm Sample
  • KeybdBuf Sample
  • KeybdImm Sample
  • MouseExc Sample
  • MouseNon Sample
  • Scrawl Sample

In addition to the samples that come complete with source code, the DirectX Programmer's Reference includes a utility (in the \Bin directory of the DirectInput samples) called DirectInput Quick Test (Diquick.exe). This is a tool for learning about driver support for devices and experimenting with device parameters.

Although DirectX samples include Microsoft® Visual C++® project workspace files, you might need to verify other settings in your development environment to ensure that the samples compile properly. For more information, see Compiling DirectX Samples and Other DirectX Applications.


FFDonuts Sample

Description

This is a variation on the Space Donuts sample program that adds force-feedback output if a force-feedback joystick is installed in your computer.

Path

Source: (SDK root)\Samples\Multimedia\DInput\Src\FFdonuts

Executable: (SDK root)\Samples\Multimedia\DInput\Bin

User's Guide

When the program is started, you see a dialog box that lets you set the magnitude of the force feedback effects.

When your ship appears, move the joystick forward to accelerate forward and pull it back to decelerate or move backward. Moving the joystick left or right rotates the ship. Press the trigger button to fire. Press the second button to activate the shields. Observe the force feedback effects as you fire, collide with objects, and bounce off the edge of the screen.

Programming Notes

The force feedback routines are in Input.c. The program illustrates the use of constant and periodic effects, envelopes, and gain. Note that the fire-button effect is played in response to an ordinary input event rather than being associated with a trigger button in the DIEFFECT structure.

See Also

Space Donuts


JoyFFeed Sample

Description

This application applies raw forces to a force feedback joystick, illustrating how a simulator-type application can use force feedback to generate forces computed by a physics engine.

You must have a force feedback device connected to your system in order to run the application.

Path

Source: (SDK root)\Samples\Multimedia\DInput\Src\JoyFFeed

Executable: (SDK root)\Samples\Multimedia\DInput\Bin

User's Guide

When you run the application, it displays a window with a crosshair and a black spot in it. Click the mouse anywhere within the window's client area to move the black spot. (Note that moving the joystick handle does not do anything.) JoyFFeed exerts a constant force on the joystick handle from the direction of the spot, in proportion to the distance from the crosshair. You can also hold down the mouse button and move the spot continuously.

Programming Notes

This sample program enumerates the input devices and acquires the first force-feedback joystick that it finds. If none are detected, it displays a message and terminates.

When the user moves the black spot, the joySetForcesXY function converts the cursor coordinates to a force direction and magnitude. This data is used to modify the parameters of the constant force effect.


JoystImm Sample

Description

The JoysImm program obtains and displays joystick data.

Path

Source: (SDK root)\Samples\Multimedia\DInput\Src\JoystImm

Executable: (SDK root)\Samples\Multimedia\DInput\Bin

User's Guide

Observe how the displayed data changes when you move and twist the stick, rotate the throttle wheel, and press buttons in various combinations.

Programming Notes

The application polls the joystick for immediate data in response to a timer set inside the dialog procedure.


KeybdBuf Sample

Description

The KeybdBuf program obtains and displays keyboard data.

Path

Source: (SDK root)\Samples\Multimedia\DInput\src\KeybdBuf

Executable: (SDK root)\Samples\Multimedia\DInput\bin

User's Guide

Each time you press or release a key, the event is recorded on the screen. Keys are identified by their index values (see Keyboard Device Constants).

Programming Notes

This sample illustrates how an application can use DirectInput to obtain buffered keyboard data.


KeybdImm Sample

Description

The KeybdImm program obtains and displays keyboard data.

Path

Source: (SDK root)\Samples\Multimedia\DInput\Src\KeybdImm

Executable: (SDK root)\Samples\Multimedia\DInput\Bin

User's Guide

Hold down one or more keys and the index value of each key (see Keyboard Device Constants) is shown.

Programming Notes

This sample illustrates how an application can use DirectInput to obtain immediate keyboard data. Approximately 30 times per second the application calls IDirectInputDevice::GetDeviceState and displays a string containing the values of all the keys that are down.


MouseExc Sample

Description

The MouseExc program demonstrates how to initialize and get immediate data from a DirectInput device.

Path

Source: (SDK root)\Samples\Multimedia\DInput\Src\MouseExc

Executable: (SDK root)\Samples\Multimedia\DInput\Bin

User's Guide

Move the mouse around and observe how the change in coordinates is displayed. Hold down a mouse button and its number is shown. Note that the system cursor is not present.

Programming Notes

This sample illustrates how an application can use DirectInput to obtain relative mouse data in exclusive foreground mode. Approximately 30 times per second the program displays the change in mouse coordinates since the last call to IDirectInputDevice::GetDeviceState.


MouseNon Sample

Description

The MouseNon program demonstrates how to initialize and get immediate data from a DirectInput device.

Path

Source: (SDK root)\Samples\Multimedia\DInput\Src\MouseNon

Executable: (SDK root)\Samples\Multimedia\DInput\Bin

User's Guide

Move the mouse around and observe how the change in coordinates is displayed. Hold down a mouse button and its number is shown. Note that the cursor doesn't have to be in the application window, but the application does have to be in the foreground.

Programming Notes

This sample illustrates how an application can use DirectInput to obtain relative mouse data in non-exclusive foreground mode. Approximately 30 times per second the program displays the change in mouse coordinates since the last call to IDirectInputDevice::GetDeviceState.


Scrawl Sample

Description

The Scrawl application demonstrates use of the mouse in exclusive mode in a windowed application.

Path

Source: (SDK root)\Samples\Multimedia\DInput\Src\Scrawl

Executable: (SDK root)\Samples\Multimedia\DInput\Bin

User's Guide

The main mouse button is always the left button, and the secondary button is always the right button, regardless of any settings the user may have made in Control Panel.

To scrawl, hold down the left button and move the mouse. Click the right mouse button to invoke a pop-up menu. From the pop-up menu you can clear the client window, set the mouse sensitivity, or close the application.

Programming Notes

The Scrawl application demonstrates many aspects of DirectInput programming, including the following:

  • Using the mouse in exclusive mode in a windowed application.
  • Releasing the mouse when Windows needs to use it for menu access.
  • Reacquiring the mouse when Windows no longer needs it.
  • Reading buffered device data.
  • Deferring screen updates till movement on both axes has been fully processed.
  • Event notifications of device activity.
  • Restricting the cursor to an arbitrary region.
  • Scaling raw mouse coordinates before using them.
  • Using relative axis mode.


DirectSetup

This section provides information about the DirectSetup component of the DirectX® application programming interface (API) in the Platform Software Development Kit (SDK). Information is found under the following main headings:

  • About DirectSetup
  • DirectSetup Essentials
  • DirectSetup Reference
  • DirectSetup Samples


About DirectSetup

DirectSetup is a simple application programming interface (API) that provides you with one-call installation of the DirectX components. This is more than a convenience—DirectX is a complex product, and installing it is an involved task. You should not attempt to install DirectX manually.

DirectSetup also provides an automated way to install the appropriate Microsoft® Windows® registry information for applications that use the DirectPlayLobby object. This registry information is required for the DirectPlayLobby object to enumerate and start the application.

DirectSetup includes the following API functions:

DirectXRegisterApplication
DirectXUnRegisterApplication
DirectXSetup
DirectXSetupSetCallback

It also includes a prototype DirectXSetupCallbackFunction that can be defined by an application in order to customize the user interface during the installation process. The DirectX Programmer's Reference includes a sample application that demonstrates the use of this callback function; for more information, see Dinstall.


DirectSetup Essentials

This section contains general information about the DirectSetup component. The following topics are discussed:

  • Setup Overview for DirectSetup
  • Preparing the Setup Folder
  • Customizing Setup
  • Testing the Setup Program
  • Enabling AutoPlay


Setup Overview for DirectSetup

Applications and games that depend on DirectX use the DirectXSetup function to install the necessary system components into an existing Windows installation. The function optionally updates the display and audio drivers for optimal support of DirectX. Typically you would call DirectXSetup from the program you are using to install your own application files.

Note The DirectXSetup function overwrites system components from previous versions of DirectX. For example, if you install DirectX 6.0 on a system that already has DirectX 5.0 components, all DirectX 5.0 components will be overwritten. Because all DirectX components comply with Component Object Model (COM) backward compatibility rules, software written for DirectX 5.0 will continue to function properly.

The DirectXSetup function can tell when DirectX components, display drivers, and audio drivers need to be upgraded. It can also distinguish whether or not these components can be upgraded without adversely affecting the Windows operating system. This is said to be a "safe" upgrade. It is important to note that the upgrade is safe for the operating system, not necessarily for the applications running on the computer. Some hardware-dependent applications can be negatively affected by an upgrade that is safe for Windows.

By default, the DirectXSetup function performs only safe upgrades. If the upgrade of a device driver may adversely affect the operation of Windows, the upgrade is not performed.

During the setup process, DirectSetup creates a backup copy of the system components and drivers that are replaced. These can be restored if problems occur.

When display or audio drivers are upgraded, the DirectXSetup function uses a database created by Microsoft to manage the process. The database contains information on existing drivers that are provided by Microsoft, the manufacturers of the hardware, or the vendors of the hardware. This database describes the upgrade status of each driver, based on testing done at Microsoft and other sites.

You should check the value returned by DirectXSetup. If it is DSETUPERR_SUCCESS_RESTART, notify the user that changes will not take effect without a restart, and offer the choice of restarting immediately. See Dinstall.c in the Dinstall sample application for an example of how to do this.


Preparing the Setup Folder

The DirectXSetup function takes a parameter, lpszRootPath, that points to the root directory of the installation. Optionally, it can be NULL to indicate that the root path is the current directory—that is, the directory where your setup program resides.

The root directory must contain Dsetup.dll, Dsetup16.dll, and Dsetup32.dll. It must also have a folder named "DirectX" (not case sensitive) containing all the redistributable files and drivers. To create the proper structure on your application setup disc, you should simply copy the entire contents of the Redist\DirectX6 folder on the DirectX SDK disc into the root path of your setup program. Note that this folder was not copied to your development machine when you installed the SDK, so you have to get it from the original disc.


Customizing Setup

DirectSetup allows you to define a callback function for customizing the DirectX setup process. In the DirectSetup documentation, this callback function is referred to as DirectXSetupCallbackFunction, but you can give it any name you like.

If a callback function is not provided by the setup program, the DirectXSetup function displays status and error information in a dialog box and obtains user input by calling the Win32® MessageBox function. If a callback is provided, the information that would have been used to create the status dialog or message box is instead passed to the callback. The callback function is called once for each DirectX component and device driver that can be installed or upgraded.

You might use the callback function to do the following:

  • Employ a custom interface. Your setup program might display messages in ways other than by using MessageBox or standard Windows dialog boxes. The callback function enables you to integrate messages for the DirectX component of your installation into your own interface.
  • Update a progress indicator.
  • Suppress the display of status and error messages. Designers of programs for novice users may want to suppress error messages and let the setup program handle errors and make upgrade choices silently. This approach requires a greater development effort for the setup program, but might be appropriate for the target audience.

The following topics help you customize your setup:

  • Creating a DirectSetup Callback Function
  • Setting the Callback Function
  • Using Upgrade Flags in the Callback Function
  • Overriding Defaults in the Callback Function


Creating a DirectSetup Callback Function

In order to customize the setup process, you must first create a callback function that conforms to the DirectXSetupCallbackFunction prototype, as in the following declaration:

DWORD WINAPI DirectXSetupCallbackFunction(
        DWORD dwReason,
        DWORD dwMsgType,
        LPSTR szMessage,
        LPSTR szName,
        void *pInfo);

In this example, adapted from the Dinstall sample application, the name of the function is the same as that of the prototype, but this is optional. The parameter names differ slightly from those in the prototype declared in Dsetup.h, and will be used throughout the following discussion.

Parameters

The dwReason parameter indicates why the callback function has been called. The possible values are listed and explained in the reference for DirectXSetupCallbackFunction.

The dwMsgType parameter receives flags equivalent to those that DirectSetup would, by default, pass to MessageBox, such as those controlling what buttons and icon are displayed. Of special interest to you are the button flags, which you use to determine what return values are expected. If this value is 0, the event never requires user input and DirectSetup would normally display a status message.

The szMessage parameter receives the same text that DirectSetup would otherwise pass to the status dialog or to MessageBox.

When a driver is a candidate for upgrading, its name is passed in the szName parameter and pInfo points to information about the how the upgrade will or should be handled—for example, whether DirectSetup recommends that the old driver be kept or upgraded. For more information, see Using Upgrade Flags in the Callback Function.

The way your callback function interprets the parameters is entirely up to you. Typically you would choose which messages to display (based on dwReason) and when to present the user with alternatives, and you would modify the interface accordingly.

Return Value

The value returned by your callback function must conform to the following rules:

  • When dwMsgType is 0, the return value must be IDOK. In this case, there are no choices to be made by the user. (Your application, of course, is free to display a status message even though no input is required.)
  • If dwMsgType is nonzero, the return value must be the same as would have been returned by MessageBox, given the equivalent choice by the user.

To determine the appropriate return value in the second case, you must test dwMsgType for the buttons that would normally have been put in a message box. The following example, from the GetReply function in Dinstall, shows how this can be done:

/* The global g_wReply identifies the custom dialog button
   that has been selected by the user. */

switch (dwMsgType & 0x0000000F)
{
   / * There would normally have been an OK and a Cancel button.
       Our IDBUT1 is equivalent to the OK button. If the user didn't
       choose that, it was a Cancel. */
    case MB_OKCANCEL:
        wDefaultButton = (g_wReply == IDBUT1) ? IDOK : IDCANCEL;
        break;

    / * And so on with the other button combinations. */
    case MB_OK:
        wDefaultButton = IDOK;
        break;
    case MB_RETRYCANCEL:
        wDefaultButton = (g_wReply == IDBUT1) ? IDRETRY : IDCANCEL;
        break;
    case MB_ABORTRETRYIGNORE:
        if (g_wReply == IDBUT1)
            wDefaultButton = IDABORT;
        else if (g_wReply == IDBUT2)
            wDefaultButton = IDRETRY;
        else
            wDefaultButton = IDIGNORE;
        break;
    case MB_YESNOCANCEL:
        if (g_wReply == IDBUT1)
            wDefaultButton = IDYES;
        else if (g_wReply == IDBUT2)
            wDefaultButton = IDNO;
        else
            wDefaultButton = IDCANCEL;
        break;
    case MB_YESNO:
        wDefaultButton = (g_wReply == IDBUT1) ? IDYES : IDNO;
        break;
    default:
        wDefaultButton = IDOK;
}

This routine translates button clicks from the custom interface into the equivalent button identifiers in the standard dialog box that DirectSetup would otherwise create. The wDefaultButton variable is set to the identifier of the equivalent standard dialog box button, and it is this value that will ultimately be returned from the callback function.

Remember, you don't necessarily have to give the user a choice even when dwMsgType is nonzero. You might decide, for example, to upgrade drivers automatically in a case where DirectSetup would normally ask for confirmation from the user. The Dinstall sample does this when the user has asked to see only problem messages and the driver upgrade is considered safe:

case DSETUP_CB_UPGRADE_SAFE:
    switch (dwMsgType & 0x0000000F)
    {
        case MB_YESNO:
        case MB_YESNOCANCEL:
            return IDYES;
        case MB_OKCANCEL:
        case MB_OK:
        default:
            return IDOK;
    }
    break;

The callback function returns either IDYES or IDOK, depending on which button would have represented a positive choice in a dialog box asking the user whether or not the upgrade should proceed.


Setting the Callback Function

Before calling DirectXSetup, you must notify DirectSetup that you wish to use a callback. You do so by calling the DirectXSetupSetCallback function, passing a pointer to the callback as a parameter. The following example shows how this is done:

DirectXSetupSetCallback(
        (DSETUP_CALLBACK) DirectXSetupCallbackFunction);


Using Upgrade Flags in the Callback Function

When the application-defined callback function DirectXSetupCallbackFunction is called by the DirectXSetup function, it is passed a parameter that contains the reason the callback function was invoked. If the reason is DSETUP_CB_MSG_CHECK_DRIVER_UPGRADE, the pInfo parameter points to a DSETUP_CB_UPGRADEINFO structure containing flags that summarize the DirectXSetup function's recommendations on how the upgrade of DirectX components and drivers should be performed. The structure member containing the flags is called UpgradeFlags.

The flags fall into the following categories:

Primary Upgrade Flags
These flags are mutually exclusive. One of them is always present in the UpgradeFlags structure member. You can extract it by performing a bitwise AND with DSETUP_CB_UPGRADE_TYPE_MASK.

DSETUP_CB_UPGRADE_FORCE

DSETUP_CB_UPGRADE_KEEP

DSETUP_CB_UPGRADE_SAFE

DSETUP_CB_UPGRADE_UNKNOWN

Secondary Upgrade Flags
Any or all of these flags may be present.

DSETUP_CB_UPGRADE_CANTBACKUP

DSETUP_CB_UPGRADE_HASWARNINGS

Device Active Flag
This flag is present if the device whose driver is being upgraded is active. It may be combined with any of the others.

DSETUP_CB_UPGRADE_DEVICE_ACTIVE

Device Class Flags
These flags are mutually exclusive. One of them is always present.

DSETUP_CB_UPGRADE_DISPLAY

DSETUP_CB_UPGRADE_MEDIA

In summary: every time the Reason parameter has the value DSETUP_CB_MSG_CHECK_DRIVER_UPGRADE, the UpgradeFlags member of the structure pointed to by pInfo contains one Primary Upgrade Flag, zero or more Secondary Upgrade Flags, zero or one Device Active Flag, and one Device Class Flag.

If the UpgradeFlags member is set to DSETUP_CB_UPGRADE_KEEP, the DirectX component or device driver can't be upgraded. Performing an upgrade would cause Windows to cease functioning properly. The DirectXSetup function will not perform an upgrade on the component or driver.

A value of DSETUP_CB_UPGRADE_FORCE in UpgradeFlags means that the component or driver must be upgraded for Windows to function properly. The DirectXSetup function will upgrade the driver or component. It is possible that the upgrade may adversely affect some programs on the system. When the DirectXSetup function detects this condition, the UpgradeFlags member is set to (DSETUP_CB_UPGRADE_FORCE | DSETUP_CB_UPGRADE_HAS_WARNINGS). When this occurs, the DirectXSetup function will perform the upgrade but issue a warning to the user.

Components and drivers are considered safe for upgrade if they will not adversely affect the operation of Windows when they are installed. In this case, the UpgradeFlags member is set to DSETUP_CB_UPGRADE_SAFE. It is possible that the upgrade can be safe for Windows, but still cause problems for programs installed on the system. When DirectXSetup detects this condition, the UpgradeFlags member contains the value (DSETUP_CB_UPGRADE_SAFE | DSETUP_CB_UPGRADE_HAS_WARNINGS). If this condition occurs, the default action for the DirectXSetup function is not to perform the upgrade.


Overriding Defaults in the Callback Function

The application-defined function DirectXSetupCallbackFunction can override some of the default behaviors of the DirectXSetup function through its return value.

For example, the default behavior for DirectXSetup is not to install a component if the upgrade type in the structure pointed to by the pInfo parameter is set to (DSETUP_CB_UPGRADE_SAFE | DSETUP_CB_UPGRADE_HAS_WARNINGS). In this case, the MsgType parameter of the callback function is set to (MB_YESNO | MB_DEFBUTTON2). Without a callback function, DirectSetup would present the user with a dialog box whose default button was No. If the callback function does not seek user input but accepts the default, it returns IDNO. To override the default, the callback function returns IDYES. If it does override the default, the user will be notified by the DirectXSetup function.


Testing the Setup Program

To test the DirectSetup component of your setup program, compile a version in which the DSETUP_TESTINSTALL flag is passed to the DirectXSetup function. Set up the installation directory as described under Preparing the Setup Folder.

Now, when you run your setup program, DirectSetup will go through the motions of installing DirectX, including calls to a callback function if you have provided one, without actually installing any components.


Enabling AutoPlay

If you are building an AutoPlay compact disc title, copy the Autorun.inf file in the root directory of the DirectX SDK compact disc to the root of your application directory. This text file contains the following information:

[autorun]
OPEN=SETUP.EXE

If your application's setup program is called Setup.exe, you will not have to make any changes to this file; otherwise, edit this file to contain the name of your setup program. For more information, see Autorun.inf.


DirectSetup Reference

This section contains reference information for the API elements that DirectSetup provides. Reference material is divided into the following categories:

  • Functions
  • Structures
  • Return Values


Functions

This section contains information on the following global functions used with DirectSetup:

  • DirectXRegisterApplication
  • DirectXSetup
  • DirectXSetupGetVersion
  • DirectXSetupSetCallback
  • DirectXSetupCallbackFunction
  • DirectXUnRegisterApplication


DirectXRegisterApplication

The DirectXRegisterApplication function registers an application as one designed to work with DirectPlayLobby.

int WINAPI DirectXRegisterApplication(
  HWND hWnd,
  LPDIRECTXREGISTERAPP lpDXRegApp
);

Parameters

hWnd
Handle to the parent window. If this parameter is set to NULL, the desktop is the parent window.
lpDXRegApp
Address of the DIRECTXREGISTERAPP structure that contains the registry entries that are required for the application to function properly with DirectPlayLobby.

Return Values

If this function is successful, it returns TRUE.

If it is not successful, it returns FALSE. Use the GetLastError Win32 function to get extended error information.

Remarks

The DirectXRegisterApplication function inserts the registry entries needed for an application to operate with DirectPlayLobby. If these registry entries are added with DirectXRegisterApplication, they should be removed with DirectXUnRegisterApplication when the application is uninstalled.

Many commercial install programs will remove registry entries automatically when a program in uninstalled. However, such a program will only do so if it added the registry entries itself. If the DirectPlayLobby registry entries are added by DirectXRegisterApplication, commercial install programs will not delete the registry entries when the application is uninstalled. Therefore, DirectPlayLobby registry entries that are created by DirectXRegisterApplication should be deleted by DirectXUnRegisterApplication.

Registry entries needed for DirectPlayLobby access can be created without the use of the DirectXRegisterApplication function. This, however, is not generally recommended. See Registering Lobby-able Applications in the DirectPlay® documentation.

QuickInfo

Windows NT: Requires version 4.0 SP3 or later.
Windows: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsetup.h.
Import Library: Use dsetup.lib.

See Also

DirectXUnRegisterApplication


DirectXSetup

The DirectXSetup function installs one or more DirectX components.

int WINAPI DirectXSetup(
  HWND hWnd,
  LPSTR lpszRootPath,
  DWORD dwFlags
);

Parameters

hWnd
Handle to the parent window for the setup dialog boxes.
lpszRootPath
Pointer to a string that contains the root path of the DirectX component files. This string must specify a full path to the directory that contains the files Dsetup.dll, Dsetup16.dll, and Dsetup32.dll, as well as a "DirectX" (not case sensitive) directory containing redistributable files. If this value is NULL, the current working directory is used.
dwFlags
One or more flags indicating which DirectX components should be installed. A full installation (DSETUP_DIRECTX) is recommended.
DSETUP_D3D | Obsolete. DirectX 3 programs that use this flag will install all DirectX components.
DSETUP_DDRAW | Obsolete. DirectX 3 programs that use this flag will install all DirectX components.
DSETUP_DDRAWDRV | Installs display drivers provided by Microsoft.
DSETUP_DINPUT | Obsolete. DirectX 3 programs that use this flag will install all DirectX components.
DSETUP_DIRECTX | Installs DirectX run-time components as well as DirectX-compatible display and audio drivers.
DSETUP_DIRECTXSETUP | Obsolete. DirectX 3 programs that use this flag will install all DirectX components.
DSETUP_DPLAY | Obsolete. DirectX 3 programs that use this flag will install all DirectX components.
DSETUP_DPLAYSP | Obsolete. DirectX 3 programs that use this flag will install all DirectX components.
DSETUP_DSOUND | Obsolete. DirectX 3 programs that use this flag will install all DirectX components.
DSETUP_DSOUNDDRV | Installs audio drivers provided by Microsoft.
DSETUP_DXCORE | Installs DirectX run-time components. Does not install DirectX-compatible display and audio drivers.
DSETUP_TESTINSTALL | Performs a test installation. Does not actually install new components.

Return Values

If this function is successful, it returns DSETUPERR_SUCCESS, or DSETUPERR_SUCCESS_RESTART if the user must restart the system in order for changes to take effect.

If it is not successful, it returns an error code. For a list of possible return codes, see Return Values.

Remarks

Before you use the DirectXSetup function in your setup program, you should ensure that there is at least 15 MB of available disk space on the user's system. This is the maximum space required for DirectX to set up the appropriate files. If the user's system already contains the DirectX files, this space is not needed.

QuickInfo

Windows NT: Requires version 4.0 SP3 or later.
Windows: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsetup.h.
Import Library: Use dsetup.lib.


DirectXSetupGetVersion

The DirectXSetupGetVersion function retrieves the version number of the DirectX components that are currently installed.

INT WINAPI DirectXSetupGetVersion(
  DWORD   *pdwVersion,
  DWORD   *pdwRevision
);

Parameters

pdwVersion
Address of a variable to receive the version number. Can be NULL if the version number is not wanted.
pdwRevision
Address of a variable to receive the revision number. Can be NULL if the revision number is not wanted.

Return Values

If the function is successful, it returns nonzero.

If it is not successful, it returns zero.

Remarks

The DirectXSetupGetVersion function can be used to retrieve the version and revision numbers before or after the DirectXSetup function is called. If it is called before the DirectXSetup function is invoked, it gives the version and revision numbers of the DirectX components that are currently installed. If it is called after the DirectXSetup function is called, but before the computer has been rebooted, it will give the version and revision numbers of the DirectX components that will take effect after the computer is restarted.

The version number in the pdwVersion parameter is composed of the major version number and the minor version number. The major version number will be in the 16 most significant bits of the DWORD when this function returns. The minor version number will be in the 16 least significant bits of the DWORD when this function returns. The version numbers can be interpreted as follows:

DirectX Version | Value Pointed At By pdwVersion
DirectX 1 | 0x00040001
DirectX 2 | 0x00040002
DirectX 3 | 0x00040003
DirectX 5.0 | 0x00040005
DirectX 6.0 | 0x00040006

Note that there is no version 4 of DirectX.

The version number in the pdwRevision parameter is composed of the release number and the build number. The release number will be in the 16 most significant bits of the DWORD when this function returns. The build number will be in the 16 least significant bits of the DWORD when this function returns.

The following sample code fragment demonstrates how the information returned by DirectXSetupGetVersion can be extracted and used.

DWORD dwVersion;
DWORD dwRevision;
if (DirectXSetupGetVersion(&dwVersion, &dwRevision))
{
    printf("DirectX version is %d.%d.%d.%d\n",
           HIWORD(dwVersion), LOWORD(dwVersion),
           HIWORD(dwRevision), LOWORD(dwRevision));
}

Version and revision numbers can be concatenated into a 64-bit quantity for comparison. The version number should be in the 32 most significant bits and the revision number should be in the 32 least significant bits.

QuickInfo

Windows NT: Requires version 4.0 SP3 or later.
Windows: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsetup.h.
Import Library: Use dsetup.lib.

See Also

DirectXSetup


DirectXSetupSetCallback

The DirectXSetupSetCallback sets a pointer to a callback function that is periodically called by DirectXSetup. The callback function can be used for setup progress notification and to implement a custom user interface for an application's setup program. For information on the callback function, see DirectXSetupCallbackFunction. If a setup program does not provide a callback function, the DirectXSetupSetCallback function should not be invoked.

INT WINAPI DirectXSetupSetCallback(
  DSETUP_CALLBACK   Callback
);

Parameters

Callback
Pointer to a callback function.

Return Values

Currently returns zero.

Remarks

To set a callback function, DirectXSetupSetCallback must be called before the DirectXSetup function is called.

The name of the callback function passed to DirectXSetupSetCallback is supplied by the setup program. However, it must match the prototype given in DirectXSetupCallbackFunction.

QuickInfo

Windows NT: Requires version 4.0 SP3 or later.
Windows: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsetup.h.
Import Library: Use dsetup.lib.

See Also

DirectXSetupCallbackFunction, DirectXSetup


DirectXSetupCallbackFunction

DirectXSetupCallbackFunction is a placeholder name for an optional callback function supplied by the setup program. If present, it is called once for each step of the setup process.

DWORD DirectXSetupCallbackFunction(
  DWORD  Reason,
  DWORD  MsgType,
  char *szMessage,
  char *szName,
  void *pInfo
);

Parameters

Reason
Reason for the callback. It can be one of the following values:
DSETUP_CB_MSG_BEGIN_INSTALL
DirectXSetup is about to begin installing DirectX components and device drivers.
DSETUP_CB_MSG_BEGIN_INSTALL_DRIVERS
DirectXSetup is about to begin installing device drivers.
DSETUP_CB_MSG_BEGIN_INSTALL_RUNTIME
DirectXSetup is about to begin installing DirectX components.
DSETUP_CB_MSG_BEGIN_RESTORE_DRIVERS
DirectXSetup is about to begin restoring previous drivers.
DSETUP_CB_MSG_CANTINSTALL_BETA
A pre-release beta version of Windows 95 was detected. The DirectX component or device driver can't be installed.
DSETUP_CB_MSG_CANTINSTALL_NOTWIN32
The operating system detected is not a Windows 32-bit operating system. DirectX is not compatible with Windows 3.x.
DSETUP_CB_MSG_CANTINSTALL_NT
The DirectX component or device driver can't be installed on versions of Windows NT prior to version 4.0.
DSETUP_CB_MSG_CANTINSTALL_UNKNOWNOS
The operating system is unknown. The DirectX component or device driver can't be installed.
DSETUP_CB_MSG_CANTINSTALL_WRONGLANGUAGE
The DirectX component or device driver is not localized to the language being used by Windows.
DSETUP_CB_MSG_CANTINSTALL_WRONGPLATFORM
The DirectX component or device driver is for another type of computer.
DSETUP_CB_MSG_CHECK_DRIVER_UPGRADE
Driver is being considered for upgrade. Verification from user is recommended.
DSETUP_CB_MSG_INTERNAL_ERROR
An internal error has occurred. Setup of the DirectX component or device driver has failed.
DSETUP_CB_MSG_NOMESSAGE
No message to be displayed. The callback function should return.
DSETUP_CB_MSG_NOTPREINSTALLEDONNT
The DirectX component or device driver can't be installed on the version of Windows NT/Windows 2000 in use.
DSETUP_CB_MSG_PREINSTALL_NT
DirectX is already installed on the version of Windows NT/Windows 2000 in use.
DSETUP_CB_MSG_SETUP_INIT_FAILED
Setup of the DirectX component or device driver has failed.
MsgType
Contains flags that control the display of a message box. These flags can be passed to the MessageBox function. An exception is when MsgType is 0. In that case, the setup program can display status information but should not wait for input from the user.
szMessage
A localized character string containing error or status messages that can be displayed in a dialog box created with the MessageBox function.
szName
The value of szName is NULL unless the Reason parameter is DSETUP_CB_MSG_CHECK_DRIVER_UPGRADE. In that case, szName contains the name of driver to be upgraded.
pInfo
Pointer to a structure containing upgrade information. When Reason is DSETUP_CB_MSG_CHECK_DRIVER_UPGRADE, the setup program is in the process of upgrading a driver and asking the user whether the upgrade should take place. In this case, pInfo points to a DSETUP_CB_UPGRADEINFO structure containing information about the upgrade.

Return Values

The return value should be the same as would be returned by the MessageBox function, with one exception. If this function returns zero, the DirectXSetup function will perform the default action for upgrade of the DirectX component or driver.

Remarks

The name of the DirectXSetupCallbackFunction is supplied by the setup program. The DirectXSetupSetCallback function is used to pass the address of the callback function to DirectSetup.

If MsgType is equal to zero, the setup program may display status information, but it should not wait for user input. In this case the function should return IDOK.

QuickInfo

Windows NT: Requires version 4.0 SP3 or later.
Windows: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsetup.h.
Import Library: User-defined.

See Also

MessageBox, DirectXSetupSetCallback, Customizing Setup


DirectXUnRegisterApplication

The DirectXUnRegisterApplication function deletes the registration of an application designed to work with DirectPlayLobby.

int WINAPI DirectXUnRegisterApplication(
  HWND hWnd,
  LPGUID lpGUID
);

Parameters

hWnd
Handle to the parent window. Set this to NULL if the desktop is the parent window.
lpGUID
Pointer to a GUID that represents the DirectPlay application to be unregistered.

Return Values

If the function succeeds, the return value is TRUE meaning that the registration is successfully deleted.

If the function fails, the return value is FALSE.

Remarks

The DirectXUnRegisterApplication function removes registry the entries needed for an application to work with DirectPlayLobby. An uninstall program should only use DirectXUnRegisterApplication if it used DirectXRegisterApplication when the application was installed.

QuickInfo

Windows NT: Requires version 4.0 SP3 or later.
Windows: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsetup.h.
Import Library: Use dsetup.lib.

See Also

DirectXRegisterApplication


Structures

This section contains information about the following structures used with DirectSetup:

  • DIRECTXREGISTERAPP
  • DSETUP_CB_UPGRADEINFO

Note The memory for all DirectX structures must be initialized to zero before use. In addition, all structures that contain a dwSize member must set the member to the size of the structure, in bytes, before use. The following example from DirectDraw performs these tasks on a common structure, DDCAPS:

DDCAPS ddcaps; // Can't use this yet.

ZeroMemory(&ddcaps, sizeof(ddcaps));
ddcaps.dwSize = sizeof(ddcaps);

// Now the structure can be used.
.
.


DIRECTXREGISTERAPP

The DIRECTXREGISTERAPP structure contains the registry entries needed for applications designed to work with DirectPlayLobby.

typedef struct _DIRECTXREGISTERAPP {
    DWORD  dwSize;
    DWORD  dwFlags;
    LPSTR  lpszApplicationName;
    LPGUID lpGUID;
    LPSTR  lpszFilename;
    LPSTR  lpszCommandLine;
    LPSTR  lpszPath;
    LPSTR  lpszCurrentDirectory;
} DIRECTXREGISTERAPP, *PDIRECTXREGISTERAPP, *LPDIRECTXREGISTERAPP;

Members

dwSize
Size of the structure. Must be initialized to the size of the DIRECTXREGISTERAPP structure.
dwFlags
Reserved for future use.
lpszApplicationName
Name of the application.
lpGUID
Globally unique identifier (GUID) of the application.
lpszFilename
Name of the executable file to be called.
lpszCommandLine
Command-line arguments for the executable file.
lpszPath
Path of the executable file.
lpszCurrentDirectory
Current directory. This is typically the same as lpszPath.

QuickInfo

Windows NT: Requires version 4.0 SP3 or later.
Windows: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsetup.h.


DSETUP_CB_UPGRADEINFO

The DSETUP_CB_UPGRADEINFO structure is passed as a parameter to the application-defined DirectXSetupCallbackFunction. It contains valid information only when the Reason parameter is DSETUP_CB_MSG_CHECK_DRIVER_UPGRADE. Callback functions can use it to get status information on the upgrade that is about to be done.

typedef struct _DSETUP_CB_UPGRADEINFO {
    DWORD UpgradeFlags;
} DSETUP_CB_UPGRADEINFO;

Members

UpgradeFlags
One or more flags indicating the status of the upgrade. The following values are defined:
DSETUP_CB_UPGRADE_CANTBACKUP
The old system components can't be backed up. Upgrade can be performed, but the components or drivers can't be restored later.
DSETUP_CB_UPGRADE_DEVICE_ACTIVE
The device is currently in use.
DSETUP_CB_UPGRADE_DEVICE_DISPLAY
The device driver being upgraded is for a display device.
DSETUP_CB_UPGRADE_DEVICE_MEDIA
The device driver being upgraded is for a media device.
DSETUP_CB_UPGRADE_FORCE
Windows may not function correctly if the component is not upgraded. The upgrade will be performed.
DSETUP_CB_UPGRADE_HASWARNINGS
DirectSetup can upgrade the driver for this device, but doing so may affect one or more programs on the system. The szMessage parameter contains the names of which programs may be affected. Upgrade not recommended.
DSETUP_CB_UPGRADE_KEEP
The system may fail if this device driver is upgraded. Upgrade not allowed.
DSETUP_CB_UPGRADE_SAFE
DirectSetup can safely upgrade this device driver. Upgrade recommended. A safe upgrade will not adversely affect the operation of Windows. Some hardware-dependent programs may be adversely affected.
DSETUP_CB_UPGRADE_UNKNOWN
DirectSetup does not recognize the existing driver for this device. This value will occur frequently. Upgrading may adversely affect the use of the device. It is strongly recommended that the upgrade not be performed.

Remarks

You can use the DSETUP_CB_UPGRADE_TYPE_MASK value to extract the upgrade type (FORCE, KEEP, SAFE, or UNKNOWN) from UpgradeFlags.

QuickInfo

Windows NT: Requires version 4.0 SP3 or later.
Windows: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Header: Declared in dsetup.h.

See Also

DirectXSetupCallbackFunction


Return Values

The DirectXSetup function can return the following values. It can also return a standard COM error.

DSETUPERR_SUCCESS
Setup was successful and no restart is required.
DSETUPERR_SUCCESS_RESTART
Setup was successful and a restart is required.
DSETUPERR_BADSOURCESIZE
A file's size could not be verified or was incorrect.
DSETUPERR_BADSOURCETIME
A file's date and time could not be verified or were incorrect.
DSETUPERR_BADWINDOWSVERSION
DirectX does not support the Windows version on the system.
DSETUPERR_CANTFINDDIR
The setup program could not find the working directory.
DSETUPERR_CANTFINDINF
A required .inf file could not be found.
DSETUPERR_INTERNAL
An internal error occurred.
DSETUPERR_NEWERVERSION
A later version of DirectX has already been installed. Applications can safely ignore this error, because the newer version will not be overwritten and is fully compatible with applications written for earlier versions.
DSETUPERR_NOCOPY
A file's version could not be verified or was incorrect.
DSETUPERR_NOTPREINSTALLEDONNT
The version of Windows NT/Windows 2000 on the system does not contain the current version of DirectX. An older version of DirectX may be present, or DirectX may be absent altogether.
DSETUPERR_OUTOFDISKSPACE
The setup program ran out of disk space during installation.
DSETUPERR_SOURCEFILENOTFOUND
One of the required source files could not be found.
DSETUPERR_UNKNOWNOS
The operating system on your system is not currently supported.
DSETUPERR_USERHITCANCEL
The Cancel button was pressed before the application was fully installed.


DirectSetup Samples

This section provides a summary of the application in the DirectX SDK that is primarily intended to demonstrate the DirectSetup component. The following sample program demonstrates the use and capabilities of DirectSetup :

  • Dinstall Sample

Although DirectX samples include Microsoft® Visual C++® project workspace files, you might need to verify other settings in your development environment to ensure that the samples compile properly. For more information, see Compiling DirectX Samples and Other DirectX Applications.


Dinstall Sample

Description

Dinstall is an example of how to use DirectXSetup interfaces to install the DirectX subsystem and DirectX drivers. It shows how to use a callback function to present messages and get user input through a custom interface, in this case a simple modeless dialog box.

Path

Source: (SDK root)\Samples\Multimedia\Dxmisc\Src\Setup

Executable: (SDK root)\Samples\Multimedia\Dxmisc\Bin

User's Guide

First copy the entire contents of the Redist\DirectX6 folder from the DirectX SDK CD into the same folder as Dinstall.exe. In your development environment, set the working directory to this folder as well. (In Microsoft® Visual C++®, this setting is on the Debug page of the Project Settings dialog box.)

Run the program and select Start Install from the File menu. DirectSetup performs a simulated installation of DirectX (see Programming Notes) and advises you of its progress in a modeless dialog box. The Options menu allows you to change the level of messages shown. However, if you are performing only a simulated installation, you will never see problem or update messages.

Choose Get Version from the File menu. The program shows the version and revision number of DirectX currently installed on the system.

Programming Notes

The driver folders in \Redist\DirectX6\Directx\Drivers contain localized versions of Microsoft-provided DirectX drivers. You can delete any number of these folders from your working directory if you want to save disk space.

By default, the program passes DSETUP_TESTINSTALL to the DirectXSetup function. This means that no files are actually copied, nor is the registry modified. To perform a real installation, delete this flag from the call.

Dinstall employs a callback function to monitor the progress of installation and intercept messages. Depending on the user's preferred warning level, as tracked in g_fStatus, messages may be ignored or presented to the user in a modeless dialog box. If user input is required, the appropriate buttons are displayed and the GetReply function monitors the message queue until one of the buttons is pressed.


AutoPlay

The AutoPlay feature automatically starts an application on an AutoPlay-enabled compact disc. About AutoPlay describes the basic concept of what AutoPlay does. The Overview section covers how to use AutoPlay. The Reference section shows the details of writing AutoPlay applications.

  • About AutoPlay
  • AutoPlay Overview
  • AutoPlay Reference


About AutoPlay

Microsoft® AutoPlay is a feature of the Microsoft Windows® operating system. AutoPlay automates the procedures for installing and configuring products designed for Windows-based platforms that are distributed on compact discs. When you insert a compact disc containing AutoPlay into a CD-ROM drive on a computer running Windows, AutoPlay automatically starts an application on the compact disc that installs, configures, and runs the selected product.

You can use AutoPlay to install and run CD-ROM applications that run in Windows, whether the application is based on the MS-DOS® operating system, Windows 3.0, Windows 3.1, Windows 95, Windows 98, Windows NT® 4.0, or Windows 2000. If you want your CD-ROM product to display the Microsoft Windows 95 logo, it must be enabled for AutoPlay.

Note MS-DOS, Windows versions prior to Windows 95, and Windows NT versions 3.51 and earlier do not support AutoPlay. Adding AutoPlay to a compact disc, however, does not hinder or alter user interaction on computers running one of these operating systems.


AutoPlay Overview

For general information about how to use the AutoPlay component, refer to the following topics:

  • How AutoPlay Works
  • Autorun.inf
  • Tips for Writing AutoPlay Applications
  • Suppressing AutoPlay
  • AutoPlay for MS-DOS-Based Applications


How AutoPlay Works

The implementation of AutoPlay relies on the following items:

  • A set of 32-bit CD-ROM device drivers. These device drivers detect when a user inserts a compact disc into a CD-ROM drive for Windows 32-bit operating systems; device drivers for MS-DOS or previous versions of Windows do not.
  • An Autorun.inf file on the compact disc. When you insert a disc into a CD-ROM drive on a computer running Windows 95, Windows 98, Windows NT 4.0, or Windows 2000, the system immediately checks to see if the disc has a personal computer file system. If it does, the system searches for a file named Autorun.inf. This file specifies the application that AutoPlay runs. It can contain other information as well. For more information, see Autorun.inf.
  • A startup application on the compact disc. Although you can start any application on the disc by specifying it in the Autorun.inf file, typically the application performs a startup or installation function. By including your own startup application, you can control the install, uninstall, and run processes for your product.


Autorun.inf

The Autorun.inf file is a text file located in the root directory of the CD on which your DirectX® application is shipped. This file contains the name of the startup program on the disc. This startup program runs automatically when the disc is inserted in the CD-ROM drive. The Autorun.inf file also contains the file name of the icon that you want to represent your application's CD in the Windows user interface. In addition, the Autorun.inf file can contain optional menu commands that you want added to the shortcut menu. These menu commands are displayed when the user right-clicks the CD-ROM icon.

The following is an example of a minimal Autorun.inf file.

[autorun]
open=filename.exe
icon=filename.ico

The [autorun] section identifies the lines that follow it as AutoPlay commands. An [autorun] section is required in every Autorun.inf file. The open command specifies the path and file name of the startup application. The icon command specifies the file name that contains the icon.

The Autorun.inf file also can contain architecture-specific sections for Windows NT 4.0 running on RISC processors. For each type of processor architecture, add a section to the Autorun.inf file that contains the file name of the startup application you want to run for that architecture. The following table lists the commands used for the architectures that AutoPlay supports.

Architecture | Section Title
386 or higher | [autorun]
MIPS | [autorun.mips]
DEC Alpha | [autorun.alpha]
PowerPC | [autorun.ppc]

The following example shows how to create an Autorun.inf file that runs different startup applications depending on the computer architecture:

[autorun]
open=filename.exe
icon=filename.ico

[autorun.mips]
open=filenam2.exe
icon=filename.ico

[autorun.alpha]
open=filenam3.exe
icon=filename.ico

[autorun.ppc]
open=filenam4.exe
icon=filename.ico

The shell checks for an architecture-specific section first. If it does not find one, it uses the information in the [autorun] section. After the shell finds a section, it ignores all the other sections, so each section must contain all the information for that architecture.


Tips for Writing AutoPlay Applications

This section presents helpful guidelines for writing AutoPlay applications:

  • Opening a Startup Application
  • Loading in the Background
  • Conserving Hard Disk Space
  • Using the Registry
  • Setting the NoDriveTypeAutoRun Value


Opening a Startup Application

Users should receive feedback soon after they insert an AutoPlay compact disc into the disc drive. Therefore, your startup application should be a small program that loads quickly. The startup application should clearly identify the title it plays and provide an easy way to cancel the operation.


Loading in the Background

Typically, the startup application presents users with a dialog box asking them if they would like to proceed. The user normally clicks an OK button to continue. Take advantage of the time the user spends reading the dialog box by starting another thread that begins loading the setup application. If the user clicks OK, your setup program will already be loading. This significantly reduces the user's perception of the amount of time it takes to load your application.


Conserving Hard Disk Space

Hard disk space is a limited resource. Here are a few hints for minimizing hard disk usage:

  • Don't put files on the user's hard drive. Run your application from the compact disc directly, without running any installation application.
  • Keep installed files to a minimum. If your application needs to use the hard disk, install only the functional components necessary to run the application. In addition, provide a way to uninstall these components from the hard disk. For more information about uninstalling an application, see the documentation included with the Microsoft Platform Software Development Kit (SDK).
  • Provide the user with caching control. If your application needs to use the drive as a data cache, provide the user with options in the startup application that will discard the cached data when the user quits your application.


Using the Registry

The registry is a feature of Windows that supersedes the initialization (.ini) and application configuration files. For information about application programming interfaces that manipulate the registry, see the documentation included with the Platform SDK.

If your product records and uses initialization information, you can use the registry to store and retrieve this information. Your startup application can use the information in the registry to determine whether the product needs to be installed. If there are no registry entries for your product—which means your product is being used for the first time—you could display a dialog box that lists the setup options. If your product is listed in the registry—which means it has already been installed—you could skip the setup options.

By changing the system registry, you can cause a computer to read the Autorun.inf file from a floppy disk. This feature of implementing AutoPlay on a floppy disk is provided only to help you debug your Autorun.inf files before you burn the compact disc. AutoPlay is intended for public distribution on compact disc only. To implement AutoPlay on a floppy disk, carry out the following procedure:

  1. In Registry Editor (Regedit.exe), click Edit, and then click Find.
  2. In the Find What box, type the following, and then click Find Next:

    NoDriveTypeAutoRun

  3. Click Edit, and then click Modify.
  4. Change the data of the NoDriveTypeAutoRun value from 0000 95 00 00 00 to 0000 91 00 00 00, and then click OK.

    This enables AutoPlay on any drive. You must, however, start AutoPlay manually when it is installed on a floppy disk. To do this, double-click the floppy disk icon, or right-click the floppy disk icon, and then click AutoPlay.

  5. After you complete your tests of Autorun.inf, reset the value of NoDriveTypeAutoRun to 0000 95 00 00 00.

Important Because implementing AutoPlay on a floppy disk provides an easy way to spread computer viruses, it is appropriate to suspect that any publicly distributed floppy disk that contains Autorun.inf files is contaminated.

For more information about the NoDriveTypeAutoRun value, see Setting the NoDriveTypeAutoRun Value.


Setting the NoDriveTypeAutoRun Value

The NoDriveTypeAutoRun value in the registry is a 4-byte binary data value of the type REG_BINARY. The first byte of this value represents different kinds of drives that can be excluded from working with AutoPlay. The initial setting for this byte is 0x95, which excludes the unrecognized type drive, DRIVE_UNKNOWN, DRIVE_REMOVEABLE, and DRIVE_FIXED media types from being used with AutoPlay. You can enable a floppy disk drive for AutoPlay by resetting bit 2 to zero, or by specifying the value 0x91 to maintain the rest of the initial settings. For information about how to change the registry values, see Using the Registry. A table identifying the bits, bitmask constants, and a brief description of the drives follows:

Bit number | Bitmask constant | Description
0 (low-order bit) | DRIVE_UNKNOWN | Drive type not identified.
1 | DRIVE_NO_ROOT_DIR | Root directory does not exist.
2 | DRIVE_REMOVEABLE | Disk can be removed from drive (a floppy disk).
3 | DRIVE_FIXED | Disk cannot be removed from drive (a hard disk).
4 | DRIVE_REMOTE | Network drive.
5 | DRIVE_CDROM | CD-ROM drive.
6 | DRIVE_RAMDISK | RAM disk.
7 (high-order bit) |  | Reserved for future use.

Note For Windows NT/Windows 2000, you must restart Windows Explorer before any changes take effect.


Suppressing AutoPlay

There are a variety of reasons why you might want to suppress AutoPlay. One might be that your application has a setup program that requires the user to insert a disc which contains an Autorun.inf file. In this case, you would not want the AutoPlay feature to begin running an application while your setup application is running.

Another reason to suppress AutoPlay might be that your user needs to do disk swapping during your application. You would probably not want the setup program to execute while your application is in progress.

You can manually prevent the Autorun.inf file on a compact disc from being parsed and carried out by holding down the SHIFT key when you insert the disc.

Users of Windows NT version 4.0 can suppress AutoPlay automatically using the following code example. This initialization code is based on the assumption that your setup application is in the foreground window.

uMessage - RegisterWindowMessage(TEXT("QueryCancelAutoPlay"));

Then, add the following code to your setup window procedure:

if(msg == uMessage)
{
    // return 1 to cancel AutoPlay
    // return 0 to allow AutoPlay
    return 1L;
}

Windows 95 users can suppress AutoPlay by setting the value of the NoDriveTypeAutoRun registry entry to 0xFF. The following code sample demonstrates how this can be done. Insert this code near the beginning of the WinMain function.

const unsigned long WINDOWS_DEFAULT_AUTOPLAY_VALUE=0x095;
const unsigned long AUTOPLAYOFF=0x0FF;
  unsigned long ulOldAutoRunValue = WINDOWS_DEFAULT_AUTOPLAY_VALUE;
  unsigned long ulDisableAutoRun = AUTOPLAYOFF;
  unsigned long ulDataSize = sizeof(unsigned long);
  HKEY hkey = NULL;
char *lpzRegistryString = "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer"

if( RegOpenKeyEx(HKEY_CURRENT_USER,
    lpzRegistryString ,
    0, KEY_ALL_ACCESS, &hkey ) == ERROR_SUCCESS )
{
    if( RegQueryValueEx(hkey,"NoDriveTypeAutoRun", 0, NULL,
                        (unsigned char*)&ulOldAutoRunValue,
                        &ulDataSize ) == ERROR_SUCCESS )
    {
        RegSetValueEx(hkey, "NoDriveTypeAutoRun", 0, REG_BINARY,
                      (const unsigned char*)&ulDisableAutoRun, 4);
    }
    else ulOldAutoRunValue = WINDOWS_DEFAULT_AUTOPLAY_VALUE;

    RegFlushKey( hkey );
    RegCloseKey( hkey );
}

Just before your application terminates, it must reset the registry to the old value, as shown in the code example below:

// Restore original AutoPlay settings.
if (RegOpenKeyEx(HKEY_CURRENT_USER,
                 lpzRegistryString ,
                 0, KEY_ALL_ACCESS, &hkey ) == ERROR_SUCCESS )
{
    RegSetValueEx(hkey, "NoDriveTypeAutoRun", 0, REG_BINARY,
                  (const unsigned char*)&ulOldAutoRunValue,
                   4 );
    RegFlushKey( hkey );
    RegCloseKey( hkey );
}


AutoPlay for MS-DOS-Based Applications

You also can use AutoPlay to install, configure, and run MS-DOS-based applications in a Windows MS-DOS session. You can even configure each MS-DOS-based application with its own unique icon, Config.sys file, and Autoexec.bat file.

Windows creates the correct configuration files for the MS-DOS-based application. The startup application then starts the MS-DOS-based application in a window.


AutoPlay Reference

The reference information for the AutoPlay feature is straightforward and consists of commands.


Commands

This section contains information about the following AutoPlay commands:

  • defaulticon
  • icon
  • open
  • shell
  • shell\verb


defaulticon

The defaulticon command specifies an absolute path on the compact disc to the file that contains the information for the icon. The icon represents the AutoPlay-enabled CD in the Windows user interface.

defaulticon=path\iconname.ico

Parameters

path\iconname.ico
Absolute path and file name of the file containing the icon. The icon can be in a .bmp, .exe, .ico, or .dll file. If a file contains more than one icon, specify the resource number (index) of the icon in the file to use.

Remarks

If both the icon and defaulticon commands are present in an Autorun.inf file, AutoPlay uses the icon specified in the defaulticon command.

See Also

icon


icon

The icon command specifies a file that contains an icon which represents the AutoPlay-enabled CD in the Windows user interface. The file name specified with this command must be located in the same directory as the file name specified by the open command.

icon=filename.ico

Parameters

filename.ico
Name of the file containing the icon information. You also can specify a .bmp, .exe, or .dll file. If a file contains more than one icon, specify the resource number (index) of the icon in the file to use.

Remarks

The following example specifies the second icon in a file to represent a compact disc. The first icon's index is set to zero.

icon=filename.exe 1

See Also

defaulticon


open

The open command specifies the path and file name of the application that AutoPlay runs when you insert the compact disc in a CD-ROM drive.

open=dir\filename.exe

Parameters

dir\filename.exe
Path and file name of any executable file to run when the compact disc is inserted. If no path is specified, Windows looks for the file in the root directory on the compact disc. Specify a relative path to locate the file in a subdirectory.

Remarks

Use the open command to open a startup application that provides instant feedback to the user. For more information about startup applications, see Opening a Startup Application.

AutoPlay can pass command-line parameters to the application when it runs. Specify command line parameters after the file name.


shell

The shell command changes the default entry of the shortcut menu to the specified custom command.

shell=verb

Parameters

verb
Abbreviated form of a custom command. The custom command must be defined in the Autorun.inf file.

Remarks

If the user right-clicks the icon which represents your AutoPlay-enabled CD, a shortcut menu will be displayed. AutoPlay is the default menu item defined for any AutoPlay-enabled CD. The shell directive changes the default command to the specified command verb.

The command verb is executed when the user selects it from the shortcut menu. It is also executed when the user double-clicks the icon representing your CD.

See Also

shell\verb


shell\verb

The shell\verb command specifies a custom command listed in the shortcut menu for the icon. The first line identifies the executable file that performs the command. The second line specifies the custom entry of the shortcut menu.

shell\verb\command=filename.exe
shell\verb=Menu Item Name

Parameters

verb
Abbreviated form of the command. This parameter associates a command with the executable file name and the menu item. It must not contain embedded spaces. You will not see verb on the shortcut menu unless Menu Item Name is omitted from the Autorun.inf file.
filename.exe
File name of the application that performs the custom command.
Menu Item Name
Menu item text that can contain mixed-case letters and spaces. You also can set a shortcut key for the menu item by preceding one of the letters in the item with an ampersand (&).

Remarks

When a user right-clicks an icon in the Windows user interface, a shortcut menu for that icon appears. If an Autorun.inf file is present on a CD and the user right-clicks the icon for the CD, Windows automatically adds AutoPlay to the shortcut menu for the disk's icon. It also sets AutoPlay as the default behavior. Double-clicking the icon starts whatever is specified in the open command.

To add the command ReadMe to the shortcut menu for your product and to make the letter "M" the shortcut key, include the following in the Autorun.inf file:

shell\readit\command=notepad abc\readme.txt
shell\readit=Read &Me

See Also

shell, open


Glossary

This section provides a glossary of technical terms used in the DirectX Programmer's Reference documentation. Entries are grouped by letter in alphabetical order.

A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z


A

alpha channel
The opacity of an image defined by an alpha value per pixel interleaved with the color components (for example, ARGB), an alpha value per pixel stored in a separate alpha surface, or a constant alpha value for the entire surface.
alpha color component
The portion of a 32-bit color that determines its opacity. In this case, the alpha value per pixel is interleaved with the color components (for example, ARGB). Less commonly, this term can also refer to an image with an alpha value per pixel stored in a separate alpha surface.
alpha constant
A level of opacity (alpha value) applied to an entire surface.
alpha edge blend
A particular use of alpha blending (and alpha channel information) to reduce aliasing by blending edges based on pixel coverage information.
ambient
A light source that illuminates everything in a scene, regardless of the orientation, position, and surface characteristics of the objects in the scene. Because this illuminates a scene with equal strength everywhere, the position and orientation of the frame it is attached to are inconsequential. Multiple ambient light sources are combined within a scene.
anisotropic filtering
A mipmap filtering mode that compensates for anisotropy, which is the distortion visible in the texels of a 3-D object whose surface is oriented at an angle with respect to the plane of the screen. The anisotropy is measured as the elongation (length divided by width) of a screen pixel that is inverse-mapped into texture space.
anisotropy
The distortion visible in the image of a 3-D object whose surface is oriented at an angle with respect to the viewing plane.
array object
A group of objects organized into an array. Array objects make it simpler to apply operations to the entire group. The COM interfaces that allow you to work with array objects contain the GetElement and GetSize methods. These methods retrieve a pointer to an element in the array and the size of the array, respectively.
attach
To connect multiple DirectDrawSurface objects into complex structures, like those needed to support 3-D page flipping with z-buffers. Attachment is not bidirectional, and a surface cannot be attached to itself. Emulated surfaces (in system memory) cannot be attached to nonemulated surfaces. Unless one surface is a texture map, the two attached surfaces must be the same size.
attached
Physically connected to the system. A device may be installed but not currently attached.
attack
The period at the beginning of a force-feedback effect when the magnitude is reaching its basic or sustain level.
audio stream
Sound data, mixed or unmixed. DirectSound mixes audio streams from each secondary sound buffer that is playing and writes the result to the primary sound buffer, which supplies the sound hardware with audio data.


B

back buffer
A nonvisible surface that bitmaps and other images can be drawn to while the primary surface displays the currently visible image.
back clipping plane
The far boundary of a viewing frustum beyond which objects are not rendered. See also front clipping plane.
bank select
A MIDI controller that allows instruments to be chosen from different groups or banks, each identified by a two-byte code.
billboard
A primitive inserted into a 3-D scene that is oriented so that one face is toward the viewer. A texture, usually an animated sprite, is applied to the billboard to give the appearance of a 3-D object in the scene.
billboarding
A 2-D technique of simulating the appearance of a 3-D object in a scene. An application inserts a primitive, typically rectangular, into the scene oriented so that one face is toward the viewer and applies a texture or a set of textures. The texture or set of textures gives the appearance of an animated 3-D object.
blend factor
The description of how each color component is blended in texture blending.
blend mode
The algorithm used to determine how a texture is blended with the colors of the surface to which the texture is applied.
blending stage
One step in a texture cascade. A blending stage includes one texture and a set of texture blending operations that are used when blending multiple textures.
blit
A bit block transfer.
bounds checking
The process of checking that an on-screen image is displayed within the bounds of the screen.
bump mapping
A technique for simulating the appearance of rough surfaces in 3-D scenes. Variations in depth are stored in a texture and applied to a primitive using standard texture-blending techniques.


C

camera
A Direct3DRMFrame object used by the viewport to define the viewing position and direction. The viewport renders only what is visible along the positive z-axis of the camera frame, with the up direction being in the direction of the positive y-axis.
camera space
The frame of reference where the viewer is at the origin, looking in the direction of the positive z-direction. Objects are transformed from world space to camera space by using the view transformation.
clip list
A series of rectangles that describes the visible areas of the surface. The clip list cannot be set if a window handle is already associated with the DirectDrawClipper object.
clipper
A DirectDrawClipper object.
codec
Represents the phrase "compressor and decompressor."
collision detection
The process of determining if any pixels for two images share the same location on the screen. See also hit detection.
color key
A value indicating the color to be used for transparent or translucent effects. When using a hardware blitter, for example, all of the pixels of a rectangular area will be blitted except for the value that was set as the color key, thereby creating nonrectangular sprites on a surface.
color space
A model for representing color as three or more coordinates. Color-space models map color components onto a Cartesian coordinate system in three or more dimensions. A color space may use any of several types of color encoding and visualizing color. The two most common types of color space models are RGB and YUV.
color-space conversion
A technique for converting a color in one color space to another color space. Typically, this conversion is from YUV colors from a video source to RGB for display.
color table
An array of n color values (normally RGB triples).
complex surface
The collective term for several DirectDrawSurface objects, all of which are attached to a root surface. The complex-surface structure can be destroyed only by destroying the root.
cull
Skipping a back face of a 3-D primitive during the rendering process.
current play position
The location in a DirectSound buffer where a sound is being played.
current write position
The location in a DirectSound buffer where it is safe to change data in that buffer.


D

dark light
A light source that removes illumination from a scene, created by specifying negative values for the colors of the light.
DCI
Acronym for Display Control Interface. Defined by the Intel and Microsoft corporations, DCI in an interface that offers improved graphics performance as a result of direct video memory access.
dead zone
An area within the range of an axis where the axis is considered to be at the center.
decal
A texture that is rendered directly, as a visual. Decals are rendered into a viewport-aligned rectangle.
destination color key
The color that, in the case of blitting, will be replaced or, in the case of overlays, be covered up on the destination surface.
device window
A visible application window that DirectDraw uses for display. Applications can have a device window for each display device in a machine. See also focus window.
directional
A light source that is attached to a frame but appears to illuminate all objects with equal intensity, as if it were at an infinite distance from the objects. Directional light has orientation but no position, and it is commonly used to simulate distant light sources, such as the sun.
DLS
Downloadable sounds (sometimes called downloadable samples). Digital samples in software that are used by a synthesizer to create instrument timbres.


E

emissive property
The material property that determines whether a material emits light. The emissive property of a material is one of two properties that determines how the material reflects light. See also specular property.
emissive setting
See emissive property.
enable frame
The frame to which a light applies.
envelope
A set of values that defines the shape of a force-feedback effect by modifying the magnitude at the beginning (attack) and end (fade).
even field
The second field comprising a video frame in an odd/even field set. Also known as field 2.
execute buffer
A fully self-contained, independent packet of information that describes a 3-D scene. An execute buffer contains a vertex list followed by an instruction stream. The instruction stream consists of operation codes, or opcodes, and the data that is operated on by those opcodes.


F

face
A single polygon in a mesh.
fade
The period between the central, or sustain, portion of a force feedback effect and its end.
falloff
Light attenuation that occurs between a spotlight's inner and outer cones.
field
Data for one-half of a single video frame within a video stream. Each field contains data for every other scan line. Fields are sent and received in odd field, even field order.
field polarity
Quality determining whether a field is an even field or an odd field. Odd fields are defined when the trailing edge of VREF does not occur during a scan line. Even fields are defined as when the trailing edge of VREF occurs during a scan line.
flimmering
A shimmering appearance on 3-D primitives that results from a poor separation of z values when doing decaling. Some pixels from the back texture are rendered onto the front texture and visa versa.
flip
The process of swapping the addresses associated with the back and front buffers. This effectively swaps the image in the back buffer to the front buffer, thereby displaying the image.
flipping chain
A series of surfaces, attached to each other, that can be flipped. See also flip.
flipping surface
Any piece of memory that can be flipped. See also flip.
focus window
An application window, visible or not visible, that DirectDraw uses to hook window messages. The focus window's message handler receives input messages as forwarded by DirectDraw. Applications can have only one focus window. See also device window.
frame
An invisible box that provides a frame of reference for objects in a scene. Objects can be placed in a scene by specifying their spatial relationship to a relevant reference frame. Visual objects take their positions and orientations from frames. Also, a single image from a movie or animation.
front buffer
The first buffer in a flipping chain. In many cases, this will be the visible primary surface. In other cases, such as a flipping chain of textures, the front buffer is the surface the 3-D engine will get the texture from, but it is not the primary surface and is not displayed. In the case of flipping overlay surfaces, the front buffer is displayed, but is only a surface overlaid on the primary surface. See also primary surface.
front clipping plane
The near boundary of a viewing frustum. Any object closer to the camera than the front clipping plane is not rendered. The height of the front clipping plane defines the field of view. See also back clipping plane.


G

genlocking
The process of synchronizing one video signal with another. Because they are synchronized, the genlocked signal can be mixed with the original signal, allowing dissolves, wipes, and other transition effects.
grid
Subdivision of a beat. The number of grids per beat is part of the DirectMusic time signature.
groove level
A value given to the music during style playback, determining which patterns can be selected at any given time. The author assigns a range of groove levels to each pattern.
group
A number of players arranged together as a set in a DirectPlay session.


H

HAL
The hardware-abstraction layer. Consists of hardware and device driver mechanisms that insulate applications from device-specific implementation details. If a capability requested by an application is not implemented by the current hardware, the capability will be emulated by the software.
hardware blitter
A hardware component, built into the display adapter, that performs efficient blit operations.
HEL
The hardware-emulation layer. Provides software-based emulation of features that are not present in hardware.
hit detection
See collision detection.
host
In DirectPlay, a virtual player whose ID is DPID_SYSMSG. System messages and messages sent to all players in a session are managed by the host.
HREF
Acronym for horizontal refresh. In a video stream, the HREF is active to signal that the display is to begin a new scan line. See also VREF.


I

index palette
A DirectDrawPalette object whose entries are indices into another palette object.
IRE
IRE, an acronym for International Radio Engineers, is a scale of values ranging from 0 to 100 that defines the brightness level of a broadcast video signal. The spectrum of low-to-high IRE values describes increasing brightness levels in a video signal. At 7.5 IRE brightness units — the "black cut-off" threshold for an NTSC signal — the electron guns of an NTSC display device are cut-off and do not display images.


L

latency
A delay in response; for example, the interval between the time that a sound buffer plays and the time that the speakers actually reproduce the sound.
light map
A texture or group of textures that contain lighting information for a 3-D scene.
lobby client
Lobby management routines associated with the user's computer, including launching applications, updating the user interface, and communicating with the lobby server.
lobby server
Lobby management routines associated with a remote server. The lobby server coordinates all the information about the users connected to a specific application.


M

Mach bands
Bands of color that are not smoothly blended across a 3-D primitive.
material
A property that determines how a surface reflects light. A material has two components: an emissive property (whether it emits light) and a specular property, whose brightness is determined by a power setting.
mesh
A set of faces, each of which is described by a simple polygon.
mipmap
Also known as MIP map (Latin: multum in parvo, translated "much in little"). A sequence of textures, each of which is a progressively lower-resolution, prefiltered representation of the same image. A higher-resolution image is used when a visible object is close to the viewer; as the object moves farther away (and gets smaller), lower-resolution images are used.
mixing
In DirectSound, the process of combining sound buffers that are playing and writing the result to the primary sound buffer, which supplies the sound hardware with audio data. There are no limitations to the number of buffers that can be mixed, except the practicalities of available processing time.
Mode X
A hybrid display mode derived from the standard VGA Mode 13. This mode allows the use of up to 256 KB of display memory (rather than 64 KB allowed by Mode 13) by using the VGA display adapter's EGA multiple video plane system.
model coordinates
Coordinates that are relative to local origin. See also model space and world coordinates.
model space
The frame of reference, used by model coordinates, that uses vertices relative to a single 3-D model's local origin.
multipass texture blending
The repeated rendering of a 3-D primitive while blending on a texture with each pass. This technique is widely used to achieve a variety of special effects.


N

normal vector
An imaginary ray extending perpendicularly from a surface that defines the face's orientation.


O

odd field
The first field comprising a video frame in an odd/even field set.
off-screen surface
A conceptually rectangular area in memory that is generally used to store bitmaps that will be blitted to a back buffer before being displayed. Commonly used to store sprites.
opcode
Operation code that defines how the vertices in an execute buffer should be interpreted or how the state of the system should be changed.
overdraw
The average number of times to which a screen pixel is written.
overlay surface
A conceptually rectangular area in memory whose stored image information will cover the image information of the primary surface to which it is applied. Overlays are assumed to be on top of all other screen components.
overlay z-order
Determines the order in which overlays clip each other, enabling a hardware sprite system to be implemented under DirectDraw.


P

page flipping
See flip.
palette
The set of colors used by an object or application. In DirectX, a DirectDrawPalette object.
palette index
An integer index into the palette table array that is used to select a particular color.
palettized surface
A DirectDrawSurface object that uses an attached palette to contain color information.
pan value
The relative volume, measured in hundredths of decibels, between the left and right audio channels.
parallel point
A light source that illuminates objects with parallel light, but the orientation of the light is taken from the position of the parallel point light source. For example, two meshes on either side of a parallel point light source are lit on the side that faces the position of the source.
PChannel
Abbreviation for performance channel. A PChannel is a MIDI channel in a particular channel group on a particular port.
perspective correction
The technique of applying a texture map to a polygon that is angled away from the camera, interpolating so that the texture is stretched onto the polygon appropriately for the apparent depth of the polygon. Direct3D supplies perspective correction automatically.
pick
To search for visuals in a scene given a 2-D coordinate in a viewport.
pitch
The distance, in bytes, between an address that represents the beginning of a bitmap line and the beginning of the next line. Do not confuse memory pitch and memory width, since not all display memory is laid out as one linear block. For example, with rectangular memory, the pitch of the display memory could include the width of the bitmap plus part of a cache. See also width and stride.
player
A single participant in a DirectPlay session. Each player is associated with a player ID that enables messages to be exchanged among players.
player ID
A unique number that is assigned to each participant in a DirectPlay session when the participant is created. The application can exchange messages among players by using player IDs. The host is always assigned the DPID_SYSMSG player ID.
point light
A light source that radiates equally in all directions from its origin.
point list
The simplest 3-D primitive. A collection of unconnected points in 3-D space.
power
In the specular property of a material, the value that determines the sharpness of specular highlights. A value of 5 gives a metallic appearance, and higher values give a more plastic appearance.
primary sound buffer
The buffer the user hears when a game is playing. The primary buffer is generally used to mix sound from secondary buffers, but it can be accessed directly for custom mixing or other specialized activities.
primary surface
The area in memory containing the image being displayed on the monitor. In DirectX, the primary surface is represented by the primary DirectDrawSurface object.
projection space
Frame of reference containing vertices after they are modified from their world space locations by the projection transformation. Projection space is a homogeneous cuboid space where all vertices in a scene have x- and y-coordinates that range from -1.0 to 1.0, and a z-coordinate that ranges from 0.0 to 1.0. Projection space is sometimes referred to as "post-perspective homogeneous space."
projection transformation
The application of a matrix to vertices to change them from camera space to projection space.


Q

quaternion
A fourth element added to the [x, y, z] values that define a vector. Quaternions define a 3-D axis and a rotation around that axis.


R

reference count
A control for a component object model (COM) object. When an object is created, its reference count is set to 1. Every time an interface is bound to the object, its reference count is incremented; when the interface connection is destroyed, the reference count is decremented. The object is destroyed when the reference count reaches 0. All interfaces to that object are then invalid.
region
A range of notes for which a particular digital sample will be used in synthesizing an instrument's timbre.
root frame
A frame in Direct3D that has no parent frame; a frame at the top of a hierarchy of frames. The root frame contains the entire set of objects that make up a scene. See also scene.


S

saturation
Adjustment to the extreme value of a range when the actual value approaches the extreme. If the maximum value in a range is 1,000 and the maximum saturation point is set to 900, then any value greater than 899 is adjusted to 1,000.
scene
The entire set of objects that make up a virtual environment, including visible objects, sounds, lights, and frames. In Direct3D, the entire set of objects is contained by a root frame.
screen space
Frame of reference in which coordinates are related directly to two dimensional locations in the frame buffer, to be displayed on a monitor or other viewing device. Projection space coordinates are converted to screen space coordinates using a transformation matrix created from the viewport parameters.
secondary sound buffer
A section of audio memory that stores individual sounds that are played throughout an application. The sound can be played as a single event or as a looping sound that plays repeatedly. Secondary buffers can also play sounds that are larger than available sound-buffer memory; the buffer serves as a queue that stores the portions of the sound about to be played.
service provider
A dynamic-link library used by DirectPlay to communicate over a network. The service provider contains all the network-specific code required to send and receive messages. Online services and network operators can supply service providers to use specialized hardware, protocols, communications media, and network resources.
session
In DirectPlay, an instance of several applications on remote machines communicating with each other.
sound buffer
A segment of memory that stores DirectSound audio data. Sound buffers can be primary or secondary, static or streaming.
source color key
A color that, in the case of blitting, will not be copied, or, in the case of overlays, not be visible on the destination.
specular property
The material property that determines how a point of light on a shiny object corresponds to the reflected light source. The specular property of a material is one of two properties that determines how a material reflects light. See also emissive property.
spotlight
A light source that emits a cone of light. Only objects within the cone are illuminated. The cone produces light of two degrees of intensity, with a central brightly lit section that acts as a point source, and a surrounding dimly lit section that merges with the surrounding deep shadow.
static sound buffer
A section of memory that contains a complete sound. These buffers are convenient because the entire sound can be written once to the buffer.
sticky focus
In DirectSound, the capability to play sound buffers when the owning application does not have the input focus. For example, a DirectSound application could continue to play a sound buffer while the user was working in another application.
streaming sound buffer
A small sound buffer that can play lengthy sounds because the application dynamically loads audio data into the buffer as it plays. For example, an application could use a buffer that can hold 3 seconds of audio data to play a 2-minute sound. A streaming buffer requires much less memory than a static buffer.
stretching
Blitting an image into a destination with different dimensions. This operation is supported directly by some hardware.
stride
Synonymous with pitch. See also width.
surface
Memory that represents visual images. This is often display memory, but it can be system memory. See also complex surface, off-screen surface, overlay surface, and primary surface.
sustain
The period when the basic magnitude of a force feedback effect is attained, after the attack and before the fade.


T

tearing
A visual artifact produced when the screen refresh rate is out of sync with an application's frame rate. The top portion of one frame is displayed at the same time as the bottom portion of another frame, with a discernible tear between the two partial images.
tessellate
Breaking an image into small, square regions for processing or output.
texel
A single element in a texture. When a texture has been applied to an object, the texels rarely correspond to pixels on the screen. Applications can use texture filtering to control how texels are interpolated to pixels.
texture
A rectangular array of pixels that is applied to a visual object in Direct3D.
texture blending
The technique of combining the colors of a texture with the colors of the surface to which the texture is applied.
texture coordinates
The coordinates that determine which texel in each texture is assigned to each vertex in an object.
texture filtering
The process of mapping texel colors from one or more textures onto the pixels that comprise the image of a 3-D primitive.
texture mapping
The application of a texture to an object. Because a texture is a flat image and the object is often not, the texture must be mapped to the surface of the object, using texture coordinates and wrapping flags. See also texture coordinates and wrap.


V

VBI
Abbreviation for Vertical Blanking Interval.
velocity
In music, the speed at which a key is struck; roughly equivalent to the volume of a note.

In 3-D sound, the speed at which a sound source or listener is considered to be moving, for the purpose of calculating Doppler shift.

vertex
A point in 3-D space.
video frame
A single image in a video stream, comprised of one odd field and one even field. See also field.
view space
See camera space.
view transformation
The application of a matrix to a model's vertices to change its orientation from world space to view space.
viewing frustum
A 3-D volume in a scene positioned relative to the viewport's camera. Objects within the frustum are visible. For perspective viewing, the viewing frustum is the volume of an imaginary pyramid that is between the front clipping plane and the back clipping plane. For orthographic viewing, the viewing frustum is cuboid.
viewport
A rectangle that defines how a 3-D scene is rendered into a 2-D window. A viewport also defines an area on a device into which objects will be rendered.
VREF
Acronym for vertical refresh. In a video stream, the VREF is active to signal that the display is to begin a new screen. See also HREF.


W

width
The distance between two addresses in memory that represent the beginning of a line and the end of the line of a stored bitmap. This distance represents only the width of the bitmap in memory; it does not include any extra memory required to reach the beginning of the next line of the bitmap, such as a cache in rectangular memory.
world coordinates
Coordinates that are relative to the origin of a scene. See also model coordinates and world space.
world space
The frame of reference, used by world coordinates, that declares vertices relative to a single origin within a 3-D scene.
world transformation
The application of a matrix to a model's vertices to change its orientation from model space to world space.
wrap
The procedure used to calculate texture coordinates for a face or mesh. The basic wrapping types are flat, cylindrical, spherical, and chrome.


Z

z-buffer
A buffer that stores a depth value for each pixel in a scene. Pixels with a small z-value overwrite pixels with a large z-value.
z fighting
See flimmering.


Microsoft Direct3D Retained Mode SDK

Microsoft Direct3D Retained Mode

Welcome to the Microsoft® Direct3D® Retained Mode Software Development Kit. With Direct3D Retained Mode, you can create a three-dimensional (3-D) graphics environment on a personal computer and manipulate it in real time.

Last Updated: October 28, 1998

About Retained Mode
Provides a brief description of Direct3D Retained Mode.
Getting Started
Describes the new features in Direct3D Retained mode version 6.0, where to get started, and where to find common topics. Also provides some of the technical background you need to manipulate points in three dimensions. Includes a general discussion of coordinate systems, transformations, polygons, triangle strips and fans, vectors, vertices, and quaternions.
Technical Background
Describes some of the technical concepts you need to understand before you write programs that incorporate 3-D graphics. In this section, you will find a general discussion of coordinate systems and transformations.
Architecture
Describes Direct3D Retained Mode objects and the interfaces they support. Also provides tips on reference counting and z-buffers.
Overviews
Provides information about using some of the Direct3D Retained Mode interfaces. See the Reference for detailed information about all Retained Mode interfaces.
Tutorial
Provides a walk-through of the code in a simple Retained Mode application.
Reference
Provides detailed information about the interface methods, nonmember functions, and callbacks with syntax, parameter descriptions, flag descriptions, and comments about use. Also describes the members of Direct3D structures, enumerated types, other defined types, and the possible error values that can be returned.
Samples
Provides information about how to build the Direct3D Retained Mode samples in Microsoft Developer Studio™, and it provides summaries of the samples to help you determine which sample to look at.
DirectX File Format
Describes the file format of DirectX (.x) files, which provide support for reading predefined objects into applications and writing mesh information constructed by applications in real time. Also includes information about templates, examples, the binary format of the files, and the Conv3ds.exe utility, which converts 3-D models from other packages into .x files.
Glossary
Defines basic graphics terms used in Direct3D Retained Mode.

Note: The icon external link indicates that the link takes you to a URL that is outside the microsoft.com site; you can return to the Direct3D Retained Mode site by using the Back button. Most of these external links point to servers that are not under Microsoft's control. Please read Microsoft's official statement regarding other servers.


About Direct3D Retained Mode

About Retained Mode

This section describes Microsoft® Direct3D® Retained Mode, the Microsoft solution for real-time, three-dimensional (3-D) graphics on the personal computer. If you need to create a 3-D environment and manipulate it in real time, you should use the Direct3D Retained Mode API.

If you have written code before that uses 3-D graphics, many of the concepts underlying Direct3D Retained Mode will be familiar to you. If, however, you are new to 3-D programming, you should pay close attention to Direct3D Retained Mode Architecture, and you should read Technical Background. Whether you are an experienced 3-D programmer or just beginning, you should look carefully at the sample code included with this Software Development Kit; it illustrates how to put Direct3D Retained Mode to work in real-world applications.

For an introduction to programming with Direct3D Retained Mode, see Direct3D Retained Mode Tutorial.


Getting Started

This section discusses new features in Microsoft® Direct3D® Retained Mode version 6.0 and where to find particular information in the documentation. It also provides articles that walk through well-commented sample code.

  • What's New in the Direct3D Retained Mode SDK?
  • Documentation Roadmap
  • Rotating an Object: The RMBegin1 Sample
  • Frame Hierarchies: The RMBegin2 Sample
  • Enumerating Devices: The RMEnum Sample


What's New in the Direct3D Retained Mode SDK?

This section discusses new features and documentation in Microsoft® Direct3D® Retained Mode version 6.0. For the most recent documentation updates, consult the Microsoft® DirectX® Web site at http://www.microsoft.com/DirectX/dxm/.

This article contains the following sections.

  • New Articles
  • New Interfaces

New Articles

Most of the Getting Started section is new and contains the following articles.

  • Documentation Roadmap outlines where to go in this documentation for information on particular topics.
  • Rotating an Object: The RMBegin1 Sample contains a walkthrough of a simple sample that rotates an object.
  • Frame Hierarchies: The RMBegin2 Sample contains a walkthrough of a simple sample that provides a sun, planet, and moon scenario with each object revolving around the other appropriate objects.
  • How to Enumerate Devices contains a walkthrough of a sample that enumerates devices.
  • Eliminating Redundant State Changes explains how to avoid setting the state to a value equal to its current value, which can help performance.

The Samples section of this documentation is new. You can reach the section through Direct3D Retained Mode Samples Introduction, which leads to the following new articles.

  • Building Samples Using Developer Studio 5.0
  • Direct3D Retained Mode Samples

Direct3D Retained Mode Overviews contains the following new articles.

  • Interface Hierarchy Chart
  • Interface Changes

New Interfaces

Microsoft® Direct3D® Retained Mode version 6.0 introduces several interfaces and a number of other interfaces that add new methods, and thereby new functionality, to old interfaces. For a complete list of the new interfaces and methods, see Interface Changes. For information about interface inheritance see the new Interface Hierarchy Chart.

This documentation covers the latest version of an interface and notes differences between versions rather than duplicating information. For example, where you would have previously found separate, but nearly identical documentation for IDirect3DRMTexture3::GetDecalSize, IDirect3DRMTexture2::GetDecalSize, and IDirect3DRMTexture::GetDecalSize you will now find that method documented under the latest version of that interface as IDirect3DRMTexture3::GetDecalSize.

The Reference contains the following new interfaces.

  • Retained Mode version 6.0 introduces a new IDirect3DRM3 interface and Direct3DRM3 object. MeshBuilder3 objects created using IDirect3DRM3 use the DirectX Immediate Mode DrawPrimitive interface. Lights created with IDirect3DRM3 take advantage of new Immediate Mode functionality and use the Immediate Mode D3DLIGHT2 structure. IDirect3DRM3 provides all the functionality of IDirect3DRM2 and IDirect3DRM. It adds a flag parameter to CreateDeviceFromSurface, allowing you to indicate that no z-buffer should be created, and adds the RegisterClient and UnregisterClient methods. IDirect3DRM3 also adds the GetOptions and SetOptions methods to set and retrieve whether left-handed or right-handed geometry should be used.

  • All objects implement the new IDirect3DRMObject2 interface. IDirect3DRMObject2, unlike the other new interfaces, does not implement all the methods of its predecessor. IDirect3DRMObject2 and IDirect3DRMObject continue to be documented separately. IDirect3DRMObject2 adds the SetClientData and GetClientData methods that work in conjunction with the new IDirect3DRM3::RegisterClient and IDirect3DRM3::UnregisterClient methods. It also adds the GetDirect3DRM and GetAge methods.

  • IDirect3DRMAnimation2 adds the AddKey, DeleteKeyByID, GetKeys, and ModifyKey methods that allow access to the keys of an animation. It also adds the GetFrame method that returns the frame of the corresponding animation.

  • The new IDirect3DRMAnimationArray interface lets you retrieve the number of animations in the array using GetSize and request the interface for an animation using GetElement.

  • IDirect3DRMAnimationSet2 adds the GetAnimations method that allows you to retrieve the constituent animations.

  • The new IDirect3DRMClippedVisual interface allows you to clip visuals against arbitrary planes before rendering. New ClippedVisual objects are created from the Direct3DRM3 object.

  • IDirect3DRMDevice3 adds the FindPreferredTextureFormat method to select a texture format based on certain criteria. IDirect3DRMDevice3 also introduces several methods that can be used to eliminate redundant state changes: GetStateChangeOptions, LightStateChange, RenderStateChange, and SetStateChangeOptions.

  • IDirect3DRMFace2 adds a SetTexture method with which you can specify textures whose height and width are not a power a two.

  • IDirect3DRMFrame3 provides methods that enable additional transformation capabilities between model- and world-space, retrieving the world 4x4 transform, setting and retrieving traversal options, and setting and retrieving whether fogging is done through vertex fog or table fog. It also provides methods for setting and retrieving material overrides. The SetOrientation method now respects scale and shear.

  • IDirect3DRMMaterial2 adds the GetAmbient and SetAmbient methods to allow finer control over material properties.

  • IDirect3DRMMeshBuilder3 adds methods to delete face, normal, and vertex objects. It also adds the Empty and Optimize methods. Other new IDirect3DRMMeshBuilder3 methods retrieve one or more normals, the number of normals, the texture topology, faces, one or more vertices, and the state (enabled or disabled) of the meshbuilder. This interface enables you to set vertices and normals and to create and retrieve new sub-meshes and parent meshes of the meshbuilder. IDirect3DRMMeshBuilder3 also enables the application to add new triangles and to implicitly create new faces by using the AddTriangles method.

  • IDirect3DRMShadow2 adds methods allowing the visual, light, plane, and option shadow parameters to be changed after creation. SetOptions allows you to set an option that eliminates visual artifacts when blended transparency is enabled.

  • IDirect3DRMTexture3 extends the Changed method by allowing you to specify the changed region of the texture. It also provides the texture management caching methods GetCacheOptions and SetCacheOptions. GetSurface, SetDownSampleCallback, and SetValidationCallback are the other new methods IDirect3DRMTexture3 provides.

  • IDirect3DRMViewport2 adds a flag parameter to Clear, indicating whether the target surface, z-buffer surface, or dirty rectangle list are cleared.


Documentation Roadmap

This section discusses where you can find information about particular topics in this Microsoft® Direct3D® Retained Mode Software Development Kit.

If you are new to Retained Mode, start by reading the Interface Overviews to get an idea of common concepts. If you are new to three-dimensional (3-D) programming in general, read Technical Background. This background will help you understand the Tutorial and Samples. Consult the Reference, and especially the Interfaces for more details about what is going on in the code as you look at the Samples and Tutorial. The Glossary provides definitions for common terms.

Advanced developers might need detailed information about the DirectX File Format.

Where Can I Find ...

The following table lists commonly used information and where to find it.
For Information About | See This Topic
Error codes | Return Values
Interface inheritance | Interface Hierarchy Chart
Interface history | Interface Changes
Interfaces | Interfaces
Constants | Constants
Enumerated types | Enumerated Types
Structures | Structures
Building samples | Building Samples Using Developer Studio 5.0
Developer Studio | Building Samples Using Developer Studio 5.0
Sample code | Samples
Retained Mode objects and their associated COM interfaces | Architecture
3-D graphics concepts | Technical Background
DirectX Files | DirectX File Format


Rotating an Object: The RMBegin1 Sample

Creating a device, building a scene, and moving the scene are fundamental concepts in Microsoft® Direct3D® Retained Mode. The RMBegin1 sample demonstrates these concepts by creating a default device, loading a mesh from a Microsoft DirectX® file, adding color to the object and lights to the scene, and rotating the object. In the process of building the scene, the sample uses a meshbuilder, frames, lights, and a material. The sample also creates a DirectDrawClipper object, viewport and camera.

This article walks you through code from the RMBegin1 sample. The sample source code consists of one self-contained file (RMBegin1.cpp). It does not use any separate header files, except for the standard Microsoft Windows®, DirectDraw®, and Direct3D Retained Mode header files for the sake of simplicity. It also does not contain any menus, icons, or other resources.

This sample uses the Teapot.x file from the DirectX Foundation Software Development Kit (SDK) to provide the teapot image for the scene. By default when you install the SDK, the SDK's setup program sets an environment variable to point to the SDK's media directory. Teapot.x resides in that directory, allowing the application to locate the file automatically. If you have not installed the SDK and simply run RMBegin1.exe, Teapot.x must be located in the same directory as RMBegin1.exe.

This article assumes you are an experienced C or C++ programmer and are familiar with beginning Windows programming concepts, such as the message loop, creating a window, and using menus.

This article contains the following sections.

  • Dependencies
  • Global Declarations
  • Function Summaries
  • Related Topics

Dependencies

  • RMBegin1 links to DDraw.lib and D3DRM.lib.
  • RMBegin1 loads the teapot image from Teapot.x, as described in the previous section.
  • To properly initialize globally unique identifiers (GUIDs), Direct3D applications must contain the following definition at the top of their code.
    #define INITGUID
  • The sample's RMBegin1.cpp file includes the following header files.
    #include <windows.h>   // Standard Windows header file
#include <direct.h>    // DirectDraw definitions
#include <d3drmwin.h>  // Direct3D Retained Mode definitions

Global Declarations

The sample defines some constants and global variables to help organize information.

The application-defined RELEASE macro releases an object only if the object is not NULL and ensures that an object is initialized to NULL after it has been released. This practice eliminates the problem of trying to release an object that has already been released, which can cause undesired results, such as page faults.

// Macro to release an object.
#define RELEASE(x) if (x != NULL) {x->Release(); x = NULL;}

The application-defined DISPLAYMSG macro uses the Windows MessageBox function to display information to the user. Using this macro rather than direct calls to MessageBox throughout the sample code makes the code cleaner and easier to read.

// Macro to display a message box containing the given string.
#define DISPLAYMSG(x) MessageBox(NULL, x, "D3DRM Sample", MB_OK);

Global variables keep track of the key objects, such as the Direct3D Retained Mode and DirectDrawClipper objects (the DirectDrawClipper object restricts drawing to a designated area). The myglobs structure collects device, viewport, scene, and camera information, as well as information about whether the application is minimized and whether objects have been initialized.

// Global Variables
LPDIRECT3DRM3 lpD3DRM = NULL;            // Direct3DRM object
LPDIRECTDRAWCLIPPER lpDDClipper = NULL; // DirectDrawClipper object

// Global Structure
struct _myglobs {

    // Direct3DRM device.
    LPDIRECT3DRMDEVICE3 dev;

    // Direct3DRM viewport through which to view the scene.
    LPDIRECT3DRMVIEWPORT2 view;

    // Master frame in which other frames are placed.
    LPDIRECT3DRMFRAME3 scene;

    // Frame describing the users point of view.
    LPDIRECT3DRMFRAME3 camera;

    // Application is minimized.
    BOOL bMinimized;

    // All Direct3D Retained Mode objects have been initialized.
    BOOL bInitialized;

} myglobs;

Function Summaries

RMBegin1.cpp contains the following functions.

BuildScene creates the scene to be rendered. It loads a mesh from the DirectX file, adds color to the mesh, and adds lights to the scene. BuildScene also sets the position of objects and how objects should be rotated. CreateObjects, which initializes global variables and creates default devices, frames, and viewports, uses this function.

BOOL BuildScene(LPDIRECT3DRM3, LPDIRECT3DRMDEVICE3,
                LPDIRECT3DRMFRAME3, LPDIRECT3DRMFRAME3);

RenderScene draws the scene that BuildScene created. Each time WinMain uses this function, RenderScene moves the scene, giving the effect of a spinning object.

static BOOL RenderScene(void);

AddMediaPath provides a path to the textures and .x files needed by the application by searching the registry.

VOID AddMediaPath(LPDIRECT3DRM3 pD3DRM)

CreateObjects initializes the global variables and creates a default device, camera frame, scene frame, and viewport. CreateObjects uses BuildScene to create the scene to be rendered. InitApp uses CreateObjects.

BOOL CreateObjects(HWND win);

InitApp provides standard, Windows application code to create the window class and the application's window. It uses CreateObjects to initialize global objects.

static HWND InitApp(HINSTANCE, int);

WinMain provides the application's message loop. It uses InitApp to initialize the application and uses RenderScene to draw the scene.

int APIENTRY WinMain(HINSTANCE, HINSTANCE, LPSTR, int);

WindowProc handles messages for the application. It handles cases where the application is minimized or destroyed.

LRESULT CALLBACK WindowProc(HWND, UINT, WPARAM, LPARAM);

For more information about these functions, see the following topics in this article.

  • BuildScene
  • RenderScene
  • AddMediaPath
  • CreateObjects
  • InitApp
  • WinMain
  • WindowProc

BuildScene

The BuildScene function creates the scene to be rendered. All Direct3D Retained Mode applications must create a scene, but the code required depends on the scene. Applications typically create frames and lights, add visuals to the scene, and set the position of objects.

This section of this article provides code fragments from the BuildScene function and presents the steps the RMBegin1 sample performs to build the scene. This section also presents the complete source code for the RMBegin1 sample's BuildScene function. If an error occurs, the code uses goto statements to jump to the end of the function and ensure that all objects are properly released before returning from the function.

  1. Load a mesh from a DirectX file by using the IDirect3DRM3::CreateMeshBuilder and IDirect3DRMMeshBuilder3::Load methods.
        if (FAILED(lpD3DRM->CreateMeshBuilder(&meshbuilder)))
        goto generic_error;

    rval = meshbuilder->Load("teapot.x",
                              NULL, D3DRMLOAD_FROMFILE, NULL, NULL);
  2. Create a child frame within the scene by using the IDirect3DRM3::CreateFrame method.
        if (FAILED(lpD3DRM->CreateFrame(scene, &childframe)))
        goto generic_error;
  3. Add the loaded mesh into the child frame by using the IDirect3DRMFrame3::AddVisual method.
        if (FAILED(childframe->AddVisual((LPDIRECT3DRMVISUAL)meshbuilder)))
        goto generic_error;
  4. Set the camera position within the scene by using the IDirect3DRMFrame3::SetPosition method.
        rval = camera->SetPosition(scene, D3DVAL(0), D3DVAL(0), -D3DVAL(7));
  5. Set the child frame's rotation by using the IDirect3DRMFrame3::SetRotation method.
        if (FAILED(childframe->SetRotation(scene,
                                       D3DVAL(0), D3DVAL(1), D3DVAL(0),
                                       D3DVAL(0.03)))) // angle
        goto generic_error;
  6. Create a light frame that is a child of the scene by using the IDirect3DRM3::CreateFrame method.
        if (FAILED(lpD3DRM->CreateFrame(scene, &lights)))
        goto generic_error;
  7. Position the light frame within the scene by using the IDirect3DRMFrame3::SetPosition method.
        if (FAILED(lights->SetPosition(scene,
                                   D3DVAL(5), D3DVAL(0), -D3DVAL(7))))
        goto generic_error;
  8. Create a bright, parallel point light and add it to the light frame by using the IDirect3DRM3::CreateLightRGB and IDirect3DRMFrame3::AddLight methods.
        if (FAILED(lpD3DRM->CreateLightRGB(D3DRMLIGHT_PARALLELPOINT,
                                       D3DVAL(1.0), D3DVAL(0.8),
                                       D3DVAL(0.9), &light1)))
        goto generic_error;

    if (FAILED(lights->AddLight(light1)))
        goto generic_error;
  9. Create a dim, ambient light and add it to the scene, again by using using the IDirect3DRM3::CreateLightRGB and IDirect3DRMFrame3::AddLight methods.
        if (FAILED(lpD3DRM->CreateLightRGB(D3DRMLIGHT_AMBIENT,
                                       D3DVAL(0.1), D3DVAL(0.1),
                                       D3DVAL(0.1), &light2)))
        goto generic_error;

    if (FAILED(scene->AddLight(light2)))
        goto generic_error;
  10. Create a material and set the reflectiveness by using the IDirect3DRM3::CreateMaterial and IDirect3DRMMeshBuilder3::SetMaterial methods.
        if (FAILED(lpD3DRM->CreateMaterial(D3DVAL(10.0), &mat)))
        goto generic_error;

    if (FAILED(meshbuilder->SetMaterial(mat)))
        goto generic_error;
  11. Set the mesh color by using the IDirect3DRMMeshBuilder3::SetColorRGB method.
        if (FAILED(meshbuilder->SetColorRGB(D3DVAL(0.0),   // red
                                        D3DVAL(0.7),   // green
                                        D3DVAL(0.0)))) // blue
        goto generic_error;
  12. Clean up by releasing all of the objects created by this function.
        RELEASE(childframe);
    RELEASE(lights);
    RELEASE(meshbuilder);
    RELEASE(light1);
    RELEASE(light2);
    RELEASE(mat);

BuildScene Function Source Code

// Create the scene to be rendered.

BOOL BuildScene( LPDIRECT3DRM3 lpD3DRM,  LPDIRECT3DRMDEVICE3 dev,
                 LPDIRECT3DRMFRAME3 scene, LPDIRECT3DRMFRAME3 camera )
{
    LPDIRECT3DRMFRAME3 lights = NULL;
    LPDIRECT3DRMMESHBUILDER3 meshbuilder = NULL;
    LPDIRECT3DRMFRAME3 childframe = NULL;
    LPDIRECT3DRMLIGHT light1 = NULL;
    LPDIRECT3DRMLIGHT light2 = NULL;
    LPDIRECT3DRMMATERIAL2 mat = NULL;
    HRESULT rval;

    // Load a mesh from a DirectX file.
    if (FAILED(lpD3DRM->CreateMeshBuilder(&meshbuilder)))
        goto generic_error;

    rval = meshbuilder->Load("teapot.x",
                              NULL, D3DRMLOAD_FROMFILE, NULL, NULL);
    if (FAILED(rval))
    {
        DISPLAYMSG("Failed to load .x file.");
        goto ret_with_error;
    }

    // Create a child frame within the scene.
    if (FAILED(lpD3DRM->CreateFrame(scene, &childframe)))
        goto generic_error;

    // Add the loaded mesh into the child frame.
    if (FAILED(childframe->AddVisual((LPDIRECT3DRMVISUAL)meshbuilder)))
        goto generic_error;

    // Set up the camera frame's position. Objects with the same x-value and
    // y-value as the camera will appear straight ahead.
    // Negative z-values are farther away, making the object look
    // smaller as the negative numbers increase.
    rval = camera->SetPosition(scene, D3DVAL(0), D3DVAL(0), -D3DVAL(7));
    if (FAILED(rval))
    {
        DISPLAYMSG("Failed to position the camera in the frame.");
        goto ret_with_error;
    }

    // Rotate the child mesh around the y-axis (zero x-value and z-value)
    // and use a small rotational angle to rotate slowly.
    if (FAILED(childframe->SetRotation(scene,
                                       D3DVAL(0), D3DVAL(1), D3DVAL(0),
                                       D3DVAL(0.03)))) // angle
        goto generic_error;

    // Initialize the lights in the scene, creating a light frame that
    // is a child of the scene.
    if (FAILED(lpD3DRM->CreateFrame(scene, &lights)))
        goto generic_error;

    // Position the light frame within the scene. This light comes from
    // the right of the camera. It has a different x-value, but the same
    // y-value and z-value as the camera position.
    if (FAILED(lights->SetPosition(scene,
                                   D3DVAL(5), D3DVAL(0), -D3DVAL(7))))
        goto generic_error;

    // Create a bright, parallel point light and add it to the light frame.
    // Color values must be in the range 0.0 (dim) to 1.0 (bright).
    if (FAILED(lpD3DRM->CreateLightRGB(D3DRMLIGHT_PARALLELPOINT,
                                       D3DVAL(1.0), D3DVAL(0.8),
                                       D3DVAL(0.9), &light1)))
        goto generic_error;

    if (FAILED(lights->AddLight(light1)))
        goto generic_error;

    // Create a dim, ambient light and add it to the scene frame,
    // applying it to the whole scene. Ambient light comes from all
    // directions, so a bright ambient light would wash out the object.
    if (FAILED(lpD3DRM->CreateLightRGB(D3DRMLIGHT_AMBIENT,
                                       D3DVAL(0.1), D3DVAL(0.1),
                                       D3DVAL(0.1), &light2)))
        goto generic_error;

    if (FAILED(scene->AddLight(light2)))
        goto generic_error;

    // Create a material, setting the reflectiveness (5.0 is metallic,
    // higher is more plastic) on the previously loaded mesh.
    if (FAILED(lpD3DRM->CreateMaterial(D3DVAL(10.0), &mat)))
        goto generic_error;

    if (FAILED(meshbuilder->SetMaterial(mat)))
        goto generic_error;

    // Set the mesh color (bright green in this case).
    if (FAILED(meshbuilder->SetColorRGB(D3DVAL(0.0),   // red
                                        D3DVAL(0.7),   // green
                                        D3DVAL(0.0)))) // blue
        goto generic_error;

    // Clean up.
    RELEASE(childframe);
    RELEASE(lights);
    RELEASE(meshbuilder);
    RELEASE(light1);
    RELEASE(light2);
    RELEASE(mat);
    return TRUE;

generic_error:
    DISPLAYMSG("A failure occured while building the scene.");
ret_with_error:
    RELEASE(childframe);
    RELEASE(lights);
    RELEASE(meshbuilder);
    RELEASE(light1);
    RELEASE(light2);
    RELEASE(mat);
    return FALSE;
}

RenderScene

RenderScene performs the actual drawing to the screen. It draws the scene that BuildScene created by performing the following steps.

  1. Move the scene by using IDirect3DRMFrame3::Move.
  2. Clear the viewport by using IDirect3DRMViewport2::Clear.
  3. Render the scene by using IDirect3DRMViewport2::Render.
  4. Update the window by using IDirect3DRMDevice3::Update.

RenderScene Function Source Code

// Clear the viewport, render the next frame, and update the window.

static BOOL RenderScene()
{
    HRESULT rval;

    // Move the scene.
    rval = myglobs.scene->Move(D3DVAL(1.0));
    if (FAILED(rval))
    {
        DISPLAYMSG("Moving scene failed.");
        return FALSE;
    }

    // Clear the viewport.
    rval = myglobs.view->Clear();
    if (FAILED(rval))
    {
        DISPLAYMSG("Clearing viewport failed.");
        return FALSE;
    }

    // Render the scene to the viewport.
    rval = myglobs.view->Render(myglobs.scene);
    if (FAILED(rval))
    {
        DISPLAYMSG("Rendering scene failed.");
        return FALSE;
    }

    // Update the window.
    rval = myglobs.dev->Update();
    if (FAILED(rval))
    {
        DISPLAYMSG("Updating device failed.");
        return FALSE;
    }
    return TRUE;
}

AddMediaPath

AddMediaPath provides a path to the textures and .x files needed by the application. The function searches the system registry for the location of the DirectX 6 samples, prepends that location to the path of the directory containing the Retained Mode media files, and adds the whole path to the media files to the end of the current file search path.

AddMediaPath Function Source Code

// Looks in the system registry to determine the media path for the
// sample, then adds that path to the end of the current file search path.

VOID AddMediaPath(LPDIRECT3DRM3 pD3DRM)
{
    HKEY   key;
    LONG   result;
    TCHAR  strPath[512];
    DWORD  type, size = 512;

    // Open the registry
    result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\DirectX",
                          0, KEY_READ, &key);
    if(ERROR_SUCCESS != result)
        return;

    // Search for the desired registry value, and close the registry
    result = RegQueryValueEx(key, "DX6SDK Samples Path", NULL, &type,
                             (BYTE*)strPath, &size);
    RegCloseKey(key);

    if(ERROR_SUCCESS != result)
        return;

    strcat(strPath, "\\D3DRM\\Media");

    pD3DRM->AddSearchPath(strPath);

    return;
}

CreateObjects

CreateObjects initializes the sample's global variables and creates objects. After initializing global variables, CreateObjects performs the steps necessary to create a device, associate it with the application's main window, and create the master scene frame, the camera frame, and the viewport as follows:

  1. Use the DirectDraw DirectDrawCreateClipper function to create a DirectDrawClipper object.
  2. Use the DirectDrawClipper's SetHWnd method to associate the application's window with the DirectDrawClipper. The DirectDrawClipper object restricts subsequent drawing to a designated area—in this case, the application window.
  3. Use the Direct3DRMCreate function to create a Direct3D Retained Mode object, then query for the IDirect3DRM3 interface.
  4. Use the Windows GetClientRect function to obtain the height and width of the application's main window.
  5. Use the Direct3D Retained Mode object's CreateDeviceFromClipper method to create a device, passing NULL to create a default device, and passing the width and height of the application's window to the method.
  6. Create the master scene frame by using IDirect3DRM3::CreateFrame.
  7. Create the camera frame by using IDirect3DRM3::CreateFrame.
  8. Create the Direct3D Retained Mode viewport by using IDirect3DRM3::CreateViewport.
  9. Use BuildScene to create the scene.

CreateObjects Function Source Code

// Initialize globals, create the device and objects.

BOOL CreateObjects(HWND win)
{
    HRESULT rval; // Return value
    RECT rc;      // Bounding rectangle for main window
    int width;    // Device's width
    int height;   // Device's height

    // Initialize the entire global variable structure to zero.
    memset(&myglobs, 0, sizeof(myglobs));

    // Create a DirectDrawClipper object and associate the window with it.
    rval = DirectDrawCreateClipper(0, &lpDDClipper, NULL);
    if (FAILED(rval))
    {
        DISPLAYMSG("Failed to create DirectDrawClipper object");
        return FALSE;
    }

    rval = lpDDClipper->SetHWnd(0, win);
    if (FAILED(rval))
    {
        DISPLAYMSG("Failed to set the window handle for the DirectDrawClipper");
        return FALSE;
    }

    // Create the Direct3DRM object.
    LPDIRECT3DRM pD3DRMTemp;
    rval = Direct3DRMCreate(&pD3DRMTemp);
    if (FAILED(rval))
     {
        DISPLAYMSG("Failed to create Direct3DRM.");
        return FALSE;
    }
    if( FAILED(pD3DRMTemp->QueryInterface(IID_IDirect3DRM3, (void **)&lpD3DRM)))
    {
        RELEASE(pD3DRMTemp);
        DISPLAYMSG("Failed query for Direct3DRM3.\n" );
        return FALSE;
    }
    RELEASE(pD3DRMTemp);

    // Create a default Direct3D Retained Mode device.
    GetClientRect(win, &rc);

    rval = lpD3DRM->CreateDeviceFromClipper(lpDDClipper,
                           NULL, // Default device
                           rc.right, rc.bottom, &myglobs.dev);
    if (FAILED(rval))
    {
        DISPLAYMSG("Failed to create the D3DRM device.");
        return FALSE;
    }

    // Create the master scene frame and the camera frame.
    rval = lpD3DRM->CreateFrame(NULL, &myglobs.scene);
    if (FAILED(rval))
    {
        DISPLAYMSG("Failed to create the master scene frame.");
        return FALSE;
    }

    rval = lpD3DRM->CreateFrame(myglobs.scene, &myglobs.camera);
    if (FAILED(rval))
    {
        DISPLAYMSG("Failed to create the camera's frame.");
        return FALSE;
    }

    // Create the Direct3D Retained Mode viewport using the device, camera frame,
    // and the device's width and height.
    width = myglobs.dev->GetWidth();
    height = myglobs.dev->GetHeight();

    rval = lpD3DRM->CreateViewport(myglobs.dev, myglobs.camera, 0, 0,
                                   width, height, &myglobs.view);
    if (FAILED(rval))
    {
        myglobs.bInitialized = FALSE;
        RELEASE(myglobs.dev);
        return FALSE;
    }

    // Add the media path so textures and .x files can be found
    AddMediaPath( lpD3DRM );

    // Create the scene to be rendered.
    if (!BuildScene(lpD3DRM, myglobs.dev, myglobs.scene,
                    myglobs.camera))
        return FALSE;

    // Globals are initialized.
    myglobs.bInitialized = TRUE;

    return TRUE;
}

InitApp

The InitApp function creates the main window class and the main window, as is typical of Windows applications. The only Direct3D Retained Mode–related call in InitApp is the call to CreateObjects.

InitApp Function Source Code

// Create the main window and initialize objects.

static HWND InitApp(HINSTANCE this_inst, int cmdshow)
{
    HWND win;     // Main window handle
    WNDCLASS wc;  // Window class

    // Set up and register the window class.
    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc = WindowProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = sizeof(DWORD);
    wc.hInstance = this_inst;
    wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
    wc.lpszMenuName = NULL;
    wc.lpszClassName = "D3DRM Example";
    if (!RegisterClass(&wc))
        return FALSE;

    // Create the window.
    win = CreateWindow(
            "D3DRM Example",                   // class
            "RMBegin1: Direct3DRM Sample One", // caption
            WS_OVERLAPPEDWINDOW,               // style
            CW_USEDEFAULT,                     // init. x pos
            CW_USEDEFAULT,                     // init. y pos
            350,                               // init. x size
            300,                               // init. y size
            NULL,                              // parent window
            NULL,                              // menu handle
            this_inst,                         // program handle
            NULL);                             // create parms

    if (!win)
        return FALSE;

    // Initialize global variables and create the Direct3D Retained
    // Mode objects.
    if (!CreateObjects(win))
        return FALSE;

    // Display the window.
    ShowWindow(win, cmdshow);
    UpdateWindow(win);

    return win;
}

WinMain

WinMain provides the main message loop for the application. As long as the global variables are initialized and the application is not minimized, WinMain uses RenderScene to draw the scene to the screen.

WinMain Function Source Code

// Initialize the application, process messages, and render the scene.

int APIENTRY WinMain (HINSTANCE this_inst,
                      HINSTANCE prev_inst,
                      LPSTR cmdline,
                      int cmdshow)
{
    HWND    hwnd;
    MSG     msg;
    prev_inst;
    cmdline;

    // Create the window and initialize objects.
    if (!(hwnd = InitApp(this_inst, cmdshow)))
        return 1;

    while (TRUE)
    {
        // Monitor the message queue and process messages. PeekMessage
        // returns control to the application immediately so that the
        // application can both process messages and continue rendering.
        // If the message is WM_QUIT, break out of this function
        // because the application is terminating.
        if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
        {
            if (msg.message == WM_QUIT)
                break;
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }

        // If the application is not minimized and the Direct3D Retained
        // Mode objects are initialized, render.
        if (!myglobs.bMinimized && myglobs.bInitialized)
        {
            // Render one frame of the scene. If rendering fails, post
            // the WM_DESTROY message, enabling the application to
            // free resources before terminating the application.
            if (!RenderScene())
            {
                DISPLAYMSG("Rendering failed. Aborting execution.");
                PostMessage(NULL, WM_DESTROY, 0, 0);
                break;
            }

        // Yield to other applications if this application is
        // not currently rendering.
        } else
              WaitMessage();

    }
    return msg.wParam;
}

WindowProc

WindowProc handles messages for the main application window. WindowProc sets a flag so that the application stops rendering while minimized. This function also releases objects when the application shuts down.

WindowProc Function Source Code

// Handle messages for the main window.

LRESULT CALLBACK WindowProc(HWND win,
                            UINT msg,
                            WPARAM wparam,
                            LPARAM lparam)
{
    switch (msg)
    {
        case WM_SIZE:
            // Handle minimizing of the window. If the application was
            // minimized, set a flag so that rendering will stop while
            // minimized. Otherwise, continue rendering.
            if (SIZE_MINIMIZED == wparam)
                myglobs.bMinimized = TRUE;
            else
                myglobs.bMinimized = FALSE;
            break;

        case WM_DESTROY:
            // Clear the bInitialized flag, free objects, and post the
            // WM_QUIT message to terminate the application. Be sure to
            // free the viewport before freeing the device, or a general
            // protection fault might occur.
            myglobs.bInitialized = FALSE;
            RELEASE(myglobs.view);
            RELEASE(myglobs.dev);
            RELEASE(lpD3DRM);
            RELEASE(lpDDClipper);
            PostQuitMessage(0);
            break;

        default:
            return DefWindowProc(win, msg, wparam, lparam);
    }
    return 0L;
}

Related Topics

Now that you are familiar with the basics of creating objects and putting something on the screen using Direct3D Retained Mode, the code in the Direct3D Retained Mode samples should be easier to understand. Nearly all of these samples use the helper code provided by RMMain to create a device and render a scene. They each provide their own BuildScene function to create unique scenes.

As a next step, you can look at the RMBegin2 sample, which extends the functionality provided by RMBegin1. You could also look at some of the Direct3D Retained Mode samples, such as Egg or Globe, that provide functionality similar to RMBegin1.

For information about another common task in Direct3D Retained Mode, see Enumerating Devices: The RMEnum Sample, which provides a walkthrough of the RMEnum sample code. RMEnum focuses on how to enumerate devices.

For brief summaries of all of the Retained Mode samples, see Samples.


Frame Hierarchies: The RMBegin2 Sample

Creating a device, building a scene, and moving the scene are fundamental concepts in Microsoft® Direct3D® Retained Mode. The RMBegin2 sample builds on these concepts, which were introduced by the RMBegin1 sample. This article walks you through code from the RMBegin2 sample.

Similar to RMBegin1, RMBegin2 demonstrates creating a default device, loading meshes from Microsoft DirectX® files, adding color to the objects and lights to the scene, and rotating the objects. RMBegin2 builds a more complex scene than RMBegin1, scales the objects, and uses a hierarchy of frames. In the process of building the scene, the sample uses three meshbuilders, several frames, and several lights. The sample also creates a DirectDrawClipper object, viewport and camera. RMBegin2 also adds new functionality by resizing the scene when the application window is resized and by handling the WM_ACTIVATE and WM_PAINT messages.

RMBegin2 provides a hierarchy of frames with three spheres (representing a sun, planet, and moon) revolving around their respective parent frames.

The source code for the RMBegin2 sample consists of one self-contained file (RMBegin2.cpp). For simplicity, this sample doesn't use any separate header files, except for the standard Microsoft Windows®, DirectDraw®, and Direct3D Retained Mode header files. It also does not contain any menus, icons, or other resources.

This sample uses the Sphere0.x, Sphere1.x, and Sphere2.x files from the DirectX Foundation Software Development Kit (SDK) to provide the moon, planet, and sun images for the scene. By default when you install the SDK, the SDK's setup program sets an environment variable to point to the SDK's media directory. These three DirectX (.x) files reside in that directory, allowing the application to locate the file automatically. If you have not installed the SDK and simply run RMBegin2.exe, these DirectX files must be located in the same directory as RMBegin2.exe.

This article assumes you are an experienced C or C++ programmer and are familiar with beginning Windows programming concepts, such as the message loop, creating a window, and using menus.

This article contains the following sections.

  • Dependencies
  • Global Declarations
  • Function Summaries
  • Related Topics

Dependencies

  • RMBegin2 links to DDraw.lib and D3DRM.lib.
  • RMBegin2 loads the sphere images from Sphere0.x, Sphere1.x, and Sphere2.x, as described in the previous section.
  • To properly initialize globally unique identifiers (GUIDs), Direct3D applications must contain the following definition at the top of their code.
    #define INITGUID
  • The sample's RMBegin2.cpp file includes the following header files.
    #include <windows.h>   // Standard Windows header file
#include <direct.h>    // DirectDraw definitions
#include <d3drmwin.h>  // Direct3D Retained Mode definitions

Global Declarations

The sample defines some constants and global variables to help organize information.

The application-defined RELEASE macro releases an object only if the object is not NULL and ensures that an object is initialized to NULL after it has been released. This practice eliminates the problem of trying to release an object that has already been released, which can cause undesired results, such as page faults.

// Macro to release an object.
#define RELEASE(x) if (x != NULL) {x->Release(); x = NULL;}

The application-defined DISPLAYMSG macro uses the Windows MessageBox function to display information to the user. Using this macro rather than direct calls to MessageBox throughout the sample code makes the code cleaner and easier to read.

// Macro to display a message box containing the given string.
#define DISPLAYMSG(x) MessageBox(NULL, x, "D3DRM Sample", MB_OK);

Global variables keep track of the key objects, such as the Direct3D Retained Mode and DirectDrawClipper objects (the DirectDrawClipper object restricts drawing to a designated area). The myglobs structure collects device, window device, viewport, scene, and camera information, as well as information about whether the application is minimized and whether objects have been initialized. Note that RMBegin2 adds a Direct3D Retained Mode window device to the objects RMBegin1 uses.

// Global Variables
LPDIRECT3DRM3 lpD3DRM = NULL;            // Direct3D Retained Mode object
LPDIRECTDRAWCLIPPER lpDDClipper = NULL; // DirectDrawClipper object

// Global Structure
struct _myglobs {

   // Direct3DRM device.
    LPDIRECT3DRMDEVICE3 dev;

    // Direct3DRM window device.
    LPDIRECT3DRMWINDEVICE windevice;

    // Direct3DRM viewport through which to view the scene.
    LPDIRECT3DRMVIEWPORT2 view;

    // Master frame in which other frames are placed.
    LPDIRECT3DRMFRAME3 scene;

    // Frame describing the users point of view.
    LPDIRECT3DRMFRAME3 camera;

    // Application is minimized
    BOOL bMinimized;

    // All Direct3D Retained Mode objects have been initialized.
    BOOL bInitialized;

} myglobs;

Function Summaries

RMBegin2.cpp contains the following functions.

BuildScene creates the scene to be rendered. It loads meshes from DirectX files, scales the meshes, adds color to the meshes, creates a hierarchy of frames, and adds lights to the scene. BuildScene also sets the position of objects and how objects should be rotated. CreateObjects, which initializes global variables and creates default devices, frames, and viewports, uses this function. Although conceptually similar to the RMBegin1 BuildScene function, the RMBegin2 BuildScene functions creates a more complex scene.

BOOL BuildScene(LPDIRECT3DRM3, LPDIRECT3DRMDEVICE3,
                LPDIRECT3DRMFRAME3, LPDIRECT3DRMFRAME3);

RenderScene draws the scene that BuildScene created. Each time WinMain uses this function, RenderScene moves the scene, giving the effect of a spinning object. This function is identical to the RenderScene function provided by the RMBegin1 sample.

static BOOL RenderScene(void);

AddMediaPath provides a path to the textures and .x files needed by the application by searching the registry.

VOID AddMediaPath(LPDIRECT3DRM3 pD3DRM)

CreateObjects initializes the global variables and creates a default device, window device, camera frame, scene frame, and viewport. CreateObjects uses BuildScene to create the scene to be rendered. InitApp, which creates the application's window, uses CreateObjects. This function is identical to the CreateObjects function provided by the RMBegin1 sample, except that it also creates a window device.

BOOL CreateObjects(HWND win);

InitApp provides standard, Windows application code to create the window class and the application's window. It uses CreateObjects to initialize global objects. This function is identical to the InitApp function provided by the RMBegin1 sample, except that it provides a different window caption.

static HWND InitApp(HINSTANCE, int);

WinMain provides the application's message loop. It uses InitApp to initialize the application and uses RenderScene to draw the scene. This function is identical to the WinMain function provided by the RMBegin1 sample.

int APIENTRY WinMain(HINSTANCE, HINSTANCE, LPSTR, int);

WindowProc handles messages for the application. It handles cases where the application is minimized, resized, activated, painted, or destroyed.

LRESULT CALLBACK WindowProc(HWND, UINT, WPARAM, LPARAM);

For more information about these functions, see the following topics in this article.

  • BuildScene
  • RenderScene
  • AddMediaPath
  • CreateObjects
  • InitApp
  • WinMain
  • WindowProc

BuildScene

The BuildScene function creates the scene to be rendered. All Direct3D Retained Mode applications must create a scene, but the code required depends on the scene. Applications typically create frames and lights, add visuals to the scene, and set the position of objects. This function also scales objects and sets up a hierarchy of frames.

This section of this article provides code fragments from the BuildScene function and presents the steps the RMBegin2 sample performs to build the sun, planet, and moon scene. This section also presents the complete source code for the RMBegin2 sample's BuildScene function. If an error occurs, the code uses goto statements to jump to the end of the function and ensure that all objects are properly released before returning from the function.

  1. Load meshes from DirectX files by using the IDirect3DRM3::CreateMeshBuilder and IDirect3DRMMeshBuilder3::Load methods. The following code fragment loads one mesh. The sample uses a similar process to load the other meshes.
        if (FAILED(lpD3DRM->CreateMeshBuilder(&sun_builder)))
        goto generic_error;

    rval = sun_builder->Load("sphere2.x", NULL,
                    D3DRMLOAD_FROMFILE, NULL, NULL);
    if (FAILED(rval)) {
        DISPLAYMSG("Failed to load sphere2.x file.");
        goto ret_with_error;
    }
  2. Scale and color the meshes. The three spheres that the sample loads are all nearly the same size, so the sample increases the size of the sun sphere and decreases the size of the planet and moon spheres. The following code fragment shows this process for one mesh.
        if (FAILED(sun_builder->Scale(D3DVAL(1.2), D3DVAL(1.2),
                                  D3DVAL(1.2))))
        goto generic_error;
    if (FAILED(sun_builder->SetColorRGB(D3DVAL(1.0), D3DVAL(1.0),
                                        D3DVAL(0.0))))
        goto generic_error;
  3. Create a hierarchy of frames within the scene by using the IDirect3DRM3::CreateFrame method. The following code fragment creates a sun frame within the master scene frame, a planet frame within the sun frame, and a moon frame within the planet frame. When the sample sets the object's rotation, this hierarchy governs which objects revolve around the other objects.
        if (FAILED(lpD3DRM->CreateFrame(scene, &sun)))
        goto generic_error;
    if (FAILED(lpD3DRM->CreateFrame(sun, &planet)))
        goto generic_error;
    if (FAILED(lpD3DRM->CreateFrame(planet, &moon)))
        goto generic_error;
  4. Use the meshbuilder object to convert to the underlying meshes by using IDirect3DRMMeshBuilder3::CreateMesh. This code fragment creates the sun mesh.
        if (FAILED(sun_builder->CreateMesh(&sun_mesh)))
        goto generic_error;
  5. Add the loaded meshes into the appropriate child frames by using the IDirect3DRMFrame3::AddVisual method. This code fragment adds the sun mesh into the sun frame.
        if (FAILED(sun->AddVisual((LPDIRECT3DRMVISUAL) sun_mesh)))
        goto generic_error;
  6. Set the camera position within the scene by using the IDirect3DRMFrame3::SetPosition method. Set the other object's position, as well. This code fragment sets the camera's and sun's positions. The sun appears to be straight in front of the camera because the x-coordinate and y-coordinate for the sun position and camera position are the same (0,0).
        if (FAILED(camera->SetPosition(scene, D3DVAL(0), D3DVAL(0),
                                   -D3DVAL(25))))
        goto generic_error;
    if (FAILED(sun->SetPosition(scene, D3DVAL(0), D3DVAL(0),
                                D3DVAL(0))))
        goto generic_error;
  7. Set the frame's rotation by using the IDirect3DRMFrame3::SetRotation method. This fragment sets the sun's rotation.
        if (FAILED(sun->SetRotation(scene, D3DVAL(0), D3DVAL(0),
                                D3DVAL(1),
                                D3DVAL(0.01))))
  8. Create a light frame that is a child of the scene by using the IDirect3DRM3::CreateFrame method. Position the light frame within the scene by using the IDirect3DRMFrame3::SetPosition method. Create a bright point light and add it to the light frame by using the IDirect3DRM3::CreateLightRGB and IDirect3DRMFrame3::AddLight methods.
        if (FAILED(lpD3DRM->CreateFrame(scene, &lights)))
        goto generic_error;
    if (FAILED(lights->SetPosition(scene, D3DVAL(0), D3DVAL(0),
                                -D3DVAL(7))))
        goto generic_error;
    if (FAILED(lpD3DRM->CreateLightRGB(D3DRMLIGHT_POINT, D3DVAL(0.9),
                                  D3DVAL(0.8), D3DVAL(0.7), &light1)))
        goto generic_error;
    if (FAILED(lights->AddLight(light1)))
        goto generic_error;
  9. Create a dim, ambient light and add it to the scene, again by using the IDirect3DRM3::CreateLightRGB and IDirect3DRMFrame3::AddLight methods.
        if (FAILED(lpD3DRM->CreateLightRGB(D3DRMLIGHT_AMBIENT, D3DVAL(0.1),
                                  D3DVAL(0.1), D3DVAL(0.1), &light2)))
        goto generic_error;
    if (FAILED(scene->AddLight(light2)))
        goto generic_error;
  10. Create a bright, parallel point light and add it to the light frame, using the same methods used to create ambient light.
        if (FAILED(lpD3DRM->CreateLightRGB(D3DRMLIGHT_PARALLELPOINT,
                                  D3DVAL(0.9), D3DVAL(0.9), D3DVAL(0.9),
                                  &light3)))
        goto generic_error;
    if (FAILED(sun->AddLight(light3)))
        goto generic_error;
  11. Clean up by releasing all of the objects created by this function.
        RELEASE(sun_builder);
    RELEASE(planet_builder);
    RELEASE(moon_builder);
    RELEASE(sun_mesh);
    RELEASE(planet_mesh);
    RELEASE(moon_mesh);
    RELEASE(sun);
    RELEASE(planet);
    RELEASE(moon);
    RELEASE(lights);
    RELEASE(light1);
    RELEASE(light2);
    RELEASE(light3);

BuildScene Function Source Code

// Create the scene to be rendered.

BOOL BuildScene(LPDIRECT3DRM3 lpD3DRM,  LPDIRECT3DRMDEVICE3 dev,
                 LPDIRECT3DRMFRAME3 scene, LPDIRECT3DRMFRAME3 camera)
{
    LPDIRECT3DRMMESHBUILDER3 sun_builder = NULL;
    LPDIRECT3DRMMESHBUILDER3 planet_builder = NULL;
    LPDIRECT3DRMMESHBUILDER3 moon_builder = NULL;
    LPDIRECT3DRMMESH sun_mesh = NULL;
    LPDIRECT3DRMMESH planet_mesh = NULL;
    LPDIRECT3DRMMESH moon_mesh = NULL;
    LPDIRECT3DRMFRAME3 sun = NULL;
    LPDIRECT3DRMFRAME3 planet = NULL;
    LPDIRECT3DRMFRAME3 moon = NULL;
    LPDIRECT3DRMLIGHT light1 = NULL;
    LPDIRECT3DRMLIGHT light2 = NULL;
    LPDIRECT3DRMLIGHT light3 = NULL;
    LPDIRECT3DRMFRAME3 lights = NULL;
    HRESULT rval;

    // Create a meshbuilder for each DirectX file to be loaded (one
    // for sun, planet, and moon) and load the meshes.
    if (FAILED(lpD3DRM->CreateMeshBuilder(&sun_builder)))
        goto generic_error;
    if (FAILED(lpD3DRM->CreateMeshBuilder(&planet_builder)))
        goto generic_error;
    if (FAILED(lpD3DRM->CreateMeshBuilder(&moon_builder)))
        goto generic_error;

    rval = sun_builder->Load("sphere2.x", NULL,
                    D3DRMLOAD_FROMFILE, NULL, NULL);
    if (FAILED(rval)) {
        DISPLAYMSG("Failed to load sphere2.x file.");
        goto ret_with_error;
    }

    rval = planet_builder->Load("sphere1.x", NULL,
                    D3DRMLOAD_FROMFILE, NULL, NULL);
    if (FAILED(rval)) {
        DISPLAYMSG("Failed to load sphere1.x file.");
    goto ret_with_error;
    }

    rval = moon_builder->Load("sphere0.x", NULL,
                    D3DRMLOAD_FROMFILE, NULL, NULL);
    if (FAILED(rval)) {
        DISPLAYMSG("Failed to load sphere0.x file.");
        goto ret_with_error;
    }

    // Adjust the scale (size) of the sun, planet, and moon meshes.
    // Scale equally in the x-, y-, and z-directions to maintain the
    // spherical shape of each mesh. Increase the size of the sun
    // and decrease the size of the planet and moon meshes to
    // achieve the desired relative sizes.
    if (FAILED(sun_builder->Scale(D3DVAL(1.2), D3DVAL(1.2),
                                  D3DVAL(1.2))))
        goto generic_error;
    if (FAILED(planet_builder->Scale(D3DVAL(0.5), D3DVAL(0.5),
                                     D3DVAL(0.5))))
        goto generic_error;
    if (FAILED(moon_builder->Scale(D3DVAL(0.2), D3DVAL(0.2),
                                   D3DVAL(0.2))))
        goto generic_error;

    // Adjust the color of the sun, planet, and moon meshes.
    // Set the sun to yellow, the planet to greenish-blue, and the
    // moon to red.
    if (FAILED(sun_builder->SetColorRGB(D3DVAL(1.0), D3DVAL(1.0),
                                        D3DVAL(0.0))))
        goto generic_error;
    if (FAILED(planet_builder->SetColorRGB(D3DVAL(0.2), D3DVAL(1.0),
                                           D3DVAL(0.8))))
        goto generic_error;
    if (FAILED(moon_builder->SetColorRGB(D3DVAL(0.7), D3DVAL(0.2),
                                         D3DVAL(0.3))))
        goto generic_error;

    // Create hierarchies of frames:
    // - Sun frame within the master scene frame
    // - Planet frame within the sun frame
    // - Moon frame within the planet frame
    if (FAILED(lpD3DRM->CreateFrame(scene, &sun)))
        goto generic_error;
    if (FAILED(lpD3DRM->CreateFrame(sun, &planet)))
        goto generic_error;
    if (FAILED(lpD3DRM->CreateFrame(planet, &moon)))
        goto generic_error;

    // Create meshes from the meshbuilders to avoid the same future
    // conversion by Direct3D Retained Mode. The meshbuilders could be
    // released now, but for clarity they are released with the other
    // objects at the end of this function.
    if (FAILED(sun_builder->CreateMesh(&sun_mesh)))
        goto generic_error;
    if (FAILED(planet_builder->CreateMesh(&planet_mesh)))
        goto generic_error;
    if (FAILED(moon_builder->CreateMesh(&moon_mesh)))
        goto generic_error;

    // Add the meshes into the frames.
    if (FAILED(sun->AddVisual((LPDIRECT3DRMVISUAL) sun_mesh)))
        goto generic_error;
    if (FAILED(planet->AddVisual((LPDIRECT3DRMVISUAL) planet_mesh)))
        goto generic_error;
    if (FAILED(moon->AddVisual((LPDIRECT3DRMVISUAL) moon_mesh)))
        goto generic_error;

    // Set up the frame positions.
    if (FAILED(camera->SetPosition(scene, D3DVAL(0), D3DVAL(0),
                                   -D3DVAL(25))))
        goto generic_error;
    if (FAILED(sun->SetPosition(scene, D3DVAL(0), D3DVAL(0),
                                D3DVAL(0))))
        goto generic_error;
    if (FAILED(planet->SetPosition(sun, D3DVAL(7), D3DVAL(0),
                                   D3DVAL(0))))
        goto generic_error;
    if (FAILED(moon->SetPosition(planet, D3DVAL(0), D3DVAL(3),
                                 D3DVAL(0))))
        goto generic_error;

    // Set up the frame rotations.
    if (FAILED(sun->SetRotation(scene, D3DVAL(0), D3DVAL(0),
                                D3DVAL(1),
                                D3DVAL(0.01))))
        goto generic_error;
    if (FAILED(planet->SetRotation(sun, D3DVAL(1), D3DVAL(0),
                                   D3DVAL(0),
                                   D3DVAL(0.02))))
        goto generic_error;
    if (FAILED(moon->SetRotation(planet, D3DVAL(0.1), D3DVAL(0.2),
                               D3DVAL(0.7),
                               D3DVAL(0.03))))
       goto generic_error;

    // Initialize the lights in the scene.
    // - Create a light frame. Set its position within the scene
    //   (straight ahead, directly in front of the sun, to illuminate
    //   the sun) and attach a point light to the light frame.
    // - Create a soft, ambient light and add it to the scene.
    // - Create a bright, parallel point light and add it to the sun
    //   frame to properly illuminate the planet and moon as they
    //   revolve around the sun.

    // Create a point light in front of sun.
    if (FAILED(lpD3DRM->CreateFrame(scene, &lights)))
        goto generic_error;
    if (FAILED(lights->SetPosition(scene, D3DVAL(0), D3DVAL(0),
                                -D3DVAL(7))))
        goto generic_error;
    if (FAILED(lpD3DRM->CreateLightRGB(D3DRMLIGHT_POINT, D3DVAL(0.9),
                                  D3DVAL(0.8), D3DVAL(0.7), &light1)))
        goto generic_error;
    if (FAILED(lights->AddLight(light1)))
        goto generic_error;

    // Create an ambient light and add it to the scene.
    if (FAILED(lpD3DRM->CreateLightRGB(D3DRMLIGHT_AMBIENT, D3DVAL(0.1),
                                  D3DVAL(0.1), D3DVAL(0.1), &light2)))
        goto generic_error;
    if (FAILED(scene->AddLight(light2)))
        goto generic_error;

    // Create a parallel point light and add it to the sun frame.
    if (FAILED(lpD3DRM->CreateLightRGB(D3DRMLIGHT_PARALLELPOINT,
                                  D3DVAL(0.9), D3DVAL(0.9), D3DVAL(0.9),
                                  &light3)))
        goto generic_error;
    if (FAILED(sun->AddLight(light3)))
        goto generic_error;

    // Clean up.
    RELEASE(sun_builder);
    RELEASE(planet_builder);
    RELEASE(moon_builder);
    RELEASE(sun_mesh);
    RELEASE(planet_mesh);
    RELEASE(moon_mesh);
    RELEASE(sun);
    RELEASE(planet);
    RELEASE(moon);
    RELEASE(lights);
    RELEASE(light1);
    RELEASE(light2);
    RELEASE(light3);
    return TRUE;

generic_error:
    DISPLAYMSG("A failure occurred while building the scene.");
ret_with_error:
    RELEASE(sun_builder);
    RELEASE(planet_builder);
    RELEASE(moon_builder);
    RELEASE(sun_mesh);
    RELEASE(planet_mesh);
    RELEASE(moon_mesh);
    RELEASE(sun);
    RELEASE(planet);
    RELEASE(moon);
    RELEASE(lights);
    RELEASE(light1);
    RELEASE(light2);
    RELEASE(light3);
    return FALSE;
}

RenderScene

RenderScene performs the actual drawing to the screen. It draws the scene that BuildScene created by performing the following steps.

  1. Move the scene by using IDirect3DRMFrame3::Move.
  2. Clear the viewport by using IDirect3DRMViewport2::Clear.
  3. Render the scene by using IDirect3DRMViewport2::Render.
  4. Update the window by using IDirect3DRMDevice3::Update.

RenderScene Function Source Code

// Clear the viewport, render the next frame, and update the window.

static BOOL RenderScene()
{
    HRESULT rval;

    // Move the scene.
    rval = myglobs.scene->Move(D3DVAL(1.0));
    if (FAILED(rval))
    {
        DISPLAYMSG("Moving scene failed.");
        return FALSE;
    }

    // Clear the viewport.
    rval = myglobs.view->Clear();
    if (FAILED(rval))
    {
        DISPLAYMSG("Clearing viewport failed.");
        return FALSE;
    }

    // Render the scene to the viewport.
    rval = myglobs.view->Render(myglobs.scene);
    if (FAILED(rval))
    {
        DISPLAYMSG("Rendering scene failed.");
        return FALSE;
    }

    // Update the window.
    rval = myglobs.dev->Update();
    if (FAILED(rval))
    {
        DISPLAYMSG("Updating device failed.");
        return FALSE;
    }
    return TRUE;
}

AddMediaPath

AddMediaPath provides a path to the textures and .x files needed by the application. The function searches the system registry for the location of the DirectX 6.0 samples, prepends that location to the path of the directory containing the Retained Mode media files, and adds the whole path to the media files to the end of the current file search path.

AddMediaPath Function Source Code

// Looks in the system registry to determine the media path for the
// sample, then adds that path to the end of the current file search path.

VOID AddMediaPath(LPDIRECT3DRM3 pD3DRM)
{
    HKEY   key;
    LONG   result;
    TCHAR  strPath[512];
    DWORD  type, size = 512;

    // Open the registry
    result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\DirectX",
                          0, KEY_READ, &key);
    if(ERROR_SUCCESS != result)
        return;

    // Search for the desired registry value, and close the registry
    result = RegQueryValueEx(key, "DX6SDK Samples Path", NULL, &type,
                             (BYTE*)strPath, &size);
    RegCloseKey(key);

    if(ERROR_SUCCESS != result)
        return;

    strcat(strPath, "\\D3DRM\\Media");

    pD3DRM->AddSearchPath(strPath);

    return;
}

CreateObjects

CreateObjects initializes the sample's global variables and creates objects. After initializing global variables, CreateObjects performs the steps necessary to create a device, associate it with the application's main window, and create the master scene frame, the camera frame, and the viewport as follows:

  1. Use the DirectDraw DirectDrawCreateClipper function to create a DirectDrawClipper object.
  2. Use the DirectDrawClipper object's SetHWnd method to associate the application's window with the DirectDrawClipper. The DirectDrawClipper object restricts subsequent drawing to a designated area—in this case, the application window.
  3. Use the Direct3DRMCreate function to create a Direct3D Retained Mode object, then query for the IDirect3DRM3 interface.
  4. Use the Windows GetClientRect function to obtain the height and width of the application's main window.
  5. Use the Direct3D Retained Mode object's CreateDeviceFromClipper method to create a device, passing NULL to create a default device, and passing the width and height of the application's window to the method.
  6. Create a Direct3D Retained Mode window device by querying the device for support of the IDirect3DRMWinDevice interface. The window device handles the WM_ACTIVATE and WM_PAINT messages.
  7. Create the master scene frame by using IDirect3DRM3::CreateFrame.
  8. Create the camera frame by using IDirect3DRM3::CreateFrame.
  9. Create the Direct3D Retained Mode viewport by using IDirect3DRM3::CreateViewport.
  10. Use BuildScene to create the scene.

CreateObjects Function Source Code

// Initialize globals, and create the device and objects.

BOOL CreateObjects(HWND win)
{
    HRESULT rval; // Return value
    RECT rc;      // Bounding rectangle for main window
    int width;    // Device's width
    int height;   // Device's height

    // Initialize the entire global variable structure to zero.
    memset(&myglobs, 0, sizeof(myglobs));

    // Create a DirectDrawClipper object and associate the window with it.
    rval = DirectDrawCreateClipper(0, &lpDDClipper, NULL);
    if (FAILED(rval)) {
        DISPLAYMSG("Failed to create DirectDrawClipper object.");
        return FALSE;
    }
    rval = lpDDClipper->SetHWnd(0, win);
    if (FAILED(rval)) {
        DISPLAYMSG("Failed to set the window handle for the DirectDrawClipper.");
        return FALSE;
    }

   // Create the Direct3DRM object.
    LPDIRECT3DRM pD3DRMTemp;
    rval = Direct3DRMCreate(&pD3DRMTemp);
    if (FAILED(rval))
    {
        DISPLAYMSG("Failed to create Direct3DRM.");
        return FALSE;
    }
    if( FAILED(pD3DRMTemp->QueryInterface(IID_IDirect3DRM3, (void **)&lpD3DRM)))
    {
        RELEASE(pD3DRMTemp);
        DISPLAYMSG("Failed query for Direct3DRM3.\n" );
        return FALSE;
    }
    RELEASE(pD3DRMTemp);

    // Create a default Direct3D Retained Mode device.
    GetClientRect(win, &rc);

    rval = lpD3DRM->CreateDeviceFromClipper(lpDDClipper,
                           NULL, // Default device
                           rc.right, rc.bottom, &myglobs.dev);

    if (FAILED(rval)) {
        DISPLAYMSG("Failed to create the D3DRM device.");
        return FALSE;
    }

    // Create a Direct3D Retained Mode window device to handle the
    // WM_ACTIVATE and WM_PAINT messages.
    rval = myglobs.dev->QueryInterface(IID_IDirect3DRMWinDevice,
                                       (void **) &myglobs.windevice);
    if (FAILED(rval)) {
        DISPLAYMSG("Failed to create the window device.");
        return FALSE;
    }

    // Create the master scene frame and the camera frame.
    rval = lpD3DRM->CreateFrame(NULL, &myglobs.scene);
    if (FAILED(rval)) {
        DISPLAYMSG("Failed to create the master scene frame.");
        return FALSE;
    }

    rval = lpD3DRM->CreateFrame(myglobs.scene, &myglobs.camera);
    if (FAILED(rval)) {
        DISPLAYMSG("Failed to create the camera's frame.");
        return FALSE;
    }

    // Create the Direct3D Retained Mode viewport using the device, camera frame,
    // and the device's width and height.
    width = myglobs.dev->GetWidth();
    height = myglobs.dev->GetHeight();

    rval = lpD3DRM->CreateViewport(myglobs.dev, myglobs.camera, 0, 0,
                                   width, height, &myglobs.view);
    if (FAILED(rval)) {
        myglobs.bInitialized = FALSE;
        RELEASE(myglobs.dev);
        return FALSE;
    }

    // Add the media path so textures and .x files can be found.
    AddMediaPath( lpD3DRM );

    // Create the scene to be rendered.
    if (!BuildScene(lpD3DRM, myglobs.dev, myglobs.scene,
                    myglobs.camera))
        return FALSE;

    // Globals are initialized.
    myglobs.bInitialized = TRUE;

    return TRUE;
}

InitApp

The InitApp function creates the main window class and the main window, as is typical of Windows applications. The only Direct3D Retained Mode–related call in InitApp is the call to CreateObjects.

InitApp Function Source Code

// Create the main window and initialize objects.

static HWND InitApp(HINSTANCE this_inst, int cmdshow)
{
    HWND win;     // Main window handle
    WNDCLASS wc;

    // Set up and register the window class.
    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc = WindowProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = sizeof(DWORD);
    wc.hInstance = this_inst;
    wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
    wc.lpszMenuName = NULL;
    wc.lpszClassName = "D3DRM Example";
    if (!RegisterClass(&wc))
        return FALSE;

    // Create the window.
    win = CreateWindow(
            "D3DRM Example",                   // class
            "RMBegin2: Direct3DRM Sample Two", // caption
            WS_OVERLAPPEDWINDOW,               // style
            CW_USEDEFAULT,                     // init. x pos
            CW_USEDEFAULT,                     // init. y pos
            350,                               // init. x size
            300,                               // init. y size
            NULL,                              // parent window
            NULL,                              // menu handle
            this_inst,                         // program handle
            NULL                               // create parms
        );
    if (!win)
        return FALSE;

    // Initialize global variables, enumerate devices, and create the
    // Direct3D Retained Mode objects.
    if (!CreateObjects(win))
        return FALSE;

    // Display the window.
    ShowWindow(win, cmdshow);
    UpdateWindow(win);

    return win;
}

WinMain

WinMain provides the main message loop for the application. As long as the global variables are initialized and the application is not minimized, WinMain uses RenderScene to draw the scene to the screen.

WinMain Function Source Code

// Initialize the application, process messages, and render the scene.

int APIENTRY WinMain (HINSTANCE this_inst,
                      HINSTANCE prev_inst,
                      LPSTR cmdline,
                      int cmdshow)
{
    HWND    hwnd;
    MSG     msg;
    prev_inst;
    cmdline;

    // Create the window and initialize objects.
    if (!(hwnd = InitApp(this_inst, cmdshow)))
        return 1;

    while (TRUE) {
        // Monitor the message queue and process messages. PeekMessage
        // returns control to the application immediately so that the
        // application can both process messages and continue rendering.
        // If the message is WM_QUIT, break out of this function
        // because the application is terminating.
        if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {

            if (msg.message == WM_QUIT)
                break;
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }

        // If the application is not minimized, and the Direct3D Retained
        // Mode objects are initialized, render.
        if (!myglobs.bMinimized && myglobs.bInitialized) {

            // Render one frame of the scene. If rendering fails, post
            // the WM_DESTROY message, enabling the application to
            // free resources before terminating the application.
            if (!RenderScene()) {
                DISPLAYMSG("Rendering failed. Aborting execution.");
                PostMessage(NULL, WM_DESTROY, 0, 0);
                break;
            }

        // Yield to other applications if this application is
        // not currently rendering.
        } else
              WaitMessage();

    }
    return msg.wParam;
}

WindowProc

WindowProc handles messages for the main application window. WindowProc sets a flag so that the application stops rendering while minimized. This function also handles resizing of the application window, activating the window, painting, and releasing objects when the application shuts down.

When the user resizes the application window, the RMBegin2 sample increases or decreases the size of the scene so that it continues to fill the window. This function performs the following steps to handle the WM_SIZE message (window resizing).

  • If the application was minimized, set the minimized flag and break out of the function because there is no more resizing to handle.
  • Obtain the current width and height of the window, viewport, and device.
  • If the application window was resized larger than the current device, destroy the old viewport, device, and window device and create new ones. If the application was resized smaller than the current device, re-create only the viewport.

WindowProc uses the window device to handle the WM_ACTIVATE and WM_PAINT messages by using the IDirect3DRMWinDevice::HandleActivate and IDirect3DRMWinDevice::HandlePaint methods, respectively.

WindowProc Function Source Code

// Handle messages for the main window.

LRESULT CALLBACK WindowProc(HWND win,
                            UINT msg,
                            WPARAM wparam,
                            LPARAM lparam)
{
HRESULT rval;

switch (msg) {

    case WM_SIZE:
        // Handle resizing of the window. If the application was
        // minimized, set a flag so that rendering will stop while minimized
        // and break out of this function. Otherwise, make sure the
        // minimized flag is clear and check for window resizing other
        // than minimized.
        {
        if (SIZE_MINIMIZED == wparam)
        {
            myglobs.bMinimized = TRUE;
            break;
        }
        else
            myglobs.bMinimized = FALSE;

        // Handle resizing of the window. Obtain the window's current
        // width and height.
        int width = LOWORD(lparam);
        int height = HIWORD(lparam);

        // If the global variables, such as the viewport and device,
        // have been initialized, obtain the viewport's and the
        // device's width and height. Create a new device and window
        // device or viewport, as needed. A new device and window device
        // are only needed if the window is larger than the old device.
        if (myglobs.bInitialized)
        {
            int view_width = myglobs.view->GetWidth();
            int view_height = myglobs.view->GetHeight();
            int dev_width = myglobs.dev->GetWidth();
            int dev_height = myglobs.dev->GetHeight();

            // Check whether the window size increased in either
            // width or height.
            if (width > dev_width || height > dev_height)
            {
                // Application window is now larger than the current
                // device. Destroy the old viewport and device and create
                // new ones. Be sure to free the viewport before freeing
                // the device, or a general protection fault might occur.
                myglobs.bInitialized = FALSE;
                RELEASE(myglobs.view);
                RELEASE(myglobs.dev);

                // Create a new, default Direct3D Retained Mode device.
                rval = lpD3DRM->CreateDeviceFromClipper(lpDDClipper,
                                        NULL, // Default device
                                        width, height,
                                        &myglobs.dev);

                if (FAILED(rval))
                {
                    // If the new device could not be created, notify
                    // the user and shut down the application.
                    DISPLAYMSG("Failed to create the D3DRM device.");
                    PostMessage(NULL, WM_DESTROY, 0, 0);
                    return FALSE;
                }

                // Destroy the old Direct3D Retained Mode window device
                // and create a new one to match the newly created
                // device. The window device handles the WM_ACTIVATE and
                // WM_PAINT messages.
                RELEASE(myglobs.windevice);
                rval = myglobs.dev->QueryInterface(
                                       IID_IDirect3DRMWinDevice,
                                       (void **) &myglobs.windevice);
                if (FAILED(rval)) {
                    DISPLAYMSG("Failed to create the window device.");
                    return FALSE;
                }

            }

            // If the window size changed, free the old viewport and
            // create a new viewport of the proper size.
            myglobs.bInitialized = FALSE;
            RELEASE(myglobs.view);
            rval = lpD3DRM->CreateViewport(myglobs.dev,
                                           myglobs.camera,
                                           0, 0, width, height,
                                           &myglobs.view);
            if (FAILED(rval))
            {
                // If the new viewport could not be created, notify
                // the user and shut down the application.
                DISPLAYMSG("Failed to create a new viewport.");
                PostMessage(NULL, WM_DESTROY, 0, 0);
                break;
            }

            myglobs.bInitialized = TRUE;
        }
        }
        break;

    case WM_ACTIVATE:
        // Use the window device's HandleActivate method to handle
        // window activation.
        if (myglobs.bInitialized)
            if (FAILED(myglobs.windevice->HandleActivate(wparam)))
                DISPLAYMSG("Failed to handle WM_ACTIVATE.");
        break;

    case WM_PAINT:
        // Use the window device's HandlePaint method to handle
        // repainting, unless global variables have not yet been
        // initialized.
        if (!myglobs.bInitialized)
            return DefWindowProc(win, msg, wparam, lparam);

        // Use the window device to handle repainting.
        RECT rc;
        PAINTSTRUCT ps;

        if (GetUpdateRect(win, &rc, FALSE)) {
            BeginPaint(win, &ps);
            if (FAILED(myglobs.windevice->HandlePaint(ps.hdc)))
                DISPLAYMSG("Failed to handle WM_PAINT.");
        }
        EndPaint(win, &ps);
        break;

    case WM_DESTROY:
        // Clear the bInitialized flag, free objects, and post the WM_QUIT
        // message to terminate the application. Be sure to free the
        // viewport before freeing the device, or a general protection
        // fault might occur.
        myglobs.bInitialized = FALSE;
        RELEASE(myglobs.view);
        RELEASE(myglobs.windevice);
        RELEASE(myglobs.dev);
        RELEASE(lpD3DRM);
        RELEASE(lpDDClipper);
        PostQuitMessage(0);
        break;

    default:
        return DefWindowProc(win, msg, wparam, lparam);
    }
    return 0L;
}

Related Topics

Now that you are familiar with the basics of creating objects and putting something on the screen using Direct3D Retained Mode, the code in the Direct3D Retained Mode samples should be easier to understand. Nearly all of these samples use the helper code provided by RMMain to create a device and render a scene. They each provide their own BuildScene function to create unique scenes.

As a next step, you can look at some of the other Direct3D Retained Mode samples, such as Egg or Globe, which provide functionality similar to RMBegin1 and RMBegin2.

For information about another common task in Direct3D Retained Mode, see Enumerating Devices: The RMEnum Sample, which provides a walkthrough of the RMEnum sample code. RMEnum focuses on how to enumerate devices.

For brief summaries of all of the Retained Mode samples, see Samples.


Enumerating Devices: The RMEnum Sample

Device enumeration is one of the fundamental concepts in Microsoft® Direct3D® Retained Mode. You can create a default device without device enumeration, but enumerating devices provides more flexibility for your application. It enables you to identify the devices present on a given system, and to choose the device that is most appropriate for your needs and can offer more advanced capabilities.

This article walks you through code from the RMEnum sample. RMEnum enumerates the hardware and software devices on the system, makes an intelligent choice about which device to use, and creates the device. It adds the enumerated devices to the application's File menu and enables the user to switch between devices by choosing devices from the menu. Unlike a real-world Direct3D Retained Mode application, RMEnum does not display any three-dimensional (3-D) objects or render any graphics. It focuses on enumeration for the sake of simplicity and clarity.

This article assumes you are an experienced C or C++ programmer and are familiar with beginning Windows programming concepts, such as the message loop, creating a window, and using menus.

This article contains the following sections.

  • Dependencies
  • Global Declarations
  • Function Summaries
  • Related Topics

Dependencies

RMEnum links to DDraw.lib and D3DRM.lib. It uses the Msg and D3DRMErrorToString helper functions from Error.c to provide detailed information in case of errors. By default, Error.c resides in the Samples\Misc directory of the Microsoft® DirectX® Software Development Kit (SDK). RMEnum could just as easily use the standard Microsoft® Windows® MessageBox function instead of using these helper functions, but the error reporting would not be as clean or detailed. The sample also links to the menus and other resources provided by RMEnum.rc.

To properly initialize globally unique identifiers (GUIDs), Direct3D applications must contain the following definition at the top of their code.

#define INITGUID

The sample's RMEnum.cpp file includes the following header files.

#include <windows.h>   /* Standard Windows header file */
#include <direct.h>    /* DirectDraw definitions */
#include <d3drmwin.h>  /* D3DRM definitions */
#include "RMEnum.h"    /* Defines constants used in RMEnum.rc */
#include "rmerror.h"   /* Prototypes for error reporting functions in
                             rmerror.c */

Global Declarations

The sample defines some constants and global variables to help organize information.

For simplicity, RMEnum.cpp sets an arbitrary limit on the number of drivers it will enumerate. You could enumerate drivers once to count how many are available, and enumerate again to examine each driver's capabilities as this sample does. A real-world same could also maintain a linked list of driver information rather than a fixed size array as RMEnum does.

#define MAX_DRIVERS 5  /* Arbitrary limit for the maximum number of
                            Direct3D drivers expected to be found */

The application-defined RELEASE macro releases an object only if the object is not NULL and ensures that an object is initialized to NULL after it has been released. This practice eliminates the problem of trying to release an object that has already been released, which can, in turn, cause undesired results, such as page faults.

/* Macro to release an object. */
#define RELEASE(x) if (x != NULL) {x->Release(); x = NULL;}

The myglobs structure collects device and driver information, as well as information about the current application state. The Direct3D Retained Mode and DirectDrawClipper objects are also global (the DirectDrawClipper object restricts drawing to a designated area).

/*
 * GLOBAL VARIABLES
 */
LPDIRECT3DRM lpD3DRM = NULL;            /* Direct3DRM object */
LPDIRECTDRAWCLIPPER lpDDClipper = NULL; /* DirectDrawClipper object */

struct _myglobs {
    /* Direct3DRM device */
    LPDIRECT3DRMDEVICE dev;

    /* GUIDs of the available Direct3D (D3D) drivers */
    GUID DriverGUID[MAX_DRIVERS];

    /* names of the available D3D drivers */
    char DriverName[MAX_DRIVERS][50];

    /* counter indicating the number of available D3D drivers */
    int  NumDrivers;

    /* number of the D3D driver currently being used; set to
     * the preferred driver by enumDeviceFunc */
    int  CurrDriver;

    /* program is about to terminate */
    BOOL bQuit;

    /* all D3DRM objects have been initialized */
    BOOL bInitialized;

    /* bit depth of the current display mode */
    DWORD BPP;
} myglobs;

Function Summaries

RMEnum.cpp contains the following functions.

CreateObjects is the master function that initializes the global variables, uses EnumDevices to enumerate the devices, and creates objects. InitApp uses CreateObjects.

BOOL CreateObjects(HWND win);

GetCurrentBitDepth returns the current bit depth to CreateObjects.

static DWORD GetCurrentBitDepth(HWND);

EnumDevices obtains the Direct3D object to use for device enumeration, uses the Immediate Mode IDirect3D::EnumDevices function, passing the enumDeviceFunc callback function as a parameter, and places the enumerated devices on the File menu.

static BOOL EnumDevices(HWND);

The enumDeviceFunc callback function cycles through the available drivers, chooses the usable drivers, and selects a preferred driver.

static HRESULT WINAPI enumDeviceFunc(LPGUID,
                                            LPSTR,
                                            LPSTR,
                                            LPD3DDEVICEDESC,
                                            LPD3DDEVICEDESC,
                                            LPVOID);

RMEnum uses ChangeDriver in response to the user's menu choice that switches to a differenct available driver.

void ChangeDriver(HWND, WPARAM);

CleanUpAndQuit releases objects in preparation for application termination.

static void CleanUpAndQuit(void);

The remaining functions (InitApp, WinMain, AppAbout, and WindowProc) are primarily based on the standard Windows functions and contain little code specific to the RMEnum sample.

static HWND InitApp(HINSTANCE, int);
int APIENTRY WinMain (HINSTANCE, HINSTANCE, LPSTR, int);
LRESULT CALLBACK AppAbout(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK WindowProc(HWND, UINT, WPARAM, LPARAM);

For more information about these functions, see the following topics in this article.

  • CreateObjects
  • GetCurrentBitDepth
  • EnumDevices
  • enumDeviceFunc
  • ChangeDriver
  • CleanUpAndQuit
  • Standard Windows Functions

CreateObjects

CreateObjects provides and uses the core code in the RMEnum sample. After initializing global variables and obtaining the current bit depth, it uses EnumDevices to actually enumerate the devices. The enumDeviceFunc callback function later uses the bit depth to determine which drivers support the current bit depth.

After enumerating devices, CreateObjects performs the steps necessary to create a device and associate it with the application's main window as follows:

  1. Uses Direct3DRMCreate to create a Direct3D Retained Mode object.
  2. Uses the DirectDraw DirectDrawCreateClipper function to create a DirectDrawClipper object.
  3. Uses the DirectDrawClipper's SetHWnd method to associate the application's window with the clipper. The DirectDrawClipper object restricts subsequent drawing to a designated area—in this case, to the application window.
  4. Uses the Windows GetClientRect function to obtain the height and width of the application's main window.
  5. Uses the Direct3D Retained Mode object's CreateDeviceFromClipper method to create the device, passing the preferred driver selected by the enumeration, and the width and height of the application's window, to the method.

The CreateObjects function's source code follows:

/*
 * Initialize globals, enumerate devices and create objects.
 */
BOOL CreateObjects(HWND win)
{
    HRESULT rval; /* Return value */
    RECT rc;      /* Bounding rectangle for main window */

    /*
     * Initialize the global variables.
     */
    memset(&myglobs, 0, sizeof(myglobs));

    /*
     * Record the current display bit depth.
     */
     myglobs.BPP = GetCurrentBitDepth(win);

    /*
     * Enumerate the D3D drivers and select one.
     */
    if (!EnumDevices(win))
        return FALSE;

    /*
     * Create the Direct3DRM object and the window object.
     */
    rval = Direct3DRMCreate(&lpD3DRM);
    if (rval != D3DRM_OK) {
        Msg("Failed to create Direct3DRM.\n%s", D3DRMErrorToString(rval));
        return FALSE;
    }

    /*
     * Create a DirectDrawClipper object and associate the window with it.
     */
    rval = DirectDrawCreateClipper(0, &lpDDClipper, NULL);
    if (rval != DD_OK) {
        Msg("Failed to create DirectDrawClipper object");
        return FALSE;
    }
    rval = lpDDClipper->SetHWnd(0, win);
    if (rval != DD_OK) {
        Msg("Failed to set the window handle for the DirectDrawClipper");
        return FALSE;
    }
    /*
     * Create the D3DRM device with the selected D3D driver. The GUID can
     * be NULL to create a default device without enumeration.
     */
    GetClientRect(win, &rc);

    rval = lpD3DRM->CreateDeviceFromClipper(lpDDClipper,
                           &myglobs.DriverGUID[myglobs.CurrDriver],
                           rc.right, rc.bottom, &myglobs.dev);

    if (rval) {
        Msg("Failed to create the D3DRM device.\n%s",
            D3DRMErrorToString(rval));
        return FALSE;
    }

    /*
     * Globals are initialized
     */
    myglobs.bInitialized = TRUE;

    return TRUE;
}

GetCurrentBitDepth

The GetCurrentBitDepth function determines the current device's bit depth capabilities and returns that information in the form of a DirectDraw bit depth flag. Bit depth refers to the device's color settings, such as 8-bit, 16-bit, or 24-bit color.

/*
 * Retrieve a DirectDraw bit depth flag reflecting the current
 * display bit depth in bits per pixel (BPP).
 */
static DWORD GetCurrentBitDepth(HWND win)
{
    HDC hdc;
    int BPP;

    /*
     * Record the current display's BPP.
     */
    hdc = GetDC(win);
    BPP = GetDeviceCaps(hdc, BITSPIXEL);
    ReleaseDC(win, hdc);

    /*
     * Map BPP value to DirectDraw bit depth.
     */
    switch(BPP) {
        case 1:
            return DDBD_1;
        case 2:
            return DDBD_2;
        case 4:
            return DDBD_4;
        case 8:
            return DDBD_8;
        case 16:
            return DDBD_16;
        case 24:
            return DDBD_24;
        case 32:
            return DDBD_32;
        default:
            return 0;
    }
}

EnumDevices

The RMEnum EnumDevices function performs the following steps to enumerate devices. The steps include variables and code fragments from the sample.

  1. Uses the DirectDrawCreate function to create a DirectDraw object.
    LPDIRECTDRAW lpDD;
HRESULT rval;
rval = DirectDrawCreate(NULL, &lpDD, NULL);
  2. Uses the DirectDraw object's QueryInterface method to obtain a Direct3D Immediate Mode object. For more information on Direct3D Immediate Mode, see the DirectX Foundation SDK.
    LPDIRECT3D lpD3D;
rval = lpDD->QueryInterface(IID_IDirect3D, (void**) &lpD3D);
  3. Uses the Direct3D Immediate Mode object's IDirect3D::EnumDevices function to enumerate the devices on the system. IDirect3D::EnumDevices passes the enumDeviceFunc callback function as a parameter.
    rval = lpD3D->EnumDevices(enumDeviceFunc, &myglobs.CurrDriver);

    The callback function cycles through the available devices and selects the drivers that are compatible with certain criteria.

After it has enumerated the drivers, RMEnum's EnumDevices function releases the DirectDraw and Direct3D devices and adds the drivers to the application's File menu.

lpD3D->Release();
lpDD->Release();

Complete source code for RMEnum's EnumDevices function follows:

/*
 * EnumDevices
 * Enumerate the available Direct3D drivers, add them to the file menu,
 * and choose one to use.
 */
static BOOL EnumDevices(HWND win)
{
    LPDIRECTDRAW lpDD;
    LPDIRECT3D lpD3D;
    HRESULT rval;
    HMENU hmenu;
    int i;

    /*
     * Create a DirectDraw object and query for the Direct3D interface
     * to use to enumerate the drivers.
     */
    rval = DirectDrawCreate(NULL, &lpDD, NULL);
    if (rval != DD_OK) {
        Msg("Creation of DirectDraw HEL failed.\n%s",
            D3DRMErrorToString(rval));
        return FALSE;
    }
    rval = lpDD->QueryInterface(IID_IDirect3D, (void**) &lpD3D);
    if (rval != DD_OK) {
        Msg("Creation of Direct3D interface failed.\n%s",
            D3DRMErrorToString(rval));
        lpDD->Release();
        return FALSE;
    }
    /*
     * Enumerate the drivers. Pass the arbitrary value of -1 as
     * application-defined data. The enumDeviceFunc callback function
     * performs special-case initialization code in response to a -1.
     */
    myglobs.CurrDriver = -1;
    rval = lpD3D->EnumDevices(enumDeviceFunc, &myglobs.CurrDriver);
    if (rval != DD_OK) {
        Msg("Enumeration of drivers failed.\n%s",
            D3DRMErrorToString(rval));
        return FALSE;
    }
    /*
     * Make sure we found at least one valid driver.
     */
    if (myglobs.NumDrivers == 0) {
        Msg("Could not find a D3D driver that is compatible with this \
            display depth");
        return FALSE;
    }
    lpD3D->Release();
    lpDD->Release();
    /*
     * Add the driver names to the File menu.
     */
    hmenu = GetSubMenu(GetMenu(win), 0);
    for (i = 0; i < myglobs.NumDrivers; i++) {
        InsertMenu(hmenu, 2 + i, MF_BYPOSITION | MF_STRING,
                   MENU_FIRST_DRIVER + i,
                   myglobs.DriverName[i]);
    }
    return TRUE;
}

enumDeviceFunc

Direct3D Immediate Mode defines D3DENUMDEVICESCALLBACK as the prototype definition for the callback function to enumerate installed Direct3D devices. RMEnum provides enumDeviceFunc as this enumeration callback function. Direct3D Immediate Mode calls enumDeviceFunc repeatedly, once for each device on the system, and passes device information to enumDeviceFunc each time. As D3D Immediate Mode loops through the available drivers, enumDeviceFunc saves information about drivers that can render in the current display bit depth into global variables. enumDeviceFunc chooses hardware drivers over software emulation drivers because hardware drivers typically render faster and chooses color lights over monochromatic lights for better-looking 3-D lighting. These choices do not actually come into play with this sample, because RMEnum does no rendering, but they do effect real applications and can have a large impact on the appearance of 3-D graphics.

enumDeviceFunc's parameters include the device's globally unique identifier (GUID), a textual description of the device, and the device name. Other parameters include pointers to two Direct3D Immediate Mode D3DDEVICEDESC structures. The first structure (lpHWDesc) contains the hardware capabilities of the Direct3D device and the other structure (lpHELDesc) contains the Hardware Emulation Layer (HEL) software emulation capabilities of the device. The last parameter is application-defined data passed to this callback function the first time Direct3D Immediate Mode calls it.

Complete source code for RMEnum's enumDeviceFunc callback function follows:

/*
 * enumDeviceFunc
 * Callback function which records each usable D3D driver's name and
 * GUID. It selects the preferred driver on the system by choosing
 * hardware drivers over software drivers, and color lights over
 * monochrome lights. It sets myglobs.CurrDriver to indicate the
 * preferred driver.
 */
static HRESULT WINAPI enumDeviceFunc(LPGUID lpGuid,
                                     LPSTR lpDeviceDescription,
                                     LPSTR lpDeviceName,
                                     LPD3DDEVICEDESC lpHWDesc,
                                     LPD3DDEVICEDESC lpHELDesc,
                                     LPVOID lpContext)
{
    static BOOL hardware = FALSE; /* current start driver is software */
    static BOOL mono = FALSE;     /* current start driver is color */
    LPD3DDEVICEDESC lpDesc;       /* description of current driver */

    /*
     * Data defined by this application that, when it equals -1,
     * indicates that the current driver is the first to be enumerated
     */
    int *lpStartDriver = (int *)lpContext;

    /*
     * Decide which device description to consult. The driver is either
     * hardware (HW) or software. Software drivers provide support
     * through the hardware emulation layer (HEL).
     */
    lpDesc = lpHWDesc->dcmColorModel ? lpHWDesc : lpHELDesc;
    /*
     * If this driver cannot render in the current display bit depth,
     * return D3DENUMRET_OK to skip this driver. Enumeration continues
     * automatically as D3D calls enumDeviceFunc again for the next
     * driver.
     */
    if (!(lpDesc->dwDeviceRenderBitDepth & myglobs.BPP))
        return D3DENUMRET_OK;
    /*
     * Record this driver's GUID and name.
     */
    memcpy(&myglobs.DriverGUID[myglobs.NumDrivers], lpGuid, sizeof(GUID));
    lstrcpy(&myglobs.DriverName[myglobs.NumDrivers][0], lpDeviceName);
    /*
     * Choose hardware over software, and color lights over monochrome
     * lights.
     */
    if (*lpStartDriver == (int)-1) {
        /*
         * This is the first valid driver, so record whether this driver
         * is a hardware driver or not, and whether it is limited to
         * monochrome lights or not.
         */
        myglobs.CurrDriver = myglobs.NumDrivers;
        hardware = lpDesc == lpHWDesc ? TRUE : FALSE;
        mono = lpDesc->dcmColorModel & D3DCOLOR_MONO ? TRUE : FALSE;
    } else if (lpDesc == lpHWDesc && !hardware) {
        /*
         * If this driver is a hardware driver and the start driver is not,
         * then make this driver the new preferred driver and record
         * its hardware and mono capabilities. The next time D3D calls
         * enumDeviceFunc, that driver will be compared against this
         * new start driver.
         */
        myglobs.CurrDriver = myglobs.NumDrivers;
        hardware = lpDesc == lpHWDesc ? TRUE : FALSE;
        mono = lpDesc->dcmColorModel & D3DCOLOR_MONO ? TRUE : FALSE;
    } else if ((lpDesc == lpHWDesc && hardware ) || (lpDesc == lpHELDesc
                                                     && !hardware)) {
        if (lpDesc->dcmColorModel == D3DCOLOR_RGB && mono) {
            /*
             * If this driver and the start driver are the same type
             * (both hardware or both software) and this driver is
             * color while the start driver is not, then make this driver
             * the new preferred driver and record its capabilities.
             * The next time D3D calls enumDeviceFunc, that driver will
             * be compared against this new start driver.
             */
            myglobs.CurrDriver = myglobs.NumDrivers;
            hardware = lpDesc == lpHWDesc ? TRUE : FALSE;
            mono = lpDesc->dcmColorModel & D3DCOLOR_MONO ? TRUE : FALSE;
        }
    }
    /*
     * Increment the current driver number in preparation for the next
     * driver.
     */
    myglobs.NumDrivers++;

    /* Maximum number of drivers reached, stop enumeration. */
    if (myglobs.NumDrivers == MAX_DRIVERS)
        return (D3DENUMRET_CANCEL);
    /*
     * Continue enumerating drivers. D3D will call enumDeviceFunc
     * again with information for the next driver.
     */
    return (D3DENUMRET_OK);
}

ChangeDriver

ChangeDriver is not a required function in the RMEnum sample, but it does add flexibility by enabling the user to choose between drivers. ChangeDriver changes the current driver in response to a menu selection. It re-creates the device by using the Direct3D Retained Mode object's CreateDeviceFromClipper method, much as RMEnum's CreateObjects function originally created the device.

The ChangeDriver source code follows:

/*
 * Release the current device and create the new one.
 */
void ChangeDriver(HWND win, WPARAM wparam)
{
    HRESULT rval;
    RECT rc;

    /*
     * Save the previous driver selection as LastDriver.
     */
    int LastDriver = myglobs.CurrDriver;

    /*
     * Globals are no longer correct since the selection is changing.
     */
    myglobs.bInitialized = FALSE;

    /*
     * Release the current device.
     */
    RELEASE(myglobs.dev);

    /*
     * Set the current driver to the driver selected through the menu.
     */
    myglobs.CurrDriver = LOWORD(wparam)-MENU_FIRST_DRIVER;

    /*
     * Obtain the window rectangle and create the new current driver
     * for that window using the global DirectDrawClipper object.
     */
    GetClientRect(win, &rc);

    rval = lpD3DRM->CreateDeviceFromClipper(lpDDClipper,
                             &myglobs.DriverGUID[myglobs.CurrDriver],
                             rc.right, rc.bottom, &myglobs.dev);

    /*
     * If an error occurred, try to recreate the previous driver.
     */
    if (rval) {
        myglobs.CurrDriver = LastDriver;

        rval = lpD3DRM->CreateDeviceFromClipper(lpDDClipper,
                                 &myglobs.DriverGUID[myglobs.CurrDriver],
                                 rc.right, rc.bottom, &myglobs.dev);
        if (rval) {
            Msg("Failed to create the D3DRM device.\n%s",
                D3DRMErrorToString(rval));
            CleanUpAndQuit();
        }
        else {
            Msg("There was not enough video memory available to use the \
                 3D accelerated hardware device.\nRestoring old software \
                 device.");
            myglobs.bInitialized = TRUE;
        }
    }
    else {
        /*
         * Globals are properly initialized again.
         */
        myglobs.bInitialized = TRUE;
    }
}

CleanUpAndQuit

The small CleanUpAndQuit function releases global objects and sets the quit flag to TRUE to indicate that the application is ready to quit.

void CleanUpAndQuit(void)
{
    myglobs.bInitialized = FALSE;
    RELEASE(myglobs.dev);
    RELEASE(lpD3DRM);
    RELEASE(lpDDClipper);
    myglobs.bQuit = TRUE;
}

Standard Windows Functions

The remaining functions in RMEnum.cpp (InitApp, WinMain, AppAbout, and WindowProc) are primarily the standard Windows functions and contain little code that is specific to the RMEnum sample. See the RMEnum sample code for more information.

  • InitApp creates the main window and uses the sample's CreateObjects function.
  • WinMain calls the InitApp function. It also contains the main Windows message loop that handles messages until the global myglobs.bQuit variable is TRUE. WinMain uses CleanUpAndQuit in response to the standard Windows WM_QUIT message, indicating that the application is terminating.
  • AppAbout handles messages for the application's About dialog box.
  • WindowProc handles messages for the main application window. It initializes the File menu with the enumerated driver choices and handles the user's driver selection by using the application's ChangeDriver function. WindowProc uses CleanUpAndQuit to release resources in response to the standard Windows WM_DESTROY message indicating that Windows is in the process of destroying the application window because the user terminated the application.

Related Topics

Now that you are familiar with how to enumerate devices, the code in the Direct3D Retained Mode samples should be easier to understand. Nearly all of these samples use the helper code provided by RMMain to enumerate devices. As a next step, you can look at the Egg or the Globe sample to see how they perform rendering, knowing that they use device enumeration behind the scenes.

For brief summaries of all of the Retained Mode samples, see Samples.


Technical Background

The following topics describe some of the technical concepts you need to understand before you write programs that incorporate 3-D graphics. In these sections, you will find a general discussion of coordinate systems and transformations. This is not a discussion of broad architectural details, such as setting up models, lights, and viewing parameters. For more information about these topics, see Direct3D Retained Mode Architecture.

If you are already experienced in producing 3-D graphics, simply scan the following topics for information that is unique to Microsoft® Direct3D® Retained Mode:

  • 3-D Coordinate Systems
  • 3-D Transformations
  • Polygons
  • Triangle Strips and Fans
  • Vectors, Vertices, and Quaternions
  • Floating-Point Precision
  • Z-Buffers and Overlays

3-D Coordinate Systems

There are two varieties of Cartesian coordinate systems in 3-D graphics: left-handed and right-handed. In both coordinate systems, the positive x-axis points to the right and the positive y-axis points up. You can remember which direction the positive z-axis points by pointing the fingers of either your left or right hand in the positive x-direction and curling them into the positive y-direction. The direction your thumb points, either toward or away from you, is the direction the positive z-axis points for that coordinate system.

This section describes the Direct3D coordinate system and coordinate types that your application can use.

  • Direct3D Coordinate System
  • U- and V-Coordinates

Direct3D Coordinate System

Direct3D uses the left-handed coordinate system by default. This means the positive z-axis points away from the viewer, as shown in the following illustration:

Direct3D coordinate system

In a left-handed coordinate system, rotations occur clockwise around any axis that is pointed at the viewer.

If you need to work in a right-handed coordinate system—for example, if you are porting an application that relies on right-handedness—you can do so by making two simple changes to the data passed to Direct3D.

Note: Beginning with DirectX version 6.0, you can use IDirect3DRM3::SetOptions to instruct Direct3D Retained Mode to use a right-handed coordinate system. If you use IDirect3DRM3::SetOptions, changing data is not necessary.

Versions of DirectX prior to version 6.0 require the following changes to the data passed to Direct3D Retained Mode to use right-handed coordinates.

  • Flip the order of triangle vertices so that the system traverses them clockwise from the front. In other words, if the vertices are v0, v1, v2, pass them to Direct3D as v0, v2, v1.
  • Scale the projection matrix by –1 in the z-direction. To do this, flip the signs of the _13, _23, _33, and _43 members of the D3DMATRIX structure.

U- and V-Coordinates

Direct3D also uses texture coordinates. These coordinates (u and v) are used when mapping textures onto an object. The v-vector describes the direction or orientation of the texture and lies along the z-axis. The u-vector (or the up vector) typically lies along the y-axis, with its origin at [0,0,0]. For more information about u- and v-coordinates, see Wraps.

3-D Transformations

In programs that work with 3-D graphics, you can use geometrical transformations to:

  • Express the location of an object relative to another object.
  • Rotate, shear, and size objects.
  • Change viewing positions, directions, and perspective.

You can transform any point into another point by using a 4×4 matrix. In the following example, a matrix is used to reinterpret the point (x, y, z), producing the new point (x', y', z'):

Transformation of a point with a 4×4 matrix

You perform the following operations on (x, y, z) and the matrix to produce the point (x', y', z'):

Operations within the matrix transformation

The most common transformations are translation, rotation, and scaling. You can combine the matrices that produce these effects into a single matrix to calculate several transformations at once. For example, you can build a single matrix to translate and rotate a series of points.

Matrices are specified in row order. For example, the following matrix could be represented by an array:

Sample matrix that is represented by the array below

The array for this matrix would look like the following:

D3DMATRIX scale = {
    D3DVAL(s),    0,            0,            0,
    0,            D3DVAL(s),    D3DVAL(t),    0,
    0,            0,            D3DVAL(s),    D3DVAL(v),
    0,            0,            0,            D3DVAL(1)
};

This section describes the 3-D transformations available to your applications through Direct3D.

  • Translation
  • Rotation
  • Scaling

Other parts of this documentation also discuss transformations. You can find a general discussion of transformations in the section devoted to viewports in Retained Mode, Transformations. For a discussion of transformations in frames, see Transformations. Although each of these sections discusses Retained Mode API, the architecture and mathematics of the transformations apply to both Retained Mode and Immediate Mode.

Translation

The following transformation translates the point (x, y, z) to a new point (x', y', z'):

Matrix that translates a point

Rotation

The transformations described in this section are for left-handed coordinate systems, and so they may be different from transformation matrices you have seen elsewhere.

The following transformation rotates the point (x, y, z) around the x-axis, producing a new point (x', y', z'):

Matrix that rotates a point around the x-axis

The following transformation rotates the point around the y-axis:

Matrix that rotates a point around the y-axis

The following transformation rotates the point around the z-axis:

Matrix that rotates a point around the z-axis

Note that in these example matrices, the Greek letter theta stands for the angle of rotation, specified in radians. Angles are measured clockwise when looking along the rotation axis toward the origin.

Scaling

The following transformation scales the point (x, y, z) by arbitrary values in the x-, y-, and z-directions to a new point (x', y', z'):

Matrix that scales a point

Polygons

Three-dimensional objects in Direct3D are made up of meshes. A mesh is a set of faces, each of which is described by a simple polygon. The fundamental polygon type is the triangle. Although Retained Mode applications can specify polygons with more than three vertices, the system translates these into triangles before the objects are rendered. Immediate Mode applications must use triangles.

This section describes how your applications can use Direct3D polygons.

  • Geometry Requirements
  • Face and Vertex Normals
  • Shade Modes
  • Interpolated Triangle Characteristics

Geometry Requirements

Triangles are the preferred polygon type because they are always convex, and they are always planar—two conditions that are required of polygons by the renderer. A polygon is convex if a line drawn between any two points of the polygon is also inside the polygon.

Diagram of concave and convex polygons

The three vertices of a triangle always describe a plane, but it is easy to accidentally create a nonplanar polygon by adding another vertex.

Diagram of nonplanar polygon

Face and Vertex Normals

Each face in a mesh has a perpendicular face normal vector whose direction is determined by the order in which the vertices are defined and by whether the coordinate system is right- or left-handed. If the normal vector of a face is oriented toward the viewer, that side of the face is its front. In Direct3D, only the front side of a face is visible, and a front face is one in which vertices are defined in clockwise order.

Diagram of a polygon face's vertices and normal vector

Direct3D applications do not need to specify face normals; the system calculates them automatically when they are needed. The system uses face normals in the flat shade mode. For Phong and Gouraud shade modes, and for controlling lighting and texturing effects, the system uses vertex normals.

Diagram of vertex normals and face normals

Shade Modes

In the flat shade mode, the system duplicates the color of one vertex across all the other faces of the primitive. In the Gouraud and Phong shade modes, vertex normals are used to give a smooth look to a polygonal object. In Gouraud shading, the color and intensity of adjacent vertices is interpolated across the space that separates them. In Phong shading, the system calculates the appropriate shade value for each pixel on a face.

Note Phong shading is not currently supported.

Most applications use Gouraud shading because it allows objects to appear smooth and is computationally efficient. However, Gouraud shading can miss details that Phong shading will not. For example, Gouraud and Phong shading would produce very different results as shown by the following illustration, in which a spotlight is completely contained within a face.

Diagram of a spotlight on a face for comparison of Gouraud and Phong shading

In this case, the Phong shade mode would calculate the value for each pixel and display the spotlight. The Gouraud shade mode, which interpolates between vertices, would miss the spotlight altogether; the face would be rendered as though the spotlight did not exist.

In the flat shade mode, the following pyramid would be displayed with a sharp edge between adjoining faces; the system would generate automatic face normals. In the Gouraud or Phong shade modes, however, shading values would be interpolated across the edge, and the final appearance would be of a curved surface.

A pyramid in the flat shade mode

If you want to use the Gouraud or Phong shade mode to display curved surfaces, and you also want to include some objects with sharp edges, your application would need to duplicate the vertex normals at any intersection of faces where a sharp edge was required, as shown in the following illustration.

Vertex normals needed to retain sharp edge in shading other than flat

In addition to allowing a single object to have both curved and flat surfaces, the Gouraud shade mode lights flat surfaces more realistically than the flat shade mode. A face in the flat shade mode is a uniform color, but Gouraud shading allows light to fall across a face correctly. This effect is particularly obvious if there is a nearby point source. Gouraud shading is the preferred shade mode for most Direct3D applications.

Interpolated Triangle Characteristics

The system interpolates the characteristics of a triangle's vertices across the triangle when it renders a face. The following triangle characteristics are interpolated:

  • Color
  • Specular
  • Fog
  • Alpha

All of the triangle's interpolated characteristics are modified by the current shade mode:

Flat | No interpolation is done. Instead, the color of the first vertex in the triangle is applied across the entire face.
Gouraud | Linear interpolation is performed between all three vertices.
Phong | Vertex parameters are re-evaluated for each pixel in the face, using the current lighting. The Phong shade mode is not currently supported.

The interpolated color and specular characteristics are treated differently, depending on the color model. In the RGB color model (D3DCOLOR_RGB), the system uses the red, green, and blue color components in the interpolation. In the monochromatic model (D3DCOLOR_MONO), the system uses only the blue component of the vertex color.

For example, if the red component of the color of vertex 1 were 0.8 and the red component of vertex 2 were 0.4, in the Gouraud shade mode and RGB color model the system would use interpolation to assign a red component of 0.6 to the pixel at the midpoint of the line between these vertices.

The alpha component of a color is treated as a separate interpolated characteristic because device drivers can implement transparency in two different ways: by using texture blending or by using stippling.

An application can use the dwShadeCaps member of the D3DPRIMCAPS structure to determine what forms of interpolation the current device driver supports.

Triangle Strips and Fans

You can use triangle strips and triangle fans to specify an entire surface without having to provide all three vertices for each of the triangles. For example, only seven vertices are required to define the following triangle strip.

Sample triangle strip and its vertices

The system uses vertices v1, v2, and v3 to draw the first triangle; v2, v4, and v3 to draw the second triangle; v3, v4, and v5 to draw the third; v4, v6, and v5 to draw the fourth; and so on. Notice that the vertices of the second and fourth triangles are out of order. This is required to make sure that all of the triangles are drawn in a clockwise orientation.

A triangle fan is similar to a triangle strip, except that all of the triangles share one vertex.

Diagram of a triangle fan

The system uses vertices v1, v2, and v3 to draw the first triangle; v3, v4, and v1 to draw the second triangle; v1, v4, and v5 to draw the third triangle; and so on.

You can use the wFlags member of the D3DTRIANGLE structure to specify the flags that build triangle strips and fans.

Vectors, Vertices, and Quaternions

Throughout Direct3D, vertices describe position and orientation. Each vertex in a primitive is described by a vector that gives its position, a normal vector that gives its orientation, texture coordinates, and a color. (In Retained Mode, the D3DRMVERTEX structure contains these values.)

Quaternions add a fourth element to the [x, y, z] values that define a vector. Quaternions are an alternative to the matrix methods that are typically used for 3-D rotations. A quaternion represents an axis in 3-D space and a rotation around that axis. For example, a quaternion could represent a (1,1,2) axis and a rotation of 1 radian. Quaternions carry valuable information, but their true power comes from the two operations that you can perform on them: composition and interpolation.

Performing composition on quaternions is similar to combining them. The composition of two quaternions is notated as follows:

Equation showing composition of two quaternions

The composition of two quaternions applied to a geometry means "rotate the geometry around axis2 by rotation2, then rotate it around axis1 by rotation1." In this case, Q represents a rotation around a single axis that is the result of applying q2, then q1 to the geometry.

Using quaternion interpolation, an application can calculate a smooth and reasonable path from one axis and orientation to another. Therefore, interpolation between q1 and q2 provides a simple way to animate from one orientation to another.

When you use composition and interpolation together, they provide you with a simple way to manipulate a geometry in a manner that appears complex. For example, imagine that you have a geometry that you want to rotate to a given orientation. You know that you want to rotate it r2 degrees around axis2, then rotate it r1 degrees around axis1, but you don't know the final quaternion. By using composition, you could combine the two rotations on the geometry to get a single quaternion that is the result. Then, you could interpolate from the original to the composed quaternion to achieve a smooth transition from one to the other.

Direct3D Retained Mode includes some functions that help you work with quaternions. For example, the D3DRMQuaternionFromRotation function adds a rotation value to a vector that defines an axis of rotation, and returns the result in a quaternion defined by a D3DRMQUATERNION structure. Additionally, the D3DRMQuaternionMultiply function composes quaternions and the D3DRMQuaternionSlerp performs spherical linear interpolation between two quaternions.

Retained Mode applications can use the following functions to simplify the task of working with vectors and quaternions:

  • D3DRMQuaternionFromRotation
  • D3DRMQuaternionMultiply
  • D3DRMQuaternionSlerp
  • D3DRMVectorAdd
  • D3DRMVectorCrossProduct
  • D3DRMVectorDotProduct
  • D3DRMVectorModulus
  • D3DRMVectorNormalize
  • D3DRMVectorRandom
  • D3DRMVectorReflect
  • D3DRMVectorRotate
  • D3DRMVectorScale
  • D3DRMVectorSubtract

Floating-Point Precision

Direct3D, like the rest of the DirectX architecture, uses a floating-point precision of 53 bits. The precision is set in the floating-point control word registry in the floating-point unit (FPU). If your application needs to change this precision for certain calculations, the application must change the precision back to 53 when the calculations are finished. Otherwise, system components that depend on the default value will stop working.

Z-Buffers and Overlays

The order in the z-buffer determines the order in which overlays clip each other. Overlays are assumed to be on top of all other screen components. Overlays that do not have a specified z-order behave in unpredictable ways when overlaying the same area on the primary surface. Direct3D Retained Mode does not sort overlays if you do not have a z-buffer. Overlays without a specified z-order are assumed to have a z-order of 0, and will appear in the order they are rendered. The possible z-order of overlays ranges from 0, which is just on top of the primary surface, to 4 billion, which is as close to the viewer as possible. An overlay with a z-order of 2 would obscure an overlay with a z-order of 1. No two overlays can have the same z-order.


Architecture

This section gives an overview of the Microsoft® Direct3D® Retained Mode objects and COM architecture. The following topics are discussed:

  • Objects gives a brief description of the Direct3D Retained Mode objects.
  • Objects and Interfaces lists the interfaces supported by each object, as well as information on creating interfaces to both single objects and array objects.
  • Objects and Reference Counting gives tips on reference counting in Direct3D Retained Mode.

Direct3D Retained Mode Objects

All access to Direct3D Retained Mode is through a small set of objects. The following table lists these objects and a brief description of each:

Object | Description
Direct3DRMAnimation2 | Defines how a transformation will be modified—often in reference to a Direct3DRMFrame3 object. You can use it to animate the position, orientation, and scaling of Direct3DRMVisual, of Direct3DRMLight, and of Direct3DRMViewport2 objects. Same as the Direct3DRMAnimation object, but allows access to the keys and frame of an animation.
Direct3DRMAnimationArray | Retrieves the number of animations in the array, and an interface to the requested animation.
Direct3DRMAnimationSet2 | Allows Direct3DRMAnimation2 objects to be grouped together. Same as the Direct3DRMAnimationSet object, but allows access to the constituent animations.
Direct3DRMClippedVisual | Allows clipping visuals to arbitrary planes before rendering.
Direct3DRMDevice3 | Represents the visual display destination for the renderer. Extends the Direct3DRMDevice2 object by enabling you to set and retrieve materials. Direct3DRMDevice2 offers the same functionality as the Direct3DRMDevice object but with enhanced control of transparency.
Direct3DRMFace2 | Represents a single polygon in a mesh.
Direct3DRMFrame3 | Positions objects within a scene and defines the positions and orientations of visual objects. Extends the Direct3DRMFrame object by enabling access to the frame axes, bounding boxes, and materials. Also supports ray picking. Extends the Direct3DRMFrame2 object by adding to the transform, traversal, and fogging capabilities.
Direct3DRMInterpolator | Stores actions and applies the actions to objects with automatic calculation of in-between values.
Direct3DRMLight | Defines one of five types of lights that are used to illuminate the visual objects in a scene.
Direct3DRMMaterial2 | Defines how a surface reflects light. Same as the Direct3DRMMaterial object, but allows finer control over material properties.
Direct3DRMMesh | Consists of a set of polygonal faces. You can use this object to manipulate groups of faces and vertices.
Direct3DRMMeshBuilder3 | Allows you to work with individual vertices and faces in a mesh. Extends Direct3DRMMeshBuilder objects by providing more control over normals and allowing retrieval of a face on a mesh. Extends Direct3DRMMeshBuilder2 objects by using the Immediate Mode DrawPrimitive interface when created with the IDirect3DRM3 interface.
Direct3DRMObject | Used as a base class by all other Direct3D Retained Mode objects. It has characteristics that are common to all objects.
Direct3DRMObject2 | Used as a base class by all other Direct3D Retained Mode objects. It has characteristics that are common to all objects. Enhances Direct3DRMObject by allowing more flexible data association with an object.
Direct3DRMPickedArray | Identifies a visual object that corresponds to a given 2-D point.
Direct3DRMPicked2Array | Identifies a visual object that corresponds to a given ray intersection.
Direct3DRMProgressiveMesh | Consists of a coarse base mesh together with records describing how to incrementally refine the mesh. This allows a generalized level of detail to be set on the mesh, as well as progressive download of the mesh from a remote source.
Direct3DRMShadow2 | Defines a shadow. Same as the Direct3DRMShadow object except that shadow properties can be set and retrieved after creation.
Direct3DRMTexture3 | Consists of a rectangular array of colored pixels. Same as the Direct3DRMTexture object except that resources can be loaded from files other than the currently executing file, textures can be created from images in memory, and you can generate mipmaps. Enhances the Direct3DRMTexture2 object by allowing finer control over texture management.
Direct3DRMUserVisual | Provides functionality not otherwise available in the system. It is defined by an application.
Direct3DRMViewport2 | Defines how the 3-D scene is rendered into a 2-D window. Same as the Direct3DRMViewport object except allows you to specify what should be cleared.
Direct3DRMVisual | Consists of anything that can be rendered in a scene. Visual objects need not be visible; for example, a frame can be added as a visual object.
Direct3DRMWrap | Calculates texture coordinates for a face or mesh.

Many objects can be grouped into arrays, called array objects. Array objects make it simpler to apply operations to the entire group. The Component Object Model (COM) interfaces that allow you to work with array objects contain the GetElement and GetSize methods. These methods retrieve a pointer to an element in the array and the size of the array, respectively. For more information about array interfaces, see the interface reference section.

Objects and Interfaces

Using the IObjectName::QueryInterface method retrieves a valid interface pointer only if the object supports that interface; therefore, you could use the IDirect3DRMDevice3::QueryInterface method to retrieve the IDirect3DRMWinDevice interface, but not to retrieve the IDirect3DRMVisual interface.

Object name | Supported interfaces
Direct3DRMAnimation2 | IDirect3DRMAnimation2
Direct3DRMAnimationSet2 | IDirect3DRMAnimationSet2
Direct3DRMClippedVisual | IDirect3DRMClippedVisual, IDirect3DRMVisual
Direct3DRMDevice3 | IDirect3DRMDevice3, IDirect3DRMWinDevice
Direct3DRMFace2 | IDirect3DRMFace2
Direct3DRMFrame3 | IDirect3DRMFrame3, IDirect3DRMVisual
Direct3DRMInterpolator | IDirect3DRInterpolator
Direct3DRMLight | IDirect3DRMLight
Direct3DRMMaterial2 | IDirect3DRMMaterial2
Direct3DRMMesh | IDirect3DRMMesh, IDirect3DRMVisual
Direct3DRMMeshBuilder3 | IDirect3DRMMeshBuilder3, IDirect3DRMVisual
Direct3DRMProgressiveMesh | IDirect3DRMProgressiveMesh, IDirect3DRMVisual
Direct3DRMShadow2 | IDirect3DRMShadow2, IDirect3DRMVisual
Direct3DRMTexture3 | IDirect3DRMTexture3, IDirect3DRMVisual
Direct3DRMUserVisual | IDirect3DRMUserVisual, IDirect3DRMVisual
Direct3DRMViewport2 | IDirect3DRMViewport2
Direct3DRMWrap | IDirect3DRMWrap

The following example illustrates how to create two interfaces to a single Direct3DRMDevice3 object. The IDirect3DRM3::CreateObject method creates an uninitialized Direct3DRMDevice3 object. The IDirect3DRMDevice3::InitFromClipper method initializes the object. The call to the IDirect3DRMDevice3::QueryInterface method creates a second interface to the Direct3DRMDevice3 object—an IDirect3DRMWinDevice interface that the application will use to handle WM_PAINT and WM_ACTIVATE messages.

d3drmapi->CreateObject(CLSID_CDirect3DRMDevice, NULL,
    IID_IDirect3DRMDevice3,(LPVOID FAR*)&dev1);
dev1->InitFromClipper(lpDDClipper, IID_IDirect3DRMDevice3,
    r.right, r.bottom);
dev1->QueryInterface(IID_IDirect3DRMWinDevice, (LPVOID*) &dev2);

To determine whether two interfaces refer to the same object, use the QueryInterface method of each interface, and compare the values of the pointers they return. If the pointer values are the same, the interfaces refer to the same object.

All Direct3D Retained Mode objects support the IDirect3DRMObject, IDirect3DRMObject2 and IUnknown interfaces in addition to the interfaces in the preceding list. Array objects are not derived from IDirect3DRMObject. Array objects have no class identifiers (CLSIDs) because they are not needed. Applications cannot create array objects in a call to the IDirect3DRM3::CreateObject method; instead, they should use the creation methods listed below for each interface:

Array interface | Creation method
IDirect3DRMAnimationArray IDirect3DRMAnimationSet2::GetAnimations
IDirect3DRMDeviceArray IDirect3DRM3::GetDevices
IDirect3DRMFaceArray IDirect3DRMMeshBuilder3::GetFaces
IDirect3DRMFrameArray | IDirect3DRMPickedArray::GetPick, IDirect3DRMPicked2Array::GetPick, or IDirect3DRMFrame3::GetChildren
IDirect3DRMLightArray IDirect3DRMFrame3::GetLights
IDirect3DRMObjectArray IDirect3DRMInterpolator::GetAttachedObjects
IDirect3DRMPickedArray IDirect3DRMViewport2::Pick
IDirect3DRMPicked2Array IDirect3DRMFrame3::RayPick
IDirect3DRMViewportArray IDirect3DRM3::CreateFrame
IDirect3DRMVisualArray IDirect3DRMFrame3::GetVisuals

Objects and Reference Counting

When an object is created, its reference count is incremented. Each time an application creates a child of an object or a method returns a pointer to an object, the system increments the reference count for that object. The object is not deleted until its reference count reaches zero. When you are finished with an object be sure to call the object's Release method to decrement its reference count. For example, you could call IDirect3DRM3::CreateMeshBuilder to create an IDirect3DRMMeshBuilder3 object and IDirect3DRMMeshBuilder3::GetFaces to retrieve an IDirect3DRMFaceArray object. Before your application terminates you should call the Release method on the IDirect3DRMMeshBuilder3 object and also call the Release method on the IDirect3DRMFaceArray object. If you do not call Release, the objects will not be properly released and your application will leak resources. For other examples of when to release objects, see the Direct3D Retained Mode sample code.

In Direct3D Retained Mode there is internal and external reference counting. If you have created or imported objects, such as textures, and applied them to objects in your scene, such as frames or meshes, you can then release your copy of the created or imported object's interface, and when the scene is finished with the object it will be automatically released by D3DRM for you. For example, if you create a meshbuilder object, its reference count is 1. If you then add it to a frame, its reference count is 2. You can then release your copy of the pointer to the meshbuilder object, and the meshbuilder object's reference count will be 1. Then, when you release the scene containing the frame, the reference count of the meshbuilder object will be decremented (to 0) for you and the object will be released. As another example, if you import a texture, the texture object's reference count is 1. If you apply the texture to a mesh, its reference count is 2. You can then release your copy of the pointer to the texture object, and its reference count is 1. When the mesh goes away, the texture object's reference count will be decremented and it will be released as well.

If you always release your objects after they have been applied in the scene, your application does not need to keep track of the reference count for them, but only for the root of the scene. Retained Mode keeps track of the other reference counts automatically. In this case, your application should be able to simply release the scene, the viewport, and the device when it cleans up before exiting. (When your application releases the viewport, the system automatically takes care of the camera's references.)

The reference count of a child or visual object increases when it is added to a frame. When you use the IDirect3DRMFrame3::AddChild method to move a child from one parent to another, the system handles the reference counting automatically.

After your application loads a visual object into a scene, the scene handles the reference counting for the visual object. The application no longer needs the visual object and can release it.

Creating and applying a wrap does not increase the reference count of any objects because wrapping is really just a convenient method of calculating texture coordinates.


Overviews

This section provides overview articles that discuss various aspects of Microsoft® Direct3D® Retained Mode. The first two topics provide general information concerning the Direct3D Retained Mode interfaces, including a hierarchy chart and an article that details the history and changes between versions of the interfaces.

  • Interface Hierarchy Chart
  • Interface Changes

The following topics focus on a specific aspect of Direct3D Retained Mode. For a description of each interface's methods, see the appropriate entry in the Reference.

  • Eliminating Redundant State Changes
  • Frames
  • Interpolators
  • Lights
  • Output Devices
  • Textures
  • Viewports
  • Wraps

Direct3D Retained Mode 6 has added support for external visuals. External Visuals provide a method to allow custom hierarchy objects in the Direct3D Retained Mode (D3DRM) hierarchy. These are COM objects which support the IDirect3DRMExternalVisual interface (and any others they wish to support). D3DRM treats these objects as first-class visual objects, allowing for custom rendering, picking, bounding box reporting, and other behaviors. This is more powerful than the User Visuals supported in earlier versions of D3DRM, which only allowed for custom rendering using a callback function. External Visuals provides an extension mechanism that allows any type of visual object, such as deformable meshes or inverse kinematic solvers, to be inserted into the D3DRM visual hierarchy.

Although you can access External Visuals from D3DRM, they support DirectX Transform interfaces and can be used from the DirectX Transform DXETool.exe. For this reason, they are documented in DirectX Transform in the DirectX Media SDK. For more information about External Visuals, please see the Reference section of the DirectX Transform documentation in the DirectX Media SDK.


Interface Hierarchy Chart

Direct3D Retained Mode Interface Hierarchy

 IUnknown
 |
 +--IDirect3DRM (replaced)
 |
 +--IDirect3DRM2 (replaced)
 |
 +--IDirect3DRM3
 |
 +--IDirect3DRMArray
 |  |
 |  +--IDirect3DRMAnimationArray
 |  |
 |  +--IDirect3DRMDeviceArray
 |  |
 |  +--IDirect3DRMFaceArray
 |  |
 |  +--IDirect3DRMFrameArray
 |  |
 |  +--IDirect3DRMLightArray
 |  |
 |  +--IDirect3DRMObjectArray
 |  |
 |  +--IDirect3DRMPicked2Array
 |  |
 |  +--IDirect3DRMPickedArray
 |  |
 |  +--IDirect3DRMViewportArray
 |  |
 |  +--IDirect3DRMVisualArray
 |
 +--IDirect3DRMObject
 |  |
 |  +--IDirect3DRMAnimation (replaced)
 |  |
 |  +--IDirect3DRMAnimation2
 |  |
 |  +--IDirect3DRMAnimationSet (replaced)
 |  |
 |  +--IDirect3DRMAnimationSet2
 |  |
 |  +--IDirect3DRMDevice (replaced)
 |  |  |
 |  |  +--IDirect3DRMDevice2 (replaced)
 |  |
 |  +--IDirect3DRMDevice3
 |  |
 |  +--IDirect3DRMFace2
 |  |
 |  +--IDirect3DRMInterpolator
 |  |
 |  +--IDirect3DRMLight
 |  |
 |  +--IDirect3DRMMaterial (replaced)
 |  |
 |  +--IDirect3DRMMaterial2
 |  |
 |  +--IDirect3DRMViewport (replaced)
 |  |
 |  +--IDirect3DRMViewport2
 |  |
 |  +--IDirect3DRMVisual
 |  |  |
 |  |  +--IDirect3DRMFrame (replaced)
 |  |  |  |
 |  |  |  +--IDirect3DRMFrame2 (replaced)
 |  |  |
 |  |  +--IDirect3DRMFrame3
 |  |  |
 |  |  +--IDirect3DRMMesh
 |  |  |
 |  |  +--IDirect3DRMMeshBuilder (replaced)
 |  |  |  |
 |  |  |  +--IDirect3DRMMeshBuilder2 (replaced)
 |  |  |
 |  |  +--IDirect3DRMMeshBuilder3
 |  |  |
 |  |  +--IDirect3DRMProgressiveMesh
 |  |  |
 |  |  +--IDirect3DRMShadow (replaced)
 |  |  |
 |  |  +--IDirect3DRMShadow2
 |  |  |
 |  |  +--IDirect3DRMTexture (replaced)
 |  |  |  |
 |  |  |  +--IDirect3DRMTexture2 (replaced)
 |  |  |
 |  |  +--IDirect3DRMTexture3
 |  |  |
 |  |  +--IDirect3DRMUserVisual
 |  |
 |  +--IDirect3DRMWinDevice
 |  |
 |  +--IDirect3DRMWrap
 |
 +--IDirect3DRMObject2


Interface Changes

This article outlines the changes in Microsoft® Direct3D® Retained Mode interfaces throughout their history. It discusses the naming convention of sequentially numbered interfaces and lists interfaces that replace older interfaces. It also lists methods added by new interfaces and by successive versions of interfaces.

This article contains the following sections.

  • Sequentially Numbered Interfaces and Methods
  • New and Replaced Interfaces
  • Added and Changed Methods

Sequentially Numbered Interfaces and Methods

Component Object Model (COM) systems, such as Direct3D Retained Mode, provide new methods and functionality through the use of new interfaces that are sequentially numbered. For example, the IDirect3DRMFrame3 interface adds methods to those exposed by IDirect3DRMFrame2. IDirect3DRMFrame2 adds methods to the those exposed by IDirect3DRMFrame.

Beginning with DirectX 6.0, new Direct3D Retained Mode interfaces do not inherit from their predecessor interfaces. For example, IDirect3DRMFrame2, which was introduced in DirectX 5.0, inherits directly from IDirect3DRMFrame, but IDirect3DRMFrame3, which was introduced in DirectX 6.0, does not inherit from IDirect3DRMFrame2 or IDirect3DRMFrame. For a diagram showing the relationship between all Direct3D Retained Mode interfaces, see the Interface Hierarchy Chart.

Beginning with DirectX 6.0, new Direct3D Retained Mode interfaces also require the latest version of input parameters, such as pointers to the latest interface objects. The older interfaces remain unchanged, so you will not have to rewrite your existing applications. For example, IDirect3DRMFrame3 provides all of the functionality present in IDirect3DRMFrame2 and IDirect3DRMFrame. IDirect3DRMFrame3::AddChild takes a pointer to an IDirect3DRMFrame3 interface as its parameter while the same method on the older interfaces takes a pointer to the base IDirect3DRMFrame interface as its parameter. For a list of the interfaces introduced in DirectX 6.0, see New and Replaced Interfaces in this article.

The Direct3D Retained Mode library and run time include the earlier, unchanged interfaces for backward compatibility, but this documentation covers only the latest interfaces and methods to decrease redundant material. This article notes the widespread changes. The documentation for the individual interfaces and methods notes more limited changes between versions. Although you could use the older interfaces to create new applications, it is recommended that you use the newer interfaces to take advantage of their increased functionality.

Prior to DirectX 6.0, new Direct3D Retained Mode methods always accepted the base interface object for input parameters. For output parameters, the new methods return the new interface or object. If the parameters for a particular method change, the name of the changed method is numbered sequentially (for example, by appending a "2" to the name), and that method is added to the new interface. For example, IDirect3DRMFrame::AddMoveCallback has two parameters. In order to expand the functionality, a new version of that method that takes an additional parameter is exposed on a new, sequentially numbered interface as IDirect3DRMFrame2::AddMoveCallback2. Beginning with DirectX 6.0, the practice of appending a number to changed method names is no longer necessary because the new interfaces do not inherit from the old interfaces. Therefore, some Direct3D Retained Mode method names that were appended with a "2" in DirectX 5.0 drop the "2" in DirectX 6.0. Specifically, IDirect3DRMFrame3::AddMoveCallback replaces IDirect3DRMFrame2::AddMoveCallback2 and IDirect3DRMMeshBuilder3::GenerateNormals replaces IDirect3DRMMeshBuilder2::GenerateNormals2.

New and Replaced Interfaces

The following lists the new interfaces introduced in version 6.0 of the Microsoft DirectX® Software Development Kit (SDK). It also lists old interfaces when those interfaces have been replaced by newer interfaces. Version 6.0 of the SDK introduces all the new interfaces below.
Old Interface | New Interface
None | IDirect3DRMClippedVisual
None | IDirect3DRMAnimationArray
None | IDirect3DRMObject2
IDirect3DRM IDirect3DRM3
IDirect3DRM2 IDirect3DRM3
IDirect3DRMAnimation | IDirect3DRMAnimation2
IDirect3DRMAnimationSet | IDirect3DRMAnimationSet2
IDirect3DRMDevice | IDirect3DRMDevice3
IDirect3DRMDevice2 | IDirect3DRMDevice3
IDirect3DRMFrame | IDirect3DRMFrame3
IDirect3DRMFrame2 | IDirect3DRMFrame3
IDirect3DRMMaterial | IDirect3DRMMaterial2
IDirect3DRMMeshBuilder | IDirect3DRMMeshBuilder3
IDirect3DRMMeshBuilder2 | IDirect3DRMMeshBuilder3
IDirect3DRMShadow | IDirect3DRMShadow2
IDirect3DRMTexture | IDirect3DRMTexture3
IDirect3DRMTexture2 | IDirect3DRMTexture3
IDirect3DRMViewport | IDirect3DRMViewport2

Added and Changed Methods

The following provides the history of Direct3D Retained Mode by listing the methods and the version in which each method and interface was added or changed. In cases where more than two interface versions exist (such as with IDirect3DRM3, IDirect3DRM2, and IDirect3DRM), all versions except the first are listed to show the incremental functionality between versions. Interfaces that remain unchanged since the inception of Direct3D Retained Mode are not listed. The version of the DirectX SDK in which an interface was introduced is indicated in parentheses beside the interface name.

  • IDirect3DRM2 (DirectX 5.0, superseded in DirectX 6.0 by IDirect3DRM3)
    • CreateProgressiveMesh
  • IDirect3DRM3 (DirectX 6.0)
    • CreateDeviceFromSurface
    • GetOptions
    • RegisterClient
    • SetOptions
    • UnregisterClient
  • IDirect3DRMAnimation2 (DirectX 6.0)
    • AddKey
    • DeleteKeyByID
    • GetFrame
    • GetKeys
    • ModifyKey
  • IDirect3DRMAnimationArray (DirectX 6.0)
    • GetElement
    • GetSize
  • IDirect3DRMAnimationSet2 (DirectX 6.0)
    • GetAnimations
  • IDirect3DRMClippedVisual (DirectX 6.0)
    • AddPlane
    • DeletePlane
    • GetPlane
    • GetPlaneIDs
    • Init
    • SetPlane
  • IDirect3DRMDevice2 (DirectX 5.0, superseded in DirectX 6.0 by IDirect3DRMDevice3)
    • GetDirect3DDevice2
    • GetRenderMode
    • InitFromD3D2
    • InitFromSurface
    • SetRenderMode
  • IDirect3DRMDevice3 (DirectX 6.0)
    • FindPreferredTextureFormat
  • IDirect3DRMFrame2 (DirectX 5.0, superseded in DirectX 6.0 by IDirect3DRMFrame3)
    • AddMoveCallback2 (Replaced by IDirect3DRMFrame3::AddMoveCallback)
    • GetAxes
    • GetBox
    • GetBoxEnable
    • GetHierarchyBox
    • GetInheritAxes
    • GetMaterial
    • RayPick
    • Save
    • SetAxes
    • SetBox
    • SetBoxEnable
    • SetInheritAxes
    • SetMaterial
    • SetQuaternion
  • IDirect3DRMFrame3 (DirectX 6.0)
    • GetMaterialOverride
    • GetSceneFogMethod
    • GetTransform (Extends IDirect3DRMFrame::GetTransform)
    • GetTraversalOptions
    • InverseTransformVectors
    • SetMaterialOverride
    • SetSceneFogMethod
    • SetTraversalOptions
    • TransformVectors
  • IDirect3DRMMaterial2 (DirectX 6.0)
    • GetAmbient
    • SetAmbient
  • IDirect3DRMMeshBuilder2 (DirectX 5.0, superseded in DirectX 6.0 by IDirect3DRMMeshBuilder3)
    • GenerateNormals2 (Replaced by IDirect3DRMMeshBuilder3::GenerateNormals)
    • GetFace
  • IDirect3DRMMeshBuilder3 (DirectX 6.0)
    • AddFacesIndexed
    • AddTriangles
    • CreateSubMesh
    • DeleteFace
    • DeleteNormals
    • DeleteSubMesh
    • DeleteVertices
    • Empty
    • Enable
    • GetEnable
    • GetNormal
    • GetGeometry (Replaces IDirect3DRMMeshBuilder::GetVertices)
    • GetNormalCount
    • GetNormals
    • GetParentMesh
    • GetSubMeshes
    • GetVertex
    • GetVertices (See GetGeometry for IDirect3DRMMeshBuilder::GetVertices functionality)
    • Optimize
    • SetNormals
    • SetVertices
  • IDirect3DRMObject2 (DirectX 6.0)

    Note that this interface does not replace IDirect3DRMObject.

    • AddDestroyCallback
    • Clone
    • DeleteDestroyCallback
    • GetAge
    • GetClientData
    • GetDirect3DRM
    • GetName
    • SetClientData
    • SetName
  • IDirect3DRMShadow2 (DirectX 6.0)
    • GetLight
    • GetOptions
    • GetPlane
    • GetVisual
    • SetLight
    • SetOptions
    • SetPlane
    • SetVisual
  • IDirect3DRMTexture2 (DirectX 5.0, superseded in DirectX 6.0 by IDirect3DRMTexture3)
    • GenerateMIPMap
    • InitFromImage
    • InitFromResource2
  • IDirect3DRMTexture3 (DirectX 6.0)
    • Changed (Extends IDirect3DRMTexture::Changed)
    • GetCacheOptions
    • GetSurface
    • SetCacheOptions
    • SetDownsampleCallback
    • SetValidationCallback
  • IDirect3DRMViewport2 (DirectX 6.0)
    • Clear (Extends IDirect3DRMViewport::Clear)


Eliminating Redundant State Changes

In earlier versions of Microsoft® Direct3D® Retained Mode, Retained Mode could not assume render and light states would remain the same from one call to the next. This led to many redundant state changes in a typical application because Retained Mode set the state to a value equal to its current value. The IDirect3DRMDevice3 interface introduces several methods that can be used to eliminate these redundant changes for a modest performance boost: GetStateChangeOptions, LightStateChange, RenderStateChange, and SetStateChangeOptions. To use these methods, follow these steps:

  1. Turn on the redundant state change check by using the following two methods on the IDirect3DRMDevice3 interface. This indicates that you will not change any render or light state without notice.
    Dev3->SetStateChangeOptions(D3DRMSTATECHANGE_RENDER, 0,
                            D3DRMSTATECHANGE_NONVOLATILE);
Dev3->SetStateChangeOptions(D3DRMSTATECHANGE_LIGHT, 0, D3DRMSTATECHANGE_NONVOLATILE);
  2. When you change a render or light state (either through an execute buffer or a draw primitive), you must inform Direct3D Retained Mode of the change so that the state cache is updated. You can do this in two ways. You can have Retained Mode change the state for you (and prevent redundant changes) or you can inform Retained Mode that you have changed the state to a new value. Both use the LightStateChange and RenderStateChange methods.

For example, the following code shows you how to change the texture handle and update the state cache.

Dev3->RenderStateChange(D3DRENDERSTATE_TEXTUREHANDLE, hTex, 0UL);

If you have changed the state and just want Retained Mode to update its state cache, use the UPDATEONLY flag, as shown in the following:

Dev3->RenderStateChange(D3DRENDERSTATE_TEXTUREHANDLE, hTex,
                        D3DRMSTATECHANGE_UPDATEONLY);

If you are going to be changing a state value many times and do not want Retained Mode to keep track of current values, you can turn off redundant state checking for the specified state with the following code. However, this is not recommended because you will lose performance benefits.

Dev3->SetStateChangeOptions(D3DRMSTATECHANGE_RENDER, D3DRENDERSTATE_TEXTUREHANDLE,
                            D3DRMSTATECHANGE_VOLATILE);


Frames

The term frame is derived from an object's physical frame of reference. The frame's role in Retained Mode is similar to a window's role in a windowing system. Objects can be placed in a scene by stating their spatial relationship to a relevant reference frame; they are not simply placed in world space. A frame is used to position objects in a scene, and visuals take their positions and orientation from frames.

A scene in Retained Mode is defined by a frame that has no parent frame; that is, a frame at the top of the hierarchy of frames. This frame is also sometimes called a root frame or master frame. The scene defines the frame of reference for all of the other objects. You can create a scene by calling the IDirect3DRM3::CreateFrame method and specifying NULL for the first parameter.

The IDirect3DRMFrame3 interface is an extension of the IDirect3DRMFrame2 interface. IDirect3DRMFrame2 has methods that enable using materials, bounding boxes, and axes with frames. IDirect3DRMFrame2 also supports ray picking.

By using the IDirect3DRMFrame3::SetAxes method and using the right-handed projection types in the D3DRMPROJECTIONTYPE structure with the IDirect3DRMViewport2::SetProjection method, you can enable right-handed projection.

For related information, see IDirect3DRMFrame3.

This section describes frames and how your application can use them.

  • Hierarchies
  • Transformations
  • Motion
  • Callback Functions

Hierarchies

The frames in a scene are arranged in a tree structure. Frames can have a parent frame and child frames. Remember, a frame that has no parent frame defines a scene and is called a root frame.

Child frames have positions and orientations relative to their parent frames. If the parent frame moves, the child frames also move.

An application can set the position and orientation of a frame relative to any other frame in the scene, including the root frame if it needs to set an absolute position. You can also remove frames from one parent frame and add them to another at any time by using the IDirect3DRMFrame3::AddChild method. To remove a child frame entirely, use the IDirect3DRMFrame3::DeleteChild method. To retrieve a frame's child and parent frames, use the IDirect3DRMFrame3::GetChildren and IDirect3DRMFrame3::GetParent methods.

You can add frames as visuals to other frames, allowing you to use a given hierarchy many times throughout a scene. The new hierarchies are referred to as instances. Be careful to avoid instancing a parent frame into its children because that will degrade performance. Retained Mode does no run-time checking for cyclic hierarchies. You cannot create a cyclic hierarchy by using the methods of the IDirect3DRMFrame3 interface; instead, this is possible only when you add a frame as a visual.

Transformations

You can think of the position and orientation of a frame relative to its parent frame as a linear transformation. This transformation takes vectors defined relative to the child frame and changes them to equivalent vectors defined relative to the parent.

Transformations can be represented by 4×4 matrices, and coordinates can be represented by four-element row vectors, [x, y, z,1].

If vchild is a coordinate in the child frame, then vparent, the equivalent coordinate in the parent frame, is defined as:

Definition of the parent frame

Tchild is the child frame's transformation matrix.

The transformations of all the parent frames above a child frame up to the root frame are concatenated with the transformation of that child to produce a world transformation. This world transformation is then applied to the visuals on the child frame before rendering. Coordinates relative to the child frame are sometimes called model coordinates. After the world transformation is applied, coordinates are called world coordinates.

The transformation of a frame can be modified directly by using the IDirect3DRMFrame3::AddTransform, IDirect3DRMFrame3::AddScale, IDirect3DRMFrame3::AddRotation, and IDirect3DRMFrame3::AddTranslation methods. Each of these methods specifies a member of the D3DRMCOMBINETYPE enumerated type, which specifies how the matrix supplied by the application should be combined with the current frame's matrix.

The IDirect3DRMFrame3::GetRotation and IDirect3DRMFrame3::GetTransform methods allow you to retrieve a frame's rotation axis and transformation matrix. To change the rotation of a frame, use the IDirect3DRMFrame3::SetRotation method.

Use the IDirect3DRMFrame3::Transform and IDirect3DRMFrame3::InverseTransform methods to change between world coordinates and model coordinates.

You can find a more general discussion of transformations in the Transformations section devoted to viewports. For an overview of the mathematics of transformations, see 3-D Transformations.

Motion

Every frame has an intrinsic rotation and velocity. Frames that are neither rotating nor translating simply have zero values for these attributes. These attributes are used before each scene is rendered to move objects in the scene, and they can also be used to create simple animations.

Callback Functions

Frames support a callback function that you can use to support more complex animations. The application registers a function that the frame calls before the motion attributes are applied. When there are multiple frames in a hierarchy, each with associated callback functions, the parent frames are called before the child frames. For a given hierarchy, rendering does not take place until all of the required callback functions have been invoked.

To add this callback function, use the IDirect3DRMFrame3::AddMoveCallback method; to remove it, use the IDirect3DRMFrame3::DeleteMoveCallback method.

You can use these callback functions to provide new positions and orientations from a preprogrammed animation sequence or to implement dynamic motion in which the activities of visuals depend upon the positions of other objects in the scene.


Interpolators

Interpolators provide a way of storing actions and applying them to objects with automatic calculation of in-between values. For example, you can set a scene's background color to red at time zero and green at time ten, and the interpolator will automatically tint successive scenes to blend from red to green. With an interpolator, you can blend colors, move objects smoothly between positions, morph meshes, and perform many other transformations.

In the Direct3D Retained Mode implementation, interpolators are a generalization of the IDirect3DRMAnimation2 interface that increases the kinds of object parameters you can animate. While the IDirect3DRMAnimation2 interface allows animation of an object's position, size and orientation, the IDirect3DRMInterpolator interface further enables animation of colors, meshes, textures, and materials.

This article contains the following sections.

  • Interpolator Keys
  • Interpolator Types
  • Interpolator Example
  • Methods Supported by the Interpolator
  • Interpolator Index Span
  • Interpolation Options

Interpolator Keys

The actions stored by the interpolator are called keys. A key is a stored procedure call and has an index associated with it. The interpolator automatically calculates between the key values.

Keys are stored in the interpolator by calling one of the supported interface methods that can be interpolated. The method and the parameter values passed to it make up the key. Methods Supported by the Interpolator supplies a list of supported methods.

Every key stored inside an interpolator has an index value. When the key is recorded, it is stamped with the current interpolator index value. The key's index value never changes once this value is set.

Interpolator Types

Objects can be attached to interpolators of an associated type; for example, a Mesh can be attached to a MeshInterpolator. The interpolator types are:

  • FrameInterpolator
  • LightInterpolator
  • MaterialInterpolator
  • MeshInterpolator
  • TextureInterpolator
  • ViewportInterpolator

Other interpolators can also be attached to an interpolator. When you change the index of an interpolator, it sets the indices of any attached interpolators to the same value.

Note that for MeshInterpolators, you add a SetVertices key to a MeshInterpolator object by calling SetVertices on the MeshInterpolator object's IDirect3DRMMesh interface. The group index used with SetVertices must correspond to a valid group index in the Mesh object or objects that the interpolator is applied to.

Interpolator Example

As an example, if you want to interpolate a frame's position, you will need a FrameInterpolator object with two interfaces, IDirect3DRMInterpolator and IDirect3DRMFrame3.

pd3drm->CreateObject(CLSID_CDirect3DRMFrameInterpolator, 0, IID_IDirect3DRMInterpolator, &pInterp);
pInterp->QueryInterface(IID_IDirect3DRMFrame3, &pFrameInterp);

To add a position key to the interpolator, set the interpolator's internal index by calling IDirect3DRMInterpolator::SetIndex, and record the position by calling SetPosition on the IDirect3DRMFrame3 interface. This method is applied to the interpolator rather than to a real frame. The function call and its parameters are stored in the interpolator as a new key with the current index.

pInterp->SetIndex(keytime);
pFrameInterp->SetPosition(NULL, keypos.x, keypos.y, keypos.z);

You can add more keys by repeating the sequence of setting the index with IDirect3DRMInterpolator::SetIndex followed by one or more object methods. To play actions back through a real frame, attach the frame to the interpolator.

pInterp->AttachObject(pRealFrame);

Now call IDirect3DRMInterpolator::Interpolate to set the position of the pRealFrame parameter using the interpolated position.

pInterp->Interpolate(time, NULL, D3DRMINTERPOLATIONSPLINE | D3DRMINTERPOLATION_OPEN);

The interpolator will call the attached frame's SetPosition method, passing it a position it has calculated by interpolating (in this case, using a B-spline) between the nearest SetPosition keys.

Alternatively, you can use the immediate form of Interpolate and pass the object as the second parameter. This overrides any attached objects.

pInterp->Interpolate(time, pRealFrame, D3DRMINTERPOLATIONSPLINE | D3DRMINTERPOLATION_OPEN);

You can use the same interpolator to store other keys such as orientation, scale, velocity, and color keys. Each property exists on a parallel timeline, and calling Interpolate assigns the interpolated value for each property to the attached frames.

It is possible to interpolate more than one method. For example, you can store SetGroupColor and SetVertices keys in the same interpolator. It is not possible to interpolate between keys of different methods, so they are stored in parallel execution threads called Key Chains. Also, if you specify two keys from different groups, such as SetGroupColor(0, black) and SetGroupColor(2, white), it does not make sense for the interpolator to generate an in-between action of SetGroupColor(1, gray) because the keys apply to different groups. In this case, the keys are also stored in separate chains.

Methods Supported by the Interpolator

Viewport

SetFront(value)
SetBack(value)
SetField(value)
SetPlane(left, right, bottom, top)

Frame

SetPosition(reference*, x, y, z)
SetRotation(reference*, x, y, z, theta)
SetVelocity(reference*, x, y, z, withRotation*)
SetOrientation(reference*, dx, dy, dz, ux, uy, uz)
SetColor(color)
SetColorRGB(red, green, blue)
SetSceneBackground(color)
SetSceneBackgroundRGB(red, green, blue)
SetSceneFogColor(color)
SetSceneFogParams(start, end, density)
SetQuaternion(reference*, quat)

Mesh

Translate(x, y, z)
SetVertices(group*, index*, count*, vertices)
SetGroupColor(group*, color)
SetGroupColorRGB(group*, red, green, blue)

Light

SetColor(color)
SetColorRGB(red, green, blue)
SetRange(value)
SetUmbra(value)
SetPenumbra(value)
SetConstantAttenuation(value)
SetLinearAttenuation(value)
SetQuadraticAttenuation(value)

Texture

SetDecalSize(width, height)
SetDecalOrigin(x, y)
SetDecalTransparentColor(color)

Material

SetPower(value)
SetSpecular(red, green, blue)
SetEmissive(red, green, blue)

*—Indicates keys with different values for this parameter are inserted in separate chains

An attempt to set a key of any unsupported method will result in a non-fatal D3DRMERR_BADOBJECT error.

Interpolator Index Span

The interpolator covers a span of index values. This index span is dictated by the following rules:

  • The start of the span is the minimum of all key index values and the current index.
  • The end of the span is the maximum of all key index values and the current index.

Interpolation Options

The d3drmInterpFlags parameter of IDirect3DRMInterpolator::Interpolate allows you to perform interpolation by specifying one or more of the following options:

  • D3DRMINTERPOLATION_CLOSED
  • D3DRMINTERPOLATION_LINEAR
  • D3DRMINTERPOLATION_NEAREST
  • D3DRMINTERPOLATION_OPEN
  • D3DRMINTERPOLATION_SLERPNORMALS
  • D3DRMINTERPOLATION_SPLINE
  • D3DRMINTERPOLATION_VERTEXCOLOR

If the interpolator is executed CLOSED, the interpolation is cyclic. The keys effectively repeat infinitely with a period equal to the index span. For compatibility with animations, any key with an index equal to the end of the span is ignored.

If the interpolation is OPEN, the first and last keys of each key chain fix the interpolated values outside of the index span.

The NEAREST, LINEAR, and SPLINE options specify how in-betweening is performed on each key chain. In-betweening is the calculation of intermediate values that smoothly connect key data points. If NEAREST is specified the nearest key value is used. LINEAR performs linear interpolation between the 2 nearest keys. SPLINE uses a B-spline blending function on the 4 nearest keys.

The following two options affect only the interpolation of IDirect3DRMMesh::SetVertices:

  • VERTEXCOLOR specifies that vertex colors should be interpolated.
  • SLERPNORMALS specifies that vertex normals should be spherically interpolated (not currently implemented).


Lights

Lighting effects are employed to increase the visual fidelity of a scene. The system colors each object based on the object's orientation to the light sources in the scene. The contribution of each light source is combined to determine the color of the object during rendering. All lights have color and intensity that can be varied independently.

An application can attach lights to a frame to represent a light source in a scene. When a light is attached to a frame, it illuminates visual objects in the scene. The frame provides both position and orientation for the light. In other words, the light originates from the origin of the frame it is attached to. An application can move and redirect a light source simply by moving and reorienting the frame the light source is attached to.

Each viewport owns one or more lights. No light can be owned by more than one viewport.

Retained Mode currently provides five types of light sources: ambient, directional, parallel point, point, and spotlight.

For a reference to the methods of the IDirect3DRMLight interface, see IDirect3DRMLight.

This section describes lighting effects available in Direct3D and how your application can use them.

  • Ambient
  • Directional
  • Parallel Point
  • Point
  • Spotlight

Ambient

An ambient light source illuminates everything in the scene, regardless of the orientation, position, and surface characteristics of the objects in the scene. Because ambient light illuminates a scene with equal strength everywhere, the position and orientation of the frame it is attached to are inconsequential. Multiple ambient light sources are combined within a scene.

Directional

A directional light source has orientation but no position. The light is attached to a frame but appears to illuminate all objects with equal intensity, as if it were at an infinite distance from the objects. The directional source is commonly used to simulate distant light sources, such as the sun. It is the best choice of light to use for maximum rendering speed.

Parallel Point

A parallel point light source illuminates objects with parallel light, but the orientation of the light is taken from the position of the parallel point light source. That is, like a directional light source, a parallel point light source has orientation, but it also has position. For example, two meshes on either side of a parallel point light source are lit on the side that faces the position of the source. The parallel point light source offers similar rendering-speed performance to the directional light source.

Point

A point light source radiates light equally in all directions from its origin. It requires the calculation of a new lighting vector for every facet or normal it illuminates, and for this reason it is computationally more expensive than a parallel point light source. It does, however, produce a more faithful lighting effect and should be chosen where visual fidelity is the deciding concern.

Spotlight

A spotlight emits a cone of light. Only objects within the cone are illuminated. The cone produces light of two degrees of intensity, with a central brightly lit section (the umbra) that acts as a point source, and a surrounding dimly lit section (the penumbra) that merges with the surrounding deep shadow. The angles of these two sections can be individually specified by using the IDirect3DRMLight::GetPenumbra, IDirect3DRMLight::GetUmbra, IDirect3DRMLight::SetPenumbra, and IDirect3DRMLight::SetUmbra methods.

Illustration of penumbra angle, umbra angle, and umbra cone


Output Devices

All forms of rendered output must be associated with an output device. The device object represents the visual display destination for the renderer.

The renderer's behavior depends on the type of output device that is specified. You can define multiple viewports on a device, allowing different aspects of the scene to be viewed simultaneously. You can also specify any number of devices, allowing multiple destination devices for the same scene.

Retained Mode supports devices that render directly to the screen, to windows, or into application memory.

Applications use the IDirect3DRMDevice3, IDirect3DRMDevice2, and IDirect3DRMDevice interfaces to interact with the output device. For related information, see IDirect3DRMDevice3.

This section describes the options available to display Direct3D images to output devices.

  • Quality
  • Color Models
  • Window Management

Quality

The output device allows the scene and its component parts to be rendered with various degrees of realism. The device rendering quality is the maximum quality at which rendering can take place on the rendering surface of that device. Mesh, progressive mesh, and mesh builder objects can also have a specified rendering quality.

A device's or object's quality has three components: shade mode (flat or Gouraud; Phong is not yet implemented and will default to Gouraud shading), lighting type (on or off), and fill mode (point, wireframe or solid).

You can set the quality of a device with IDirect3DRMDevice3::SetQuality and IDirect3DRMDevice3::SetQuality methods. By default, the device quality is D3DRMRENDER_FLAT (flat shading, lights on, and solid fill).

You can set the quality of a Direct3DRMProgressiveMesh, Direct3DRMMeshBuilder3, or Direct3DRMMeshBuilder3 object with their respective SetQuality methods: IDirect3DRMProgressiveMesh::SetQuality, IDirect3DRMMeshBuilder3::SetQuality, and IDirect3DRMMeshBuilder3::SetQuality. By default, the quality of these objects is D3DRMRENDER_GOURAUD (Gouraud shading, lights on, and solid fill).

Tip: Gourad shading gets better performance on progressive mesh objects that change level of detail, often or quickly.

Direct3D Retained Mode renders an object at the lowest quality setting based on the device and object's current setting for each individual component. For example, if the object's current quality setting is D3DRMRENDER_GOURAUD, and the device is D3DRMRENDER_FLAT then the object will be rendered with flat shading, solid fill, and lights on.

If the object's current quality setting is D3DRMSHADE_GOURAUD|D3DRMLIGHT_OFF|D3DRMFILL_WIREFRAME and the device's quality setting is D3DRMSHADE_FLAT|D3DRMLIGHT_ON|D3DRMFILL_POINT, then the object will be rendered with flat shading, lights off, and point fill mode.

These rules apply to Direct3DRMMeshBuilder3 object s, Direct3DRMMeshBuilder3 objects, and Direct3DRMProgressiveMesh objects. However, Direct3DRMMesh objects do not follow these rules. Mesh objects ignore the device's quality settings and use the group quality setting (which defaults to D3DRMRENDER_GOURAUD).

Color Models

Retained Mode supports two color models: an RGB model and a monochromatic (or ramp) model. To retrieve the color model, an application can use the IDirect3DRMDevice3::GetColorModel method.

The RGB model treats color as a combination of red, green, and blue light, and it supports multiple light sources that can be colored. There is no limit to the number of colors in the scene. You can use this model with 8-, 16-, 24-, and 32-bit displays. If the display depth is less than 24 bits, the limited color resolution can produce banding artifacts. You can avoid these artifacts by using optional dithering.

The monochromatic model also supports multiple light sources, but their color content is ignored. Each source is set to a gray intensity. RGB colors at a vertex are interpreted as brightness levels. Brightness levels between vertices with different brightness are interpolated (in Gouraud shading) across the intervening face. The number of differently colored objects in the scene is limited; after all the system's free palette entries are used up, the system's internal palette manager finds colors that already exist in the palette and that most closely match the intended colors. Like the RGB model, you can use this model with 8-, 16-, 24-, and 32-bit displays. (The monochromatic model supports only 8-bit textures, however.) The advantage of the monochromatic model over the RGB model is better performance.

It is not possible to change the color model of a Direct3D device. Your application should use the IDirect3D::EnumDevices or IDirect3D::FindDevice method to identify a driver that supports the required color model, then specify this driver in one of the device-creation methods.

Palettes are supported for textures, off-screen surfaces, and overlay surfaces, none of which is required to have the same palette as the primary surface. If a device supports a 4-bit indexed palette (16 colors) and you have 8-bit indexed art (256 colors), Retained Mode will render the art as 4-bit by taking the first 16 entries from your palette and remapping to those. Therefore, you should put your 16 preferred colors at the front of the palette if possible.

Window Management

For correct operation, applications must inform Direct3D when the WM_MOVE, WM_PAINT, and WM_ACTIVATE messages are received from the operating system by using the IDirect3DRMWinDevice::HandlePaint and IDirect3DRMWinDevice::HandleActivate methods.

For related information, see IDirect3DRMWinDevice.


Textures

A texture is a rectangular array of colored pixels. (The rectangle does not necessarily have to be square, although the system deals most efficiently with square textures.) You can use textures for texture-mapping faces, in which case their dimensions must be powers of two.

Your application can use the IDirect3DRM3::CreateTexture method to create a texture from a D3DRMIMAGE structure, or the IDirect3DRM3::CreateTextureFromSurface method to create a texture from a DirectDraw surface. The IDirect3DRM3::LoadTexture method allows your application to load a texture from a file; the texture should be in Microsoft® Windows® bitmap (.bmp) or Portable Pixmap (.ppm) format. To avoid unnecessary delays when creating textures, hold onto textures you want to use again, instead of creating them each time they're needed. For optimal performance, use a texture surface format that is supported by the device you are using. This will avoid a costly format conversion when the texture is created and any time it changes. If your textures consist of 16 colors or less, consider using the 4-bit palettized surface format to reduce video memory usage on hardware devices.

The texture coordinates of each face define the region in the texture that is mapped onto that particular face. Your application can use a wrap to calculate texture coordinates. For more information, see Wraps.

The IDirect3DRMTexture3 interface is an extension of the IDirect3DRMTexture2 interface, which is an extension of the IDirect3DRMTexture interface.

Textures are loaded from BMP and DIB (device-independent bitmap) files right-side up in IDirect3DRMTexture3::InitFromFile, IDirect3DRMTexture3::InitFromResource2, and in the IDirect3DRMTexture2 versions of these methods, unlike IDirect3DRMTexture::InitFromFile and IDirect3DRMTexture::InitFromResource2 where they are loaded inverted.

For a reference to the methods of these interfaces, see IDirect3DRMTexture3.

Note that you should not use DDSCAPS2_TEXTUREMANAGE flag in Retained Mode. Instead, create textures in system memory, and Retained Mode will manage them.

This section describes the types of textures supported by Direct3D and how your application can use them.

  • Decals
  • Texture Colors
  • Mipmaps
  • Texture Filtering
  • Texture Transparency
  • Texture Format Selection Rules

Decals

Textures can also be rendered directly, as visuals. Textures used this way are sometimes known as decals, a term adopted by Retained Mode. A decal is rendered into a viewport-aligned rectangle. The rectangle can optionally be scaled by the depth component of the decal's position. The size of the decal is taken from a rectangle defined relative to the containing frame by using the IDirect3DRMTexture3::SetDecalSize method. (An application can retrieve the size of the decal by using the IDirect3DRMTexture3::GetDecalSize method.) The decal is then transformed and perspective projection is applied.

Decals have origins that your application can set and retrieve by using the IDirect3DRMTexture3::SetDecalOrigin and IDirect3DRMTexture3::GetDecalOrigin methods. The origin is an offset from the top-left corner of the decal. The default origin is [0, 0]. The decal's origin is aligned with its frame's position when rendering.

Texture Colors

You can set and retrieve the number of colors that are used to render a texture by using the IDirect3DRMTexture3::SetColors and IDirect3DRMTexture3::GetColors methods.

If your application uses the RGB color model, you can use 8-bit, 24-bit, and 32-bit textures. If you use the monochromatic (or ramp) color model, however, you can use only 8-bit textures.

Several shades of each color are used when lighting a scene. An application can set and retrieve the number of shades used for each color by calling the IDirect3DRMTexture3::SetShades and IDirect3DRMTexture3::GetShades methods.

A Direct3DRMTexture object uses a D3DRMIMAGE structure to define the bitmap that the texture will be rendered from. If the application provides the D3DRMIMAGE structure, the texture can easily be animated or altered during rendering.

Mipmaps

A mipmap is a sequence of textures, each of which is a progressively lower resolution, prefiltered representation of the same image. Mipmapping is a computationally low-cost way of improving the quality of rendered textures. Each prefiltered image, or level, in the mipmap is a power of two smaller than the previous level. You can specify mipmaps when filtering textures by calling the IDirect3DRMDevice3::SetTextureQuality method.

For more information about mipmaps, see Mipmaps.

Texture Filtering

After a texture has been mapped to a surface, the texture elements (texels) of the texture rarely correspond to individual pixels in the final image. A pixel in the final image can correspond to a large collection of texels or to a small piece of a single texel. You can use texture filtering to specify how to interpolate texel values to pixels.

You can use the IDirect3DRMDevice3::SetTextureQuality method and the D3DRMTEXTUREQUALITY enumerated type to specify the texture filtering mode for your application.

Texture Transparency

You can use the IDirect3DRMTexture3::SetDecalTransparency method to produce transparent textures. Another method for achieving transparency is to use DirectDraw's support for color keys. Color keys are colors or ranges of colors that can be part of either the source or destination of a blit or overlay operation. You can specify that these colors should always be overwritten or never be overwritten.

For more information about DirectDraw's support for color keys, see Color Keying.

Texture Format Selection Rules

When you use a device-independent source image to create a device-dependent texture surface for rendering, the rules are (in order of precedence):

1. Preserve RGB/palettized nature

2. Preserve alpha channel

3. Preserve bit depth or palette size

4. Preserve RBGA masks

5. Prefer 8-bit palettized or 16-bit RGB

For more information about texture pixel formats, see Texture Map Formats.

For related information, see IDirect3DRMTexture3.


Viewports

The viewport defines how the 3-D scene is rendered into a 2-D window. The viewport defines a rectangular area on a device that objects will be rendered into.

For a reference to the methods of this interface, see IDirect3DRMViewport2.

This section describes the viewport, its components, and techniques for their use.

  • Camera
  • Viewing Frustum
  • Transformations
  • Picking

Camera

The viewport uses a Direct3DRMFrame object as a camera. The camera frame defines which scene is rendered and the viewing position and direction. The viewport renders only what is visible along the positive z-axis of the camera frame, with the up direction being in the direction of the positive y-axis.

An application can call the IDirect3DRMViewport2::SetCamera method to set a camera for a given viewport. This method sets a viewport's position, direction, and orientation to that of the given camera frame. To retrieve the current camera settings, call the IDirect3DRMViewport2::GetCamera method.

Viewing Frustum

The viewing frustum is a 3-D volume in a scene positioned relative to the viewport's camera. For perspective viewing, the camera is positioned at the tip of an imaginary pyramid. This pyramid is intersected by two clipping planes, the front clipping plane and the back clipping plane. The volume in the pyramid between the front and back clipping planes is the viewing frustum. Only objects in the viewing frustum are visible.

Diagram showing the front and back clipping plane and the viewing frustum

The z-axis of the camera runs from the tip of the pyramid to the center of the back clipping plane. Your application can set and retrieve the positions of the front and back clipping planes by using the IDirect3DRMViewport2::SetFront, IDirect3DRMViewport2::SetBack, IDirect3DRMViewport2::GetFront, and IDirect3DRMViewport2::GetBack methods.

The dimensions of the viewport on the front clipping plane determine the apparent focal length of the camera's lens. (You can also think of this as a way to set the magnification of objects in the frustum.) To set and retrieve proportional dimensions for the viewport on the front clipping plane, use the IDirect3DRMViewport2::SetField and IDirect3DRMViewport2::GetField methods. To set and retrieve arbitrary dimensions for the viewport on the front clipping plane, use the IDirect3DRMViewport2::SetPlane and IDirect3DRMViewport2::GetPlane methods.

You can use the following equation to determine the relationship between the height (or width) of the front clipping plane and the viewing angle:

Equation showing relationship between the front clipping plane and the viewing angle

In this formula, the viewing angle is A, the front clipping plane is a distance D from the camera, and the height or width of the front clipping plane is 2h. If the device is not square, and thus the clipping planes are not square, the viewing angle is calculated using half the height or half the width of the front clipping plane, whichever is larger. The scale factors are set to the major axis of the device so you don't get distorted objects. If this is not what you want, you need to set uniform scaling.

Illustration of the dimensions used in the previous equation

The viewing frustum is a pyramid only for perspective viewing. For orthographic viewing, the viewing frustum is cuboid. These viewing types (or projection types) are defined by the D3DRMPROJECTIONTYPE enumerated type and used by the IDirect3DRMViewport2::GetProjection and IDirect3DRMViewport2::SetProjection methods.

Units of Measurement

DirectSound is the only module of DirectX where there is a default unit of measurement, the meter. This can be changed by the use of a distance factor. However, in both Direct3D Immediate Mode and Retained Mode there is no particular default unit. The developer must decide which units are most appropriate for the application, and build this into the program. For most applications measurements in meters, or feet, are appropriate, but for some they will not be. For example, if suns and moons are in the picture, distances could be measured in miles, or when modeling insects, or even atomic particles, the measurements might be very much less than a foot or a meter. DirectX simply works on the basis of "units" and has no concept of any real distance.

The absence of built in measurements can become a problem when importing DirectX files from a variety of sources. Not only is the measurement not included in the file, the "units" can be arbitrary, so need not be any standard measurement. This could make proper scaling of, say, two aircraft from different sources, difficult. If one model is in meters, and the other in feet, all that is needed is to scale one of the models when it is loaded. The IDirect3DRMMeshBuilder3::Scale function can be used in cases where the units of measurement of a model are known. Trial and error, or inspired guesswork, may be needed if a developer has little information as to the units used by the modeller.

If a developer wishes to use DirectSound, then setting the default measurement for the whole application to meters makes sense. For more information see the Units of Measure and Distance Factors section in the DirectSound documentation.

Transformations

To render objects with 3-D coordinates in a 2-D window, the object must be transformed into the camera's frame. A projection matrix is then used to give a four-element homogeneous coordinate [x y z w], which is used to derive a three-element coordinate [x/w y/w z/w], where [x/w y/w] is the coordinate to be used in the window and z/w is the depth, ranging from 0 at the front clipping plane to 1 at the back clipping plane. The projection matrix is a combination of a perspective transformation followed by a scaling and translation to scale the objects into the window.

The following values are the elements of the projection matrix. In these formulas, h is the half-height of the viewing frustum, F is the distance from the camera, and D is the position in z-coordinates of the front clipping plane:

After projection, the next step is clipping and the conversion of x and y to screen-pixel coordinates within a viewport. Use the D3DVIEWPORT data members for this. The viewport is a rectangular window on the rendering surface.

typedef struct _D3DVIEWPORT {
    DWORD    dwSize;
    DWORD    dwX;
    DWORD    dwY;
    DWORD    dwWidth;
    DWORD    dwHeight;
    D3DVALUE dvScaleX;
    D3DVALUE dvScaleY;
    D3DVALUE dvMaxX;
    D3DVALUE dvMaxY;
    D3DVALUE dvMinZ;
    D3DVALUE dvMaxZ;
} D3DVIEWPORT, *LPD3DVIEWPORT;

The dwX and dwY fields specify the offset in screen pixels to the top left of the viewport on the surface.

The dwWidth and dwHeight fields are the width and height of the viewport in screen pixels.

The dvScaleX and dvScaleY fields are the scaling factors that are applied to the x and y values to yield screen coordinates. You would usually want to map the entire normalized perspective view volume onto the viewport using the following formulas:

  dvScaleX = dwWidth / 2
  dvScaleY = dwHeight / 2

X coordinates, for example, in the range of -1 to 1, will be scaled into the range of -dwWidth / 2 to dwWidth / 2. An offset of dwWidth / 2 is then added. This scaling occurs after clipping.

If the window is not square and you would like to preserve a correct aspect ratio, use the larger of the two window dimensions for both scaling values. You will also need to clip some of the view volume.

The dvMaxX, dvMaxY, dvinZ, and dvMaxZ fields specify the clipping planes: x = dvMaxX, x = —dvMaxX, y = dvMaxy, y = —dvMaxY, z = dvMinZ, z = dvMaxZ. To display all of the view volume, for example, you would set dvMaxX = dvMaxY = dvMaxZ = 1 and dvMinZ = 0. As noted above, if you want to preserve the correct aspect ratio on a nonsquare window, you will need to clip some of the view volume. To do so, use the following equations. These equations also work with square viewports, so use them all the time.

dvMaxX = dwWidth / (2 * dvScaleX)
dvMaxY = dwHeight / (2 * dvScaleY)

An application uses the viewport transformation to ensure that the distance by which the object is moved in world coordinates is scaled by the object's distance from the camera to account for perspective. Note that the result from IDirect3DRMViewport2::Transform is a four-element homogeneous vector. This avoids the problems associated with coordinates being scaled by an infinite amount near the camera's position.

For information about transformations for frames, see Transformations. For an overview of the mathematics of transformations, see 3-D Transformations.

Picking

Picking is the process of searching for visuals in the scene given a 2-D coordinate in the viewport's window. An application can use the IDirect3DRMViewport2::Pick method to retrieve either the closest object in the scene or a depth-sorted list of objects.


Wraps

You can use a wrap to calculate texture coordinates for a face or mesh. To create a wrap, the application must specify a type, a reference frame, an origin, a direction vector, and an up vector. The application must also specify a pair of scaling factors and an origin for the texture coordinates.

Your application calls the IDirect3DRM3::CreateWrap function to create an IDirect3DRMWrap interface. This interface has two unique methods: IDirect3DRMWrap::Apply, which applies a wrap to the vertices of the object, and IDirect3DRMWrap::ApplyRelative, which transforms the vertices of a wrap as it is applied.

In the examples, the direction vector (the v vector) lies along the z-axis, and the up vector (the u vector) lies along the y-axis, with the origin at [0 0 0].

For a reference to the methods of the IDirect3DRMWrap interface, see IDirect3DRMWrap.

This section describes the wrapping flags and the four wrapping types.

  • Wrapping Flags
  • Flat
  • Cylindrical
  • Spherical
  • Chrome

Wrapping Flags

The D3DRMMAPPING type includes the D3DRMMAP_WRAPU and D3DRMMAP_WRAPV flags. These flags determine how the rasterizer interprets texture coordinates. The rasterizer always interpolates the shortest distance between texture coordinates—that is, a line. The path taken by this line, and the valid values for the u- and v-coordinates, varies with the use of the wrapping flags. If either or both flags is set, the line can wrap around the texture edge in the u or v direction, as if the texture had a cylindrical or toroidal topology.

  • In flat wrapping mode, in which neither of the wrapping flags is set, the plane specified by the u- and v-coordinates is an infinite tiling of the texture. In this case, values greater than 1.0 are valid for u and v. The shortest line between (0.1, 0.1) and (0.9, 0.9) passes through (0.5, 0.5).
  • If either D3DRMMAP_WRAPU or D3DRMMAP_WRAPV is set, the texture is a cylinder with an infinite length and a circumference of 1.0. Texture coordinates greater than 1.0 are valid only in the dimension that is not wrapped. The shortest distance between texture coordinates varies with the wrapping flag; if D3DRMMAP_WRAPU is set, the shortest line between (0.1, 0.1) and (0.9, 0.9) passes through (0, 0.5).
  • If both D3DRMMAP_WRAPU and D3DRMMAP_WRAPV are set, the texture is a torus. Because the system is closed, texture coordinates greater that 1.0 are invalid. The shortest line between (0.1, 0.1) and (0.9, 0.9) passes through (0, 0).

Although texture coordinates that are outside the valid range may be truncated to valid values, this behavior is not defined.

Typically, applications set a wrap flag for cylindrical wraps when the intersection of the texture edges does not match the edges of the face; applications do not set a wrap flag when more than half of a texture is applied to a single face.

Flat

The flat wrap conforms to the faces of an object as if the texture were a piece of rubber that was stretched over the object.

The [u v] coordinates are derived from a vector [x y z] by using the following equations:

Equations for deriving u-v coordinates from a vector in a flat wrap

In these formulas, s is the window-scaling factor and o is the window origin. The application should choose a pair of scaling factors and offsets that map the ranges of x and y to the range from 0 to 1 for u and v.

Cylindrical

The cylindrical wrap treats the texture as if it were a piece of paper that is wrapped around a cylinder so that the left edge is joined to the right edge. The object is then placed in the middle of the cylinder and the texture is deformed inward onto the surface of the object.

For a cylindrical texture map, the effects of the various vectors are shown in the following illustration.

Diagram showing the effects of vectors on a cylindrical wrap

The direction vector specifies the axis of the cylinder, and the up vector specifies the point on the outside of the cylinder where u equals 0. To calculate the texture [u v] coordinates for a vector [x y z], the system uses the following equations:

Equations for deriving u-v coordinates from a vector in a cylindrical wrap

Typically, u would be left unscaled and v would be scaled and translated so that the range of z maps to the range from 0 to 1 for v.

Spherical

For a spherical wrap, the u-coordinate is derived from the angle that the vector [x y 0] makes with the x-axis (as in the cylindrical map) and the v-coordinate from the angle that the vector [x y z] makes with the z-axis. Note that this mapping causes distortion of the texture at the z-axis.

Diagram showing the effects of vectors on a spherical wrap

This translates to the following equations:

Equations for deriving u-v coordinates from a vector in a spherical wrap

The scaling factors and texture origin will often not be needed here as the unscaled range of u and v is already 0 through 1.

Chrome

A chrome wrap allocates texture coordinates so that the texture appears to be reflected onto the objects. The chrome wrap takes the reference frame position and uses the vertex normals in the mesh to calculate reflected vectors. The texture u- and v-coordinates are then calculated from the intersection of these reflected vectors with an imaginary sphere that surrounds the mesh. This gives the effect of the mesh reflecting whatever is wrapped on the sphere.


Tutorial

To create a Microsoft® Windows®-based, Direct3D® Retained Mode application, you set up the features of two different environments: the devices, viewports, and color capabilities of the Windows environment, and the models, textures, lights, and positions of the virtual environment. This section is a tutorial that contains all the code for a simple Retained Mode application. The following illustration is a single frame from the running animation:

Single frame from running animation

The tutorial is divided into the following sections:

  • Making the Helworld Sample
  • Definitions and Global Variables
  • Windows Setup and Initialization
  • Enumerating Device Drivers
  • Setting up the 3-D Environment
  • The Rendering Loop
  • Creating the Scene
  • Cleaning Up

Making the Helworld Sample

This tutorial includes all the code for a working Direct3D Retained Mode application. You can copy the code from this tutorial into a single .c file and then compile and run it if the following conditions are met:

  • You have the Direct3D header files (D3d.h, D3drm.h, and so on) in your include path.
  • You link with the Winmm.lib, D3drm.lib, and Ddraw.lib static libraries.
  • Your compiler can find the Sphere3.x file in the media directory of the Microsoft® DirectX® Software Development Kit.
  • You supply a bitmap called Tutor.bmp.

    Note that this bitmap must have pixel dimensions that are a power of 2; for example, a 16×16 pixel bitmap, a 128×1024 pixel bitmap, a 512×256 pixel bitmap, and so on.

Most of the code responsible for 3-D effects in this sample has been broken out into discrete functions so that you can modify parts of the system incrementally in your own experiments. You should look at the samples in the DirectX SDK for implementations of more complicated features of Direct3D.

The following topics describe some of the concerns that apply to the overall development of a simple Direct3D Retained Mode application.

  • Limitations of the Sample
  • DirectDraw Windowed Mode

Limitations of the Sample

This tutorial contains the Helworld.c example code, which creates a sphere, applies a texture to it, and rotates it in a window. This is the only C source file required to build this application. The only other files you need are Sphere3.x, a mesh file that ships in the Media directory of the DirectX SDK; and Tutor.bmp, a bitmap you supply. (Note that you must have the Direct3D header files in your include path and link to the Winmm.lib, D3drm.lib, and Ddraw.lib static libraries.)

This tutorial is a simplified version of the Globe sample that is part of the DirectX SDK. The Globe sample, like all the Direct3D Retained Mode samples in the SDK, requires the inclusion of a file named Rmmain.cpp and a number of header files. In Helworld.c, the relevant parts of Rmmain.cpp have been converted to C from C++ and integrated into the source code.

The code shown in this tutorial should not be mistaken for production code. The only possible user interactions with the program are starting it, stopping it, and minimizing the window while it is running. Most of the error checking has been removed for clarity. The purpose of this example is analogous to the purpose of the beginning program that prints "Hello, world!" on the screen: to produce output with as little confusion as possible.

DirectDraw Windowed Mode

Nearly all Direct3D applications will use DirectDraw® to display their graphics on the screen. These applications will either use DirectDraw's exclusive (full-screen) mode or nonexclusive (windowed) mode. The code in this documentation uses windowed mode. Although the full-screen mode offers some benefits in performance and convenience, it is much easier to debug code written in windowed mode. Most developers will write their code in windowed mode and port it to full-screen mode late in the development cycle, when most of the bugs have been worked out.

Definitions and Global Variables

Below are the first lines of the Helworld.c example. You won't need any other C source files to build this application, but be sure to give your file the .c extension rather than .cpp. The C compiler assumes a file with the .cpp extension contains C++ code and handles the lpVtbl pointer and the additional this parameter for you. See Accessing COM Objects by Using C in the DirectX SDK documentation for more details. Because this tutorial is written in C it explicitly includes the lpVtbl pointer and adds the initial this parameter. The compiler generates many compile errors on the same file if it has the .cpp extension.

Notice that INITGUID must be defined prior to all other includes and defines. This is a crucial point that is sometimes missed by developers who are new to DirectX.

/////////////////////////////////////////////////////////////////////
//
//  Copyright (C) 1996 Microsoft Corporation. All Rights Reserved.
//
//  File: Helworld.c
//
//  Simplified Direct3D Retained Mode example, based on
//  the "Globe" SDK sample.
//
/////////////////////////////////////////////////////////////////////

#define INITGUID           // Must precede other defines and includes

#include <windows.h>
#include <malloc.h>        // Required by memset call
#include <d3drmwin.h>

#define MAX_DRIVERS 5           // Maximum D3D drivers expected

// Global variables

LPDIRECT3DRM lpD3DRM;           // Direct3DRM object
LPDIRECTDRAWCLIPPER lpDDClipper;// DirectDrawClipper object

struct _myglobs {
    LPDIRECT3DRMDEVICE dev;     // Direct3DRM device
    LPDIRECT3DRMVIEWPORT view;  // Direct3DRM viewport through which
                                // the scene is viewed
    LPDIRECT3DRMFRAME scene;    // Master frame in which others are
                                // placed
    LPDIRECT3DRMFRAME camera;   // Frame describing the user's POV

    GUID DriverGUID[MAX_DRIVERS];     // GUIDs of available D3D drivers
    char DriverName[MAX_DRIVERS][50]; // Names of available D3D drivers
    int  NumDrivers;                  // Number of available D3D drivers
    int  CurrDriver;                  // Number of D3D driver currently
                                      // being used

    BOOL bQuit;                 // Program is about to terminate
    BOOL bInitialized;          // All D3DRM objects are initialized
    BOOL bMinimized;            // Window is minimized

    int BPP;                    // Bit depth of the current display mode

} myglobs;

// Function prototypes.

static BOOL InitApp(HINSTANCE, int);
long FAR PASCAL WindowProc(HWND, UINT, WPARAM, LPARAM);
static BOOL EnumDrivers(HWND win);
static HRESULT WINAPI enumDeviceFunc(LPGUID lpGuid,
    LPSTR lpDeviceDescription, LPSTR lpDeviceName,
    LPD3DDEVICEDESC lpHWDesc, LPD3DDEVICEDESC lpHELDesc,
    LPVOID lpContext);
static DWORD BPPToDDBD(int bpp);
static BOOL CreateDevAndView(LPDIRECTDRAWCLIPPER lpDDClipper,
    int driver, int width, int height);
static BOOL SetRenderState(void);
static BOOL RenderLoop(void);
static BOOL MyScene(LPDIRECT3DRMDEVICE dev, LPDIRECT3DRMVIEWPORT view,
    LPDIRECT3DRMFRAME scene, LPDIRECT3DRMFRAME camera);
void MakeMyFrames(LPDIRECT3DRMFRAME lpScene, LPDIRECT3DRMFRAME lpCamera,
    LPDIRECT3DRMFRAME * lplpLightFrame1,
    LPDIRECT3DRMFRAME * lplpWorld_frame);
void MakeMyLights(LPDIRECT3DRMFRAME lpScene, LPDIRECT3DRMFRAME lpCamera,
    LPDIRECT3DRMFRAME lpLightFrame1,
    LPDIRECT3DRMLIGHT * lplpLight1, LPDIRECT3DRMLIGHT * lplpLight2);
void SetMyPositions(LPDIRECT3DRMFRAME lpScene,
    LPDIRECT3DRMFRAME lpCamera, LPDIRECT3DRMFRAME lpLightFrame1,
    LPDIRECT3DRMFRAME lpWorld_frame);
void MakeMyMesh(LPDIRECT3DRMMESHBUILDER  * lplpSphere3_builder);
void MakeMyWrap(LPDIRECT3DRMMESHBUILDER  sphere3_builder,
                LPDIRECT3DRMWRAP * lpWrap);
void AddMyTexture(LPDIRECT3DRMMESHBUILDER  lpSphere3_builder,
                  LPDIRECT3DRMTEXTURE * lplpTex);
static void CleanUp(void);

Windows Setup and Initialization

This section describes the standard setup and initialization functions in a Windows program, as implemented in the Helworld.c sample code.

  • The WinMain Function
  • The InitApp Function
  • The Main Window Procedure

The WinMain Function

The WinMain function in Helworld.c has only a few lines of code that are unique to an application that uses DirectDraw and Direct3D Retained Mode. The InitApp and CleanUp functions are standard parts of a Windows program, although in the case of Helworld, they perform some unique tasks. The most important call in WinMain, from the perspective of Direct3D, is the call to the RenderLoop function. RenderLoop is responsible for drawing each new frame of the animation. For more information about the RenderLoop function, see The Rendering Loop.

/////////////////////////////////////////////////////////////////////
//
// WinMain
// Initializes the application and enters a message loop.
// The message loop renders the scene until a quit message is received.
//
/////////////////////////////////////////////////////////////////////

int PASCAL
WinMain (HINSTANCE this_inst, HINSTANCE prev_inst, LPSTR cmdline,
    int cmdshow)
{
    MSG     msg;
    HACCEL  accel = NULL;
    int     failcount = 0;  // Number of times RenderLoop has failed

    prev_inst;
    cmdline;

    // Create the window and initialize all objects needed to begin
    // rendering.

    if (!InitApp(this_inst, cmdshow))
        return 1;

    while (!myglobs.bQuit) {

        // Monitor the message queue until there are no pressing
        // messages.

        while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
            if (!TranslateAccelerator(msg.hwnd, accel, &msg)) {
                TranslateMessage(&msg);
                DispatchMessage(&msg);
            }
        }

        // If the app is not minimized, not about to quit, and D3DRM has
        // been initialized, begin rendering.

        if (!myglobs.bMinimized && !myglobs.bQuit &&
             myglobs.bInitialized) {

            // Attempt to render a frame. If rendering fails more than
            // twice, abort execution.

            if (!RenderLoop())
                ++failcount;
            if (failcount > 2) {
                CleanUp();
                break;
            }
        }
    }
    return msg.wParam;
}

The InitApp Function

The initialization function (InitApp) in Helworld.c creates the window class and main application window, just as in most Windows-based applications. After this, however, InitApp does some work that is unique to applications using DirectDraw and Direct3D.

Next, InitApp retrieves the current display's bits per pixel. This information is used to help set the rendering quality for the application. For more information, see Setting the Render State.

InitApp then uses the locally defined EnumDrivers function to determine which Direct3D drivers are available and to choose one. For more information about enumerating drivers, see Enumerating Device Drivers.

Next, the code uses the Direct3DRMCreate function to create an IDirect3DRM interface. It uses this interface in the calls to IDirect3DRM::CreateFrame and IDirect3DRMFrame::SetPosition that create the scene and camera frames, and position the camera in the scene.

A DirectDrawClipper object makes it simple to manage the clipping planes that control which parts are visible of a 3-D scene. Helworld.c uses the DirectDrawCreateClipper function to create an IDirectDrawClipper interface, and then uses the IDirectDrawClipper::SetHWnd method to set the window handle that obtains the clipping information.

Now the InitApp function uses the locally defined CreateDevAndView function to create the Direct3D device and viewport. For more information about this function, see Creating the Device and Viewport.

When the entire supporting structure of a Direct3D application has been put into place, the details of the 3-D scene can be constructed. The MyScene function does this. For more information about MyScene, see Creating the Device and Viewport.

Finally, just as in a standard initialization function, InitApp displays and updates the window.

/////////////////////////////////////////////////////////////////////
//
// InitApp
// Creates window and initializes all objects necessary to begin
// rendering.
//
/////////////////////////////////////////////////////////////////////

static BOOL
InitApp(HINSTANCE this_inst, int cmdshow)
{
    HWND win;
    HDC hdc;
    WNDCLASS wc;
    RECT rc;

    // Set up and register the window class.

    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc = WindowProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = sizeof(DWORD);
    wc.hInstance = this_inst;
    wc.hIcon = LoadIcon(this_inst, "AppIcon");
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
    wc.lpszMenuName = NULL;
    wc.lpszClassName = "D3DRM Example";
    if (!RegisterClass(&wc))
        return FALSE;

    // Initialize the global variables.

    memset(&myglobs, 0, sizeof(myglobs));

    // Create the window.

    win =
        CreateWindow
        (   "D3DRM Example",            // Class
            "Hello World (Direct3DRM)", // Title bar
            WS_VISIBLE | WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU |
                 WS_MINIMIZEBOX | WS_MAXIMIZEBOX,
            CW_USEDEFAULT,              // Init. x pos
            CW_USEDEFAULT,              // Init. y pos
            300,                        // Init. x size
            300,                        // Init. y size
            NULL,                       // Parent window
            NULL,                       // Menu handle
            this_inst,                  // Program handle
            NULL                        // Create parms
        );
    if (!win)
        return FALSE;

    // Record the current display bits-per-pixel.

    hdc = GetDC(win);
    myglobs.BPP = GetDeviceCaps(hdc, BITSPIXEL);
    ReleaseDC(win, hdc);

    // Enumerate the D3D drivers and select one.

    if (!EnumDrivers(win))
        return FALSE;

    // Create the D3DRM object and the D3DRM window object.

    lpD3DRM = NULL;
    Direct3DRMCreate(&lpD3DRM);

    // Create the master scene frame and camera frame.

    lpD3DRM->lpVtbl->CreateFrame(lpD3DRM, NULL, &myglobs.scene);
    lpD3DRM->lpVtbl->CreateFrame(lpD3DRM, myglobs.scene,
        &myglobs.camera);
    myglobs.camera->lpVtbl->SetPosition(myglobs.camera, myglobs.scene,
        D3DVAL(0.0), D3DVAL(0.0), D3DVAL(0.0));

    // Create a DirectDrawClipper object and associate the
    // window with it.

    DirectDrawCreateClipper(0, &lpDDClipper, NULL);
    lpDDClipper->lpVtbl->SetHWnd(lpDDClipper, 0, win);

    // Create the D3DRM device by using the selected D3D driver.

    GetClientRect(win, &rc);
    if (!CreateDevAndView(lpDDClipper, myglobs.CurrDriver, rc.right,
            rc.bottom)) {
        return FALSE;
    }

    // Create the scene to be rendered.

    if (!MyScene(myglobs.dev, myglobs.view, myglobs.scene,
            myglobs.camera))
        return FALSE;

    myglobs.bInitialized = TRUE;  // Initialization completed

    // Display the window.

    ShowWindow(win, cmdshow);
    UpdateWindow(win);

    return TRUE;
}

The Main Window Procedure

The Helworld.c sample has a very simple main window procedure—after all, the application allows practically no user interaction.

When the window procedure receives a WM_DESTROY message, it uses the CleanUp function, just as you would expect.

When it receives a WM_ACTIVATE message, it retrieves an IDirect3DRMWinDevice interface and uses the IDirect3DRMWinDevice::HandleActivate method to ensure that the colors are correct in the active rendering window. Similarly, the function reacts to a WM_PAINT message by using the IDirect3DRMWinDevice::HandlePaint method.

/////////////////////////////////////////////////////////////////////
//
// WindowProc
// Main window message handler.
//
/////////////////////////////////////////////////////////////////////

LONG FAR PASCAL WindowProc(HWND win, UINT msg,
    WPARAM wparam, LPARAM lparam)
{
    RECT r;
    PAINTSTRUCT ps;
    LPDIRECT3DRMWINDEVICE lpD3DRMWinDev;

    switch (msg)    {

    case WM_DESTROY:
        CleanUp();
        break;

    case WM_ACTIVATE:
        {

        // Create a Windows-specific Direct3D Retained Mode window device to handle this
        // message.

        if (!myglobs.dev)
            break;
        myglobs.dev->lpVtbl->QueryInterface(myglobs.dev,
            &IID_IDirect3DRMWinDevice, (void **) &lpD3DRMWinDev);
        lpD3DRMWinDev->lpVtbl->HandleActivate(lpD3DRMWinDev,
            (WORD) wparam);
        lpD3DRMWinDev->lpVtbl->Release(lpD3DRMWinDev);
        }
        break;

    case WM_PAINT:
        if (!myglobs.bInitialized || !myglobs.dev)
            return DefWindowProc(win, msg, wparam, lparam);

        // Create a Windows-specific Direct3D Retained Mode window device to handle this
        // message.

        if (GetUpdateRect(win, &r, FALSE)) {
            BeginPaint(win, &ps);
            myglobs.dev->lpVtbl->QueryInterface(myglobs.dev,
                &IID_IDirect3DRMWinDevice, (void **) &lpD3DRMWinDev);
            lpD3DRMWinDev->lpVtbl->HandlePaint(lpD3DRMWinDev,
                ps.hdc);
            lpD3DRMWinDev->lpVtbl->Release(lpD3DRMWinDev);
            EndPaint(win, &ps);
        }
        break;
    default:
        return DefWindowProc(win, msg, wparam, lparam);
    }
    return 0L;
}

Enumerating Device Drivers

Applications that use Direct3D always enumerate the available drivers and choose the one that best matches their needs. The following sections each describe one of the functions that perform this task:

  • The EnumDrivers Function
  • The enumDeviceFunc Callback Function
  • The BPPToDDBD Helper Function

The EnumDrivers Function

The EnumDrivers function is used by the InitApp function just before InitApp creates the application's scene and camera.

The IDirect3D Component Object Model (COM) interface is really an interface to a DirectDraw object, so the first thing this enumeration function does is use the DirectDrawCreate function to create a DirectDrawObject. Then EnumDrivers uses the QueryInterface method to create an IDirect3D interface. Notice that the C implementation of QueryInterface requires that you pass the address of the interface identifier as the second parameter, not simply the constant itself (like in the C++ implementation).

The enumeration is handled by the IDirect3D::EnumDevices method, which depends on the locally defined enumDeviceFunc callback function. For more information about this callback function, see The enumDeviceFunc Callback Function.

Notice that IDirect3D::EnumDevices is a Direct3D method, not a Direct3DRM method; there is no enumeration method in the Retained Mode API. This is a good example of the natural use of both Retained Mode and Immediate Mode methods in a single application.

/////////////////////////////////////////////////////////////////////
//
// EnumDrivers
// Enumerate the available D3D drivers and choose one.
//
/////////////////////////////////////////////////////////////////////

static BOOL
EnumDrivers(HWND win)
{
    LPDIRECTDRAW lpDD;
    LPDIRECT3D lpD3D;
    HRESULT rval;

    // Create a DirectDraw object and query for the Direct3D interface
    // to use to enumerate the drivers.

    DirectDrawCreate(NULL, &lpDD, NULL);
    rval = lpDD->lpVtbl->QueryInterface(lpDD, &IID_IDirect3D,
        (void**) &lpD3D);
    if (rval != DD_OK) {
        lpDD->lpVtbl->Release(lpDD);
        return FALSE;
    }

    // Enumerate the drivers, setting CurrDriver to -1 to initialize the
    // driver selection code in enumDeviceFunc.

    myglobs.CurrDriver = -1;
    lpD3D->lpVtbl->EnumDevices(lpD3D, enumDeviceFunc,
        &myglobs.CurrDriver);

    // Ensure at least one valid driver was found.

    if (myglobs.NumDrivers == 0) {
        return FALSE;
    }
    lpD3D->lpVtbl->Release(lpD3D);
    lpDD->lpVtbl->Release(lpDD);

    return TRUE;
}

The enumDeviceFunc Callback Function

The enumDeviceFunc callback function is of the D3DENUMDEVICESCALLBACK type, as defined in the D3dcaps.h header file. The system uses this function with identifiers and names for each Direct3D driver in the system, as well as the hardware and emulated capabilities of the driver.

The callback function uses the dcmColorModel member of the D3DDEVICEDESC structure to determine whether to examine the hardware or emulated driver description. If the member has been filled by the hardware description, the function consults the hardware description.

Next, the callback function determines whether the driver being enumerated can render in the current bit depth. If not, the function returns D3DENUMRET_OK to skip the rest of the process for this driver and continue the enumeration with the next driver. The callback function uses the locally defined BPPToDDBD function to compare the reported bit depth against the bits-per-pixel retrieved by the call to the GetDeviceCaps function in the InitApp function. (BPPToDDBD stands for bits-per-pixel to DirectDraw bit-depth.) For the code for this function, see The BPPToDDBD Helper Function.

If the driver being enumerated passes a few simple tests, other parts of D3DDEVICEDESC are examined. The callback function will choose hardware over software emulation, and monochromatic lighting capabilities over RGB lighting capabilities.

/////////////////////////////////////////////////////////////////////
//
// enumDeviceFunc
// Callback function that records each usable D3D driver's name
// and GUID. Chooses a driver and sets *lpContext to this driver.
//
/////////////////////////////////////////////////////////////////////

static HRESULT
WINAPI enumDeviceFunc(LPGUID lpGuid, LPSTR lpDeviceDescription,
    LPSTR lpDeviceName, LPD3DDEVICEDESC lpHWDesc,
    LPD3DDEVICEDESC lpHELDesc, LPVOID lpContext)
{
    static BOOL hardware = FALSE; // Current start driver is hardware
    static BOOL mono = FALSE;     // Current start driver is mono light
    LPD3DDEVICEDESC lpDesc;
    int *lpStartDriver = (int *)lpContext;

    // Decide which device description should be consulted.

    lpDesc = lpHWDesc->dcmColorModel ? lpHWDesc : lpHELDesc;

    // If this driver cannot render in the current display bit-depth,
    // skip it and continue with the enumeration.

    if (!(lpDesc->dwDeviceRenderBitDepth & BPPToDDBD(myglobs.BPP)))
        return D3DENUMRET_OK;

    // Record this driver's name and GUID.

    memcpy(&myglobs.DriverGUID[myglobs.NumDrivers], lpGuid,
        sizeof(GUID));
    lstrcpy(&myglobs.DriverName[myglobs.NumDrivers][0], lpDeviceName);

    // Choose hardware over software, RGB lights over mono lights.

    if (*lpStartDriver == -1) {

        // This is the first valid driver.

        *lpStartDriver = myglobs.NumDrivers;
        hardware = lpDesc == lpHWDesc ? TRUE : FALSE;
        mono = lpDesc->dcmColorModel & D3DCOLOR_MONO ? TRUE : FALSE;
    } else if (lpDesc == lpHWDesc && !hardware) {

        // This driver is hardware and the start driver is not.

        *lpStartDriver = myglobs.NumDrivers;
        hardware = lpDesc == lpHWDesc ? TRUE : FALSE;
        mono = lpDesc->dcmColorModel & D3DCOLOR_MONO ? TRUE : FALSE;
    } else if ((lpDesc == lpHWDesc && hardware ) ||
               (lpDesc == lpHELDesc && !hardware)) {
        if (lpDesc->dcmColorModel == D3DCOLOR_MONO && !mono) {

            // This driver and the start driver are the same type, and
            // this driver is mono whereas the start driver is not.

            *lpStartDriver = myglobs.NumDrivers;
            hardware = lpDesc == lpHWDesc ? TRUE : FALSE;
            mono = lpDesc->dcmColorModel & D3DCOLOR_MONO ? TRUE : FALSE;
        }
    }
    myglobs.NumDrivers++;
    if (myglobs.NumDrivers == MAX_DRIVERS)
        return (D3DENUMRET_CANCEL);
    return (D3DENUMRET_OK);
}

BPPToDDBD Helper Function

The enumDeviceFunc callback function uses the BPPToDDBD helper function to convert the stored bits-per-pixel the current device supports to a form that can be compared against the bit depth for the driver being enumerated. For more information about enumDeviceFunc, see The enumDeviceFunc Callback Function.

/////////////////////////////////////////////////////////////////////
//
// BPPToDDBD
// Converts bits-per-pixel to a DirectDraw bit-depth flag.
//
/////////////////////////////////////////////////////////////////////

static DWORD
BPPToDDBD(int bpp)
{
    switch(bpp) {
        case 1:
            return DDBD_1;
        case 2:
            return DDBD_2;
        case 4:
            return DDBD_4;
        case 8:
            return DDBD_8;
        case 16:
            return DDBD_16;
        case 24:
            return DDBD_24;
        case 32:
            return DDBD_32;
        default:
            return 0;
    }
}

Setting up the 3-D Environment

This section describes the code in Helworld.c that establishes the 3-D environment. The following sections describe the two functions that perform this task:

  • Creating the Device and Viewport
  • Setting the Render State

These functions do not populate the 3-D environment with objects, frames, and lights. That is done by the MyScene function and the functions it uses. For information about filling up the 3-D environment, see Creating the Scene.

Creating the Device and Viewport

The Direct3D device and viewport are created as part of the application's initialization. After creating a DirectDrawClipper object, the InitApp function uses CreateDevAndView, passing as parameters the DirectDrawClipper object, the driver that was chosen, and the dimensions of the client rectangle.

The CreateDevAndView function uses the IDirect3DRM::CreateDeviceFromClipper method to create a Direct3DRM device, using the driver that was selected during the enumeration process. It uses this IDirect3DRMDevice interface to retrieve the device's width and height, by using IDirect3DRMDevice::GetWidth and IDirect3DRMDevice::GetHeight methods. After it has retrieved this information, it uses the IDirect3DRM::CreateViewport method to retrieve the IDirect3DRMViewport interface.

When CreateDevAndView has used the IDirect3DRMViewport::SetBack method to set the back clipping plane of the viewport, it uses the locally defined SetRenderState function. SetRenderState is described in the next section, Setting the Render State.

/////////////////////////////////////////////////////////////////////
//
// CreateDevAndView
// Create the D3DRM device and viewport with the given D3D driver and
// with the specified size.
//
/////////////////////////////////////////////////////////////////////

static BOOL
CreateDevAndView(LPDIRECTDRAWCLIPPER lpDDClipper, int driver,
    int width, int height)
{
    HRESULT rval;

    // Create the D3DRM device from this window by using the specified
    // D3D driver.

    lpD3DRM->lpVtbl->CreateDeviceFromClipper(lpD3DRM, lpDDClipper,
        &myglobs.DriverGUID[driver], width, height, &myglobs.dev);

    // Create the D3DRM viewport by using the camera frame. Set the
    // background depth to a large number. The width and height
    // might have been slightly adjusted, so get them from the device.

    width = myglobs.dev->lpVtbl->GetWidth(myglobs.dev);
    height = myglobs.dev->lpVtbl->GetHeight(myglobs.dev);
    rval = lpD3DRM->lpVtbl->CreateViewport(lpD3DRM, myglobs.dev,
        myglobs.camera, 0, 0, width, height, &myglobs.view);
    if (rval != D3DRM_OK) {
        myglobs.dev->lpVtbl->Release(myglobs.dev);
        return FALSE;
    }
    rval = myglobs.view->lpVtbl->SetBack(myglobs.view, D3DVAL(5000.0));
    if (rval != D3DRM_OK) {
        myglobs.dev->lpVtbl->Release(myglobs.dev);
        myglobs.view->lpVtbl->Release(myglobs.view);
        return FALSE;
    }

    // Set the render quality, fill mode, lighting state,
    // and color shade info.

    if (!SetRenderState())
        return FALSE;
    return TRUE;
}

Setting the Render State

Direct3D is a state machine; applications set up the state of the lighting, rendering, and transformation modules and then pass data through them. This architecture is integral to Immediate Mode, but it is partially hidden by the Retained Mode API. The SetRenderState function is a simple way to set the rendering state for a Retained Mode application.

First, SetRenderState uses the IDirect3DRMDevice::SetQuality method, specifying that the lights are on, that the fill mode is solid, and that Gouraud shading should be used. At this point, applications that need to change the dithering mode or texture quality can use the IDirect3DRMDevice::SetDither or IDirect3DRMDevice::SetTextureQuality methods.

/////////////////////////////////////////////////////////////////////
//
// SetRenderState
// Set the render quality and shade information.
//
/////////////////////////////////////////////////////////////////////

BOOL
SetRenderState(void)
{
    HRESULT rval;

    // Set the render quality (light toggle, fill mode, shade mode).

    rval = myglobs.dev->lpVtbl->SetQuality(myglobs.dev,
        D3DRMLIGHT_ON | D3DRMFILL_SOLID | D3DRMSHADE_GOURAUD);
    if (rval != D3DRM_OK) {
        return FALSE;
    }

    // If you want to change the dithering mode, use SetDither here.

    // If you want a texture quality other than D3DRMTEXTURE_NEAREST
    // (the default value), use SetTextureQuality here.

   return TRUE;
}

Rendering Loop

The WinMain function uses the RenderLoop function to draw each new frame of the animation. The RenderLoop function performs a few simple tasks:

  • Uses the IDirect3DRMFrame::Move method to apply the rotations and velocities for all frames in the hierarchy.
  • Uses the IDirect3DRMViewport::Clear method to clear the current viewport, setting it to the current background color.
  • Uses the IDirect3DRMViewport::Render method to render the current scene into the current viewport.
  • Uses the IDirect3DRMDevice::Update method to copy the rendered image to the display.
/////////////////////////////////////////////////////////////////////
//
// RenderLoop
// Clear the viewport, render the next frame, and update the window.
//
/////////////////////////////////////////////////////////////////////

static BOOL
RenderLoop()
{
    HRESULT rval;

    // Tick the scene.

    rval = myglobs.scene->lpVtbl->Move(myglobs.scene, D3DVAL(1.0));
    if (rval != D3DRM_OK) {
        return FALSE;
    }

    // Clear the viewport.

    rval = myglobs.view->lpVtbl->Clear(myglobs.view);
    if (rval != D3DRM_OK) {
        return FALSE;
    }

    // Render the scene to the viewport.

    rval = myglobs.view->lpVtbl->Render(myglobs.view, myglobs.scene);
    if (rval != D3DRM_OK) {
        return FALSE;
    }

    // Update the window.

    rval = myglobs.dev->lpVtbl->Update(myglobs.dev);
    if (rval != D3DRM_OK) {
        return FALSE;
    }
    return TRUE;
}

Creating the Scene

After setting up the 3-D environment—choosing a device driver, creating the 3-D device and viewport, setting the rendering state, and so on—Helworld.c uses a series of functions to populate this 3-D environment with objects, frames, and lights:

  • The MyScene Function
  • The MakeMyFrames Function
  • The MakeMyLights Function
  • The SetMyPositions Function
  • The MakeMyMesh Function
  • The MakeMyWrap Function
  • The AddMyTexture Function

The MyScene Function

The MyScene function in Helworld.c corresponds to the BuildScene function that is implemented in all the Direct3D samples in the DirectX SDK. This is where all the work occurs that displays unique objects with unique textures and lighting effects.

The MyScene function uses a series of locally defined functions that set up the separate features of the scene that is being created. These functions are:

  • MakeMyFrames
  • MakeMyLights
  • SetMyPositions
  • MakeMyMesh
  • MakeMyWrap
  • AddMyTexture

When these functions have set up the visual object, MyScene uses the IDirect3DRMFrame::AddVisual method to add the object to the environment's world frame. After adding the visual object, MyScene no longer needs the interfaces it has created, so it uses the Release method repeatedly to release them all.

/////////////////////////////////////////////////////////////////////
//
// MyScene
// Uses the functions that create the frames, lights, mesh, and
// texture. Releases all interfaces on completion.
//
/////////////////////////////////////////////////////////////////////

BOOL
MyScene(LPDIRECT3DRMDEVICE dev, LPDIRECT3DRMVIEWPORT view,
    LPDIRECT3DRMFRAME lpScene, LPDIRECT3DRMFRAME lpCamera)
{
    LPDIRECT3DRMFRAME lpLightframe1 = NULL;
    LPDIRECT3DRMFRAME lpWorld_frame = NULL;
    LPDIRECT3DRMLIGHT lpLight1      = NULL;
    LPDIRECT3DRMLIGHT lpLight2      = NULL;
    LPDIRECT3DRMTEXTURE lpTex       = NULL;
    LPDIRECT3DRMWRAP lpWrap         = NULL;
    LPDIRECT3DRMMESHBUILDER  lpSphere3_builder = NULL;

    MakeMyFrames(lpScene, lpCamera, &lpLightframe1, &lpWorld_frame);
    MakeMyLights(lpScene, lpCamera, lpLightframe1, &lpLight1,
        &lpLight2);
    SetMyPositions(lpScene, lpCamera, lpLightframe1, lpWorld_frame);
    MakeMyMesh(&lpSphere3_builder);
    MakeMyWrap(lpSphere3_builder, &lpWrap);
    AddMyTexture(lpSphere3_builder, &lpTex);

    // If you need to create a material (for example, to create
    // a shiny surface), use CreateMaterial and SetMaterial here.

    // Now that the visual object has been created, add it
    // to the world frame.

    lpWorld_frame->lpVtbl->AddVisual(lpWorld_frame,
        (LPDIRECT3DRMVISUAL) lpSphere3_builder);

    lpLightframe1->lpVtbl->Release(lpLightframe1);
    lpWorld_frame->lpVtbl->Release(lpWorld_frame);
    lpSphere3_builder->lpVtbl->Release(lpSphere3_builder);
    lpLight1->lpVtbl->Release(lpLight1);
    lpLight2->lpVtbl->Release(lpLight2);
    lpTex->lpVtbl->Release(lpTex);
    lpWrap->lpVtbl->Release(lpWrap);

    return TRUE;
}

The MakeMyFrames Function

The MyScene function uses the MakeMyFrames function to create the frames for the directional light and the world frame used in Helworld.c. MakeMyFrames does this work by using the IDirect3DRM::CreateFrame method.

/////////////////////////////////////////////////////////////////////
//
// MakeMyFrames
// Create frames used in the scene.
//
/////////////////////////////////////////////////////////////////////

void MakeMyFrames(LPDIRECT3DRMFRAME lpScene, LPDIRECT3DRMFRAME lpCamera,
    LPDIRECT3DRMFRAME * lplpLightFrame1,
    LPDIRECT3DRMFRAME * lplpWorld_frame)
{
    lpD3DRM->lpVtbl->CreateFrame(lpD3DRM, lpScene, lplpLightFrame1);
    lpD3DRM->lpVtbl->CreateFrame(lpD3DRM, lpScene, lplpWorld_frame);
}

The MakeMyLights Function

The MyScene function uses the MakeMyLights function to create the directional and ambient lights used in Helworld.c. MakeMyLights uses the IDirect3DRM::CreateLightRGB and IDirect3DRMFrame::AddLight methods to create a bright directional light and add it to a light frame, and to create a dim ambient light and add it to the entire scene. (Ambient lights are always associated with an entire scene.)

/////////////////////////////////////////////////////////////////////
//
// MakeMyLights
// Create lights used in the scene.
//
/////////////////////////////////////////////////////////////////////

void MakeMyLights(LPDIRECT3DRMFRAME lpScene, LPDIRECT3DRMFRAME lpCamera,
    LPDIRECT3DRMFRAME lpLightFrame1,
    LPDIRECT3DRMLIGHT * lplpLight1, LPDIRECT3DRMLIGHT * lplpLight2)
{
    lpD3DRM->lpVtbl->CreateLightRGB(lpD3DRM, D3DRMLIGHT_DIRECTIONAL,
        D3DVAL(0.9), D3DVAL(0.9), D3DVAL(0.9), lplpLight1);

    lpLightFrame1->lpVtbl->AddLight(lpLightFrame1, *lplpLight1);

    lpD3DRM->lpVtbl->CreateLightRGB(lpD3DRM, D3DRMLIGHT_AMBIENT,
        D3DVAL(0.1), D3DVAL(0.1), D3DVAL(0.1), lplpLight2);

    lpScene->lpVtbl->AddLight(lpScene, *lplpLight2);
}

The SetMyPositions Function

The MyScene function uses the SetMyPositions function to set the positions and orientations of the frames used in Helworld.c. SetMyPositions does this work by using the IDirect3DRMFrame::SetPosition and IDirect3DRMFrame::SetOrientation methods. The IDirect3DRMFrame::SetRotation method imparts a spin to the frame to which the sphere will be added.

/////////////////////////////////////////////////////////////////////
//
// SetMyPositions
// Set the positions and orientations of the light, camera, and
// world frames. Establish a rotation for the globe.
//
/////////////////////////////////////////////////////////////////////

void SetMyPositions(LPDIRECT3DRMFRAME lpScene,
    LPDIRECT3DRMFRAME lpCamera, LPDIRECT3DRMFRAME lpLightFrame1,
    LPDIRECT3DRMFRAME lpWorld_frame)
{

    lpLightFrame1->lpVtbl->SetPosition(lpLightFrame1, lpScene,
        D3DVAL(2), D3DVAL(0.0), D3DVAL(22));

    lpCamera->lpVtbl->SetPosition(lpCamera, lpScene,
        D3DVAL(0.0), D3DVAL(0.0), D3DVAL(0.0));
    lpCamera->lpVtbl->SetOrientation(lpCamera, lpScene,
        D3DVAL(0.0), D3DVAL(0.0), D3DVAL(1),
        D3DVAL(0.0), D3DVAL(1), D3DVAL(0.0));

    lpWorld_frame->lpVtbl->SetPosition(lpWorld_frame, lpScene,
        D3DVAL(0.0), D3DVAL(0.0), D3DVAL(15));
    lpWorld_frame->lpVtbl->SetOrientation(lpWorld_frame, lpScene,
        D3DVAL(0.0), D3DVAL(0.0), D3DVAL(1),
        D3DVAL(0.0), D3DVAL(1), D3DVAL(0.0));

    lpWorld_frame->lpVtbl->SetRotation(lpWorld_frame, lpScene,
        D3DVAL(0.0), D3DVAL(0.1), D3DVAL(0.0), D3DVAL(0.05));
}

The MakeMyMesh Function

The MyScene function uses the MakeMyMesh function to load and set the spherical mesh used in Helworld.c. MakeMyMesh uses the IDirect3DRM::CreateMeshBuilder method to create an IDirect3DRMMeshBuilder interface. Then it uses the IDirect3DRMMeshBuilder::Load, IDirect3DRMMeshBuilder::Scale, and IDirect3DRMMeshBuilder::SetColorRGB methods to prepare the mesh represented by the Sphere3.x file. (The Sphere3.x file is included in the DirectX SDK, as part of the media provided for use with the sample code.)

/////////////////////////////////////////////////////////////////////
//
// MakeMyMesh
// Create MeshBuilder object, load, scale, and color the mesh.
//
/////////////////////////////////////////////////////////////////////

void MakeMyMesh(LPDIRECT3DRMMESHBUILDER  * lplpSphere3_builder)
{
    lpD3DRM->lpVtbl->CreateMeshBuilder(lpD3DRM, lplpSphere3_builder);

    (*lplpSphere3_builder)->lpVtbl->Load(*lplpSphere3_builder,
        "sphere3.x", NULL, D3DRMLOAD_FROMFILE, NULL, NULL);

    (*lplpSphere3_builder)->lpVtbl->Scale(*lplpSphere3_builder,
        D3DVAL(2), D3DVAL(2), D3DVAL(2));

    // Set sphere to white to avoid unexpected texture-blending results.

    (*lplpSphere3_builder)->lpVtbl->SetColorRGB(*lplpSphere3_builder,
        D3DVAL(1), D3DVAL(1), D3DVAL(1));
}

The MakeMyWrap Function

The MyScene function uses the MakeMyWrap function to create and apply texture coordinates to the sphere loaded by the MakeMyMesh function. MakeMyWrap uses the IDirect3DRMMeshBuilder::GetBox method to retrieve the bounding box that contains the sphere and uses the dimensions of that bounding box in a call to the IDirect3DRM::CreateWrap method, which creates a cylindrical texture wrap and retrieves the IDirect3DRMWrap interface. A call to the IDirect3DRMWrap::Apply method applies the texture coordinates to the sphere.

/////////////////////////////////////////////////////////////////////
//
// MakeMyWrap
// Creates and applies wrap for texture.
//
/////////////////////////////////////////////////////////////////////

void MakeMyWrap(LPDIRECT3DRMMESHBUILDER  sphere3_builder,
                LPDIRECT3DRMWRAP * lpWrap)
{
    D3DVALUE miny, maxy, height;
    D3DRMBOX box;

    sphere3_builder->lpVtbl->GetBox(sphere3_builder, &box);

    maxy = box.max.y;
    miny = box.min.y;
    height = maxy - miny;

    lpD3DRM->lpVtbl->CreateWrap
        (lpD3DRM, D3DRMWRAP_CYLINDER, NULL,
        D3DVAL(0.0), D3DVAL(0.0), D3DVAL(0.0),
        D3DVAL(0.0), D3DVAL(1.0), D3DVAL(0.0),
        D3DVAL(0.0), D3DVAL(0.0), D3DVAL(1.0),
        D3DVAL(0.0), D3DDivide(miny, height),
        D3DVAL(1.0), D3DDivide(D3DVAL(1.0), height),
        lpWrap);

    (*lpWrap)->lpVtbl->Apply(*lpWrap, (LPDIRECT3DRMOBJECT)
        sphere3_builder);

}

The AddMyTexture Function

The MyScene function uses the AddMyTexture function to load a texture and associate it with the sphere. AddMyTexture uses the IDirect3DRM::LoadTexture method to load a bitmap called Tutor.bmp, and then it uses the IDirect3DRMMeshBuilder::SetTexture method to associate the bitmap with the sphere.

Bitmap used as a texture on the sphere

/////////////////////////////////////////////////////////////////////
//
// AddMyTexture
// Creates and applies wrap for texture.
//
/////////////////////////////////////////////////////////////////////

void AddMyTexture(LPDIRECT3DRMMESHBUILDER  lpSphere3_builder,
    LPDIRECT3DRMTEXTURE * lplpTex)
{
    lpD3DRM->lpVtbl->LoadTexture(lpD3DRM, "tutor.bmp", lplpTex);

    // If you need a color depth other than the default (16),
    // use IDirect3DRMTexture::SetShades here.

    lpSphere3_builder->lpVtbl->SetTexture(lpSphere3_builder, *lplpTex);

}

Cleaning Up

Helworld.c uses the CleanUp function when it receives a WM_DESTROY message or after several consecutive unsuccessful attempts to use the RenderLoop function.

/////////////////////////////////////////////////////////////////////
//
// CleanUp
// Release all D3DRM objects and set the bQuit flag.
//
/////////////////////////////////////////////////////////////////////

void
CleanUp(void)
{
    myglobs.bInitialized = FALSE;
    myglobs.scene->lpVtbl->Release(myglobs.scene);
    myglobs.camera->lpVtbl->Release(myglobs.camera);
    myglobs.view->lpVtbl->Release(myglobs.view);
    myglobs.dev->lpVtbl->Release(myglobs.dev);
    lpD3DRM->lpVtbl->Release(lpD3DRM);
    lpDDClipper->lpVtbl->Release(lpDDClipper);

    myglobs.bQuit = TRUE;
}


Reference

The Microsoft® Direct3D® Retained Mode C++/COM Reference provides detailed information about the interfaces, methods (interface member functions), nonmember functions, and callback functions, with syntax, parameter descriptions, and flag descriptions. It also describes the members of Direct3D Retained Mode structures, enumerated types, other defined types, and the possible error values that can be returned. This section contains the following topics.

Functions and Interfaces

  • Callback Functions
  • Interfaces
  • Nonmember Functions

Data Types

  • Constants
  • Enumerated Types
  • Structures

Other Topics

  • Return Values
  • Further Reading


Callback Functions

The Microsoft® Direct3D® Retained Mode callback functions are:

  • D3DRMDEVICE3UPDATECALLBACK (replaces D3DRMUPDATECALLBACK)
  • D3DRMDOWNSAMPLECALLBACK
  • D3DRMFRAME3MOVECALLBACK (replaces D3DRMFRAMEMOVECALLBACK)
  • D3DRMLOADCALLBACK
  • D3DRMLOADTEXTURECALLBACK
  • D3DRMOBJECTCALLBACK
  • D3DRMUSERVISUALCALLBACK
  • D3DRMVALIDATIONCALLBACK
  • D3DRMWRAPCALLBACK

D3DRMDEVICE3UPDATECALLBACK

Alerts the application when the device changes. This callback function is application-defined.

Syntax

void (*D3DRMDEVICE3UPDATECALLBACK)(
  LPDIRECT3DRMDEVICE3 lpobj,
  LPVOID lpArg,
  int iRectCount,
  LPD3DRECT d3dRectUpdate);

Parameters

lpobj
Pointer to the address of the Direct3DRMDevice3 object to which this callback function applies.
lpArg
Pointer to the address of application-defined data passed to this callback function.
iRectCount
Number of rectangles specified in the d3dRectUpdate parameter.
d3dRectUpdate
Array of one or more D3DRECT structures that describe the area to be updated. The coordinates are specified in device units.

Return Value

No return value.

Remarks

When determining the order in which to use callback functions, the system searches the objects highest in the hierarchy first, and then uses their callback functions in the order in which they were created.

D3DRMDEVICE3UPDATECALLBACK was introduced with DirectX version 6.0 and replaces the older D3DRMUPDATECALLBACK. The only difference between the two callbacks is that the new callback takes a Direct3DRMDevice3 object, rather than a Direct3DRMDevice object for the lpobj parameter.

See Also

IDirect3DRMDevice3::AddUpdateCallback, IDirect3DRMDevice3::DeleteUpdateCallback, IDirect3DRMDevice3::Update

D3DRMDOWNSAMPLECALLBACK

Called when the video memory is getting overloaded and the texture surfaces need to be reduced in size. Direct3D Retained Mode provides default methods for reducing texure sizes, such as DirectDraw blitting and bilinear filtering, but users can define their own method to scale down texture size with this callback. This callback function is application-defined.

Syntax

HRESULT (*D3DRMDOWNSAMPLECALLBACK)(
  LPDIRECT3DRMTEXTURE3 lpDirect3DRMTexture,
  LPVOID lpArg,
  LPDIRECTDRAWSURFACE pDDSSrc,
  LPDIRECTDRAWSURFACE pDDSDst);

Parameters

lpDirect3DRMTexture
Pointer to the address of the Direct3DRMTexture3 object to which this callback function applies.
lpArg
Pointer to the address of application-defined data passed to this callback function.
pDDSSrc
Pointer to the system memory prototype surface.
pDDSDst
Pointer to the scaled down surface.

Return Value

No return value.

Remarks

D3DRMDOWNSAMPLECALLBACK was introduced with DirectX version 6.0.

See Also

IDirect3DRMTexture3::SetDownsampleCallback

D3DRMFRAME3MOVECALLBACK

Enables an application to apply customized algorithms when a frame is moved or updated. You can use this callback function to compensate for changing frame rates. This callback function is application-defined.

Syntax

void (*D3DRMFRAME3MOVECALLBACK)(
  LPDIRECT3DRMFRAME3 lpD3DRMFrame,
  LPVOID lpArg,
  D3DVALUE delta);

Parameters

lpD3DRMFrame
Pointer to the address of the Direct3DRMFrame3 object that is being moved.
lpArg
Pointer to the address of application-defined data passed to this callback function.
delta
Amount of change to apply to the movement. There are two components to the change in position of a frame: linear and rotational. The change in each component is equal to velocity_of_component × delta. Although either or both of these velocities can be set relative to any frame, the system automatically converts them to velocities relative to the parent frame for the purpose of applying time deltas.

Return Value

No return value.

Remarks

Your application can synthesize the acceleration of a frame relative to its parent frame. To do so, on each tick your application should set the velocity of the child frame relative to itself to (a units per tick) × 1 tick, where a is the required acceleration. This is equal to a × delta units per tick. Internally, a × delta units per tick relative to the child frame is converted to (v + (a × delta)) units per tick relative to the parent frame, where v is the current velocity of the child relative to the parent.

You can add and remove this callback function from your application by using the IDirect3DRMFrame3::AddMoveCallback and IDirect3DRMFrame3::DeleteMoveCallback methods.

When determining the order in which to use callback functions, the system searches the objects highest in the hierarchy first, and then uses their callback functions in the order in which they were created.

D3DRMFRAME3MOVECALLBACK was introduced with DirectX version 6.0 and replaces the older D3DRMFRAMEMOVECALLBACK. The only difference between the two callbacks is that the new callback takes a Direct3DRMFrame3 object rather than a Direct3DRMFrame object for the lpD3DRMFrame parameter.

D3DRMLOADCALLBACK

Loads objects named in a call to the IDirect3DRM3::Load method. This callback function is application-defined.

Syntax

void (*D3DRMLOADCALLBACK)(
  LPDIRECT3DRMOBJECT lpObject,
  REFIID ObjectGuid,
  LPVOID lpArg);

Parameters

lpObject
Pointer to the address of the Direct3DRMObject being loaded.
ObjectGuid
Globally unique identifier (GUID) of the object being loaded.
lpArg
Pointer to the address of application-defined data passed to this callback function.

Return Value

No return value.

Remarks

When determining the order in which to use callback functions, the system searches the objects highest in the hierarchy first, and then uses their callback functions in the order in which they were created.

See Also

IDirect3DRM3::Load

D3DRMLOADTEXTURECALLBACK

Loads texture maps from a file or resource named in a call to one of the Load methods. This callback function is application-defined.

Syntax

HRESULT (*D3DRMLOADTEXTURECALLBACK)(
  char *tex_name,
  void *lpArg,
  LPDIRECT3DRMTEXTURE *lpD3DRMTex);

Parameters

tex_name
Pointer to the address of a string containing the name of the texture.
lpArg
Pointer to the address of application-specific data.
lpD3DRMTex
Pointer to the address of the Direct3DRMTexture object.

Return Value

Should return D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

Remarks

Applications can use this callback function to implement support for textures that are not in the Microsoft® Windows® bitmap (.bmp) or Portable Pixelmap bitmap (.ppm) P6 format. The P6 format is a binary file format for color images.

When determining the order in which to use callback functions, the system searches the objects highest in the hierarchy first, and then uses their callback functions in the order in which they were created.

See Also

IDirect3DRM3::Load, IDirect3DRMAnimationSet2::Load, IDirect3DRMFrame3::Load, IDirect3DRMMeshBuilder3::Load

D3DRMLOADTEXTURE3CALLBACK

Loads texture maps from a file or resource named in a call to one of the Load methods. This callback function is application-defined.

Syntax

HRESULT (*D3DRMLOADTEXTURE3CALLBACK)(
  char *tex_name,
  void *lpArg,
  LPDIRECT3DRMTEXTURE3 *lpD3DRMTex3);

Parameters

tex_name
Pointer to the address of a string containing the name of the texture.
lpArg
Pointer to the address of application-specific data.
lpD3DRMTex3
Pointer to the address of the Direct3DRMTexture3 object.

Return Value

Should return D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

Remarks

Applications can use this callback function to implement support for textures that are not in the Microsoft® Windows® bitmap (.bmp) or Portable Pixelmap bitmap (.ppm) P6 format. The P6 format is a binary file format for color images.

When determining the order in which to use callback functions, the system searches the objects highest in the hierarchy first, and then uses their callback functions in the order in which they were created.

See Also

IDirect3DRM3::Load, IDirect3DRMAnimationSet2::Load, IDirect3DRMFrame3::Load, IDirect3DRMMeshBuilder3::Load

D3DRMOBJECTCALLBACK

Enumerates objects in response to a call to the IDirect3DRM3::EnumerateObjects method. This callback function is application-defined.

Syntax

void (*D3DRMOBJECTCALLBACK)(
  LPDIRECT3DRMOBJECT lpD3DRMobj,
  LPVOID lpArg);

Parameters

lpD3DRMobj
Pointer to the IDirect3DRMObject interface for the object being enumerated. The application must use the Release method for each enumerated object.
lpArg
Pointer to the address of application-defined data passed to this callback function.

Return Value

No return value.

Remarks

When determining the order in which to use callback functions, the system searches the objects highest in the hierarchy first, and then uses their callback functions in the order in which they were created.

See Also

IDirect3DRM3::EnumerateObjects

D3DRMUSERVISUALCALLBACK

Alerts an application that supplies user-visual objects that it should execute the execute buffer. This function is application-defined.

Syntax

int (*D3DRMUSERVISUALCALLBACK)(
  LPDIRECT3DRMUSERVISUAL lpD3DRMUV,
  LPVOID lpArg,
  D3DRMUSERVISUALREASON lpD3DRMUVreason,
  LPDIRECT3DRMDEVICE lpD3DRMDev,
  LPDIRECT3DRMVIEWPORT lpD3DRMview);

Parameters

lpD3DRMUV
Pointer to the address of the Direct3DRMUserVisual object.
lpArg
Pointer to the address of application-defined data passed to this callback function.
lpD3DRMUVreason
One of the members of the D3DRMUSERVISUALREASON enumerated type:
D3DRMUSERVISUAL_CANSEE
The application should return TRUE if the user-visual object is visible in the viewport. In this case, the application uses the device specified in the lpD3DRMview parameter.
D3DRMUSERVISUAL_RENDER
The application should render the user-visual element. In this case, the application uses the device specified in the lpD3DRMDev parameter.
lpD3DRMDev
Pointer to the address of a Direct3DRMDevice object used to render the Direct3DRMUserVisual object.
lpD3DRMview
Pointer to the address of a Direct3DRMViewport object used to determine whether the Direct3DRMUserVisual object is visible.

Return Value

Returns TRUE if the lpD3DRMUVreason parameter is D3DRMUSERVISUAL_CANSEE, and the user-visual object is visible in the viewport. Returns FALSE otherwise. If the lpD3DRMUVreason parameter is D3DRMUSERVISUAL_RENDER, the return value is application-defined. It is always safe to return TRUE.

Remarks

If the application changes the render state, it should restore the render state before returning from this function.

When determining the order in which to use callback functions, the system searches the objects highest in the hierarchy first, and then uses their callback functions in the order in which they were created.

See Also

IDirect3DRMUserVisual::Init and IDirect3DRM3::CreateUserVisual

D3DRMVALIDATIONCALLBACK

Called when a texture region that has previously been marked as invalid, meaning it has changed but not been updated, now needs to be updated. This callback function is application-defined.

Syntax

HRESULT (*D3DRMVALIDATIONCALLBACK)(
  LPDIRECT3DRMTEXTURE3 lpDirect3DRMTexture,
  LPVOID lpArg,
  DWORD dwFlags,
  DWORD dwcRects,
  LPRECT pRects);

Parameters

lpDirect3DRMTexture
Pointer to the address of the Direct3DRMTexture3 object to which this callback function applies.
lpArg
Pointer to the address of application-defined data passed to this callback function.
dwFlags
Not used. Set to 0.
dwcRects
Number of rectangles specified in the pRects parameter.
pRects
Array of one or more RECT structures that describe the area to be updated. The coordinates are specified in device units.

Return Value

No return value.

Remarks

When you want to inform Direct3D Retained Mode that a texture region has been changed but want to defer changing it, you can say the region is invalid and store the region in the array pointed to by pRects. Then, if the texture is needed, call this callback function to inform your application to update the texture region.

D3DRMVALIDATIONCALLBACK was introduced with DirectX version 6.0.

See Also

IDirect3DRMTexture3::SetValidationCallback

D3DRMWRAPCALLBACK

This callback function is not supported.

Syntax

void (*D3DRMWRAPCALLBACK)(
  LPD3DVECTOR lpD3DVector,
  int* lpU,
  int* lpV,
  LPD3DVECTOR lpD3DRMVA,
  LPD3DVECTOR lpD3DRMVB,
  LPVOID lpArg);


Interfaces

  • IDirect3DRM3
  • IDirect3DRMAnimation2
  • IDirect3DRMAnimationArray
  • IDirect3DRMAnimationSet2
  • IDirect3DRMArray
  • IDirect3DRMClippedVisual
  • IDirect3DRMDevice3
  • IDirect3DRMDeviceArray
  • IDirect3DRMFace2
  • IDirect3DRMFaceArray
  • IDirect3DRMFrame3
  • IDirect3DRMFrameArray
  • IDirect3DRMInterpolator
  • IDirect3DRMLight
  • IDirect3DRMLightArray
  • IDirect3DRMMaterial2
  • IDirect3DRMMesh
  • IDirect3DRMMeshBuilder3
  • IDirect3DRMObject
  • IDirect3DRMObject2
  • IDirect3DRMObjectArray
  • IDirect3DRMPicked2Array
  • IDirect3DRMPickedArray
  • IDirect3DRMProgressiveMesh
  • IDirect3DRMShadow2
  • IDirect3DRMTexture3
  • IDirect3DRMUserVisual
  • IDirect3DRMViewport2
  • IDirect3DRMViewportArray
  • IDirect3DRMVisual
  • IDirect3DRMVisualArray
  • IDirect3DRMWinDevice
  • IDirect3DRMWrap


IDirect3DRM3

Applications use the IDirect3DRM3 interface to create Direct3DRM3 objects and work with system-level variables. For a history of the Direct3D Retained Mode interfaces, see Interface Changes.

The methods of the IDirect3DRM3, IDirect3DRM2, and IDirect3DRM interfaces create the following objects:

  • Animations and animation sets
  • ClippedVisuals
  • Devices
  • Faces
  • Frames
  • Generic uninitialized objects
  • Lights
  • Materials
  • Meshes and mesh builders
  • Shadows
  • Textures
  • UserVisuals
  • Viewports
  • Wraps

Microsoft DirectX version 6.0 introduces the IDirect3DRM3 interface. IDirect3DRM3 supports all of the methods provided by the IDirect3DRM2 and IDirect3DRM interfaces and replaces these two older interfaces. It adds a flag parameter to IDirect3DRM2's CreateDeviceFromSurface, and adds RegisterClient, UnregisterClient, and CreateClippedVisual methods to the methods IDirect3DRM2 provides. IDirect3DRM3 also adds the GetOptions and SetOptions methods to set and retrieve whether left-handed or right-handed geometry should be used.

IDirect3DRM3, like IDirect3DRM2, supports all the methods in IDirect3DRM. It adds the CreateProgressiveMesh method to the methods IDirect3DRM provides. The CreateDeviceFromSurface, CreateDeviceFromD3D, and CreateDeviceFromClipper methods all create a DIRECT3DRMDEVICE2 object with IDirect3DRM2 and a DIRECT3DRMDEVICE3 object with IDirect3DRM3. The CreateViewport method creates a viewport on a DirectDRMDevice2 object. The LoadTexture and LoadTextureFromResource methods load a Direct3DRMTexture2 object with IDirect3DRM2 and a Direct3DRMTexture3 object with IDirect3DRM3.

To access the IDirect3DRM3 or IDirect3DRM2 Component Object Model (COM) interfaces, create an IDirect3DRM object with Direct3DRMCreate, then query for IDirect3DRM3 or IDirect3DRM2, respectively, from IDirect3DRM. You can also access the main Direct3D Retained Mode object directly using CoCreateInstance.

When you create a MeshBuilder object using the IDirect3DRM3 interface, the MeshBuilder uses the Immediate Mode DrawPrimitive interface for its implementation.

When you create Lights using the IDirect3DRM3 interface, they take advantage of the latest Immediate Mode functionality and use the D3DLIGHT2 structure.

Applications use the IDirect3DRMDevice3, IDirect3DRMDevice2, and IDirect3DRMDevice interfaces to interact with the output device. For more information about the capabilities of the output device when you create it using the IDirect3DRM3, IDirect3DRM2, or IDirect3DRM interfaces, see IDirect3DRMDevice3. For a conceptual overview of output devices, see Output Devices.

The methods of the IDirect3DRM3 interface can be organized into the following groups:
Animation | CreateAnimation
CreateAnimationSet
Application-specific Data | RegisterClient
UnregisterClient
Clipped Visuals | CreateClippedVisual
Devices | CreateDevice
CreateDeviceFromClipper
CreateDeviceFromD3D
CreateDeviceFromSurface
GetDevices
Enumeration | EnumerateObjects
Faces | CreateFace
Frames | CreateFrame
Lights | CreateLight
CreateLightRGB
Materials | CreateMaterial
Meshes | CreateMesh
CreateMeshBuilder
Miscellaneous | CreateObject
CreateUserVisual
GetNamedObject
GetOptions
Load
SetOptions
Tick
Progressive Meshes | CreateProgressiveMesh
Search paths | AddSearchPath
GetSearchPath
SetSearchPath
Shadows | CreateShadow
Textures | CreateTexture
CreateTextureFromSurface
LoadTexture
LoadTextureFromResource
SetDefaultTextureColors
SetDefaultTextureShades
Viewports | CreateViewport
Wraps | CreateWrap

The IDirect3DRM3 interface, like all COM interfaces, inherits the IUnknown interface methods. The IUnknown interface supports the following three methods:
AddRef
QueryInterface
Release

IDirect3DRM3::AddSearchPath

IDirect3DRM3

Adds a list of directories to the end of the current file search path.

Syntax

HRESULT AddSearchPath(
  LPCSTR lpPath
  );

Parameters

lpPath
Address of a null-terminated string specifying the path to add to the current search path.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible return codes, see Direct3D Retained Mode Return Values.

Remarks

For Microsoft® Windows®, the path should be a list of directories separated by semicolons (;).

See Also

IDirect3DRM3::SetSearchPath

IDirect3DRM3::CreateAnimation

IDirect3DRM3

Creates an empty Direct3DRMAnimation object.

Syntax

HRESULT CreateAnimation(
  LPDIRECT3DRMANIMATION2 * lplpD3DRMAnimation
  );

Parameters

lplpD3DRMAnimation
Address that will be filled with a pointer to an IDirect3DRMAnimation2 interface if the call succeeds.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible return codes, see Direct3D Retained Mode Return Values.

IDirect3DRM3::CreateAnimationSet

IDirect3DRM3

Creates an empty Direct3DRMAnimationSet object.

Syntax

HRESULT CreateAnimationSet (
  LPDIRECT3DRMANIMATIONSET2 * lplpD3DRMAnimationSet
  );

Parameters

lplpD3DRMAnimationSet
Address that will be filled with a pointer to an IDirect3DRMAnimationSet2 interface if the call succeeds.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible return codes, see Direct3D Retained Mode Return Values.

IDirect3DRM3::CreateClippedVisual

IDirect3DRM3

Creates a clipped visual object.

Syntax

HRESULT CreateClippedVisual(
  LPDIRECT3DRMVISUAL lpVisual,
  LPDIRECT3DRMCLIPPEDVISUAL * lpClippedVisual);

Parameters

lpVisual
Pointer to a visual object, such as a meshbuilder object.
lpClippedVisual
Pointer to receive the created IDirect3DRMClippedVisual clipped visual object.

Return Value

Returns one of the following values:
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DD_OK

Remarks

This method was introduced with DirectX version 6.0.

IDirect3DRM3::CreateDevice

IDirect3DRM3

Not implemented on the Windows platform.

Syntax

HRESULT CreateDevice(
  DWORD dwWidth,
  DWORD dwHeight,
  LPDIRECT3DRMDEVICE3* lplpD3DRMDevice
  );

IDirect3DRM3::CreateDeviceFromClipper

IDirect3DRM3

Creates a Direct3D Retained Mode Windows device by using a specified DirectDrawClipper object.

Syntax

HRESULT CreateDeviceFromClipper(
  LPDIRECTDRAWCLIPPER lpDDClipper,
  LPGUID lpGUID,
  int width,
  int height,
  LPDIRECT3DRMDEVICE3 * lplpD3DRMDevice
  );

Parameters

lpDDClipper
Address of a DirectDrawClipper object.
lpGUID
Address of a globally unique identifier (GUID). This parameter can be NULL.
width and height
Width and height of the device to be created.
lplpD3DRMDevice
Address that will be filled with a pointer to an IDirect3DRMDevice3 interface if the call succeeds.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible return codes, see Direct3D Retained Mode Return Values.

Remarks

If the lpGUID parameter is NULL, the system searches for a device with a default set of device capabilities. This is the recommended way to create a Retained Mode device because it always works, even if the user installs new hardware.

The system describes the default settings by using the following flags from the D3DPRIMCAPS structure in internal device-enumeration calls:
D3DPSHADECAPS_ALPHAFLATSTIPPLED
D3DPTBLENDCAPS_COPY | D3DPTBLENDCAPS_MODULATE
D3DPMISCCAPS_CULLCCW
D3DPRASTERCAPS_FOGVERTEX
D3DPCMPCAPS_LESSEQUAL
D3DPTFILTERCAPS_NEAREST
D3DPTEXTURECAPS_PERSPECTIVE | D3DPTEXTURECAPS_TRANSPARENCY
D3DPTADDRESSCAPS_WRAP

If a hardware device is not found, the monochromatic (ramp) software driver is loaded. An application should enumerate devices instead of specifying NULL in the lpGUID parameter if it has special needs that are not met by this list of default settings.

For more information about devices, see Output Devices and IDirect3DRMDevice3.

IDirect3DRM3::CreateDeviceFromD3D

IDirect3DRM3

Creates a Direct3D Retained Mode Windows device by using specified Direct3D objects.

Syntax

HRESULT CreateDeviceFromD3D(
  LPDIRECT3D2 lpD3D,
  LPDIRECT3DDEVICE2 lpD3DDev,
  LPDIRECT3DRMDEVICE3 * lplpD3DRMDevice
  );

Parameters

lpD3D
Pointer to an instance of a Direct3D Immediate Mode Direct3D2 object.
lpD3DDev
Pointer to a Direct3D Immediate Mode Direct3DDevice2 object.
lplpD3DRMDevice
Address that will be filled with a pointer to an IDirect3DRMDevice3 interface if the call succeeds.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible return codes, see Direct3D Retained Mode Return Values.

Remarks

For more information about devices, see Output Devices and IDirect3DRMDevice3.

IDirect3DRM3::CreateDeviceFromSurface

IDirect3DRM3

Creates a Direct3D Retained Mode Windows device for rendering from the specified DirectDraw surfaces.

Syntax

HRESULT CreateDeviceFromSurface(
  LPGUID lpGUID,
  LPDIRECTDRAW lpDD,
  LPDIRECTDRAWSURFACE lpDDSBack,
  DWORD dwFlags,
  LPDIRECT3DRMDEVICE3* lplpD3DRMDevice);

Parameters

lpGUID
Address of the globally unique identifier (GUID) used as the required device driver. If this parameter is NULL, the default device driver is used.
lpDD
Address of the DirectDraw object that is the source of the DirectDraw surface.
lpDDSBack
Address of the DirectDrawSurface object that represents the back buffer.
dwFlags
The only currently defined flag is:
D3DRMDEVICE_NOZBUFFER
Indicates that if the lpDDSBack parameter has no z-buffer attached, no z-buffer is to be created. By default, a z-buffer will be created.
lplpD3DRMDevice
Address that will be filled with a pointer to an IDirect3DRMDevice3 interface if the call succeeds.

Return Value

Returns one of the following values:
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_OUTOFMEMORY
DD_OK

Remarks

This method was introduced with DirectX version 6.0. This method adds the dwFlags parameter to the older IDirect3DRM2::CreateDeviceFromSurface method which it replaces.

For more information about devices, see Output Devices and IDirect3DRMDevice3.

IDirect3DRM3::CreateFace

IDirect3DRM3

Creates an instance of the IDirect3DRMFace2 interface.

Syntax

HRESULT CreateFace(
  LPDirect3DRMFace2 * lplpd3drmFace2
  );

Parameters

lplpd3drmFace2
Address that will be filled with a pointer to an IDirect3DRMFace2 interface if the call succeeds.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible return codes, see Direct3D Retained Mode Return Values.

IDirect3DRM3::CreateFrame

IDirect3DRM3

Creates a new child frame of the given parent frame.

Syntax

HRESULT CreateFrame(
  LPDIRECT3DRMFRAME3 lpD3DRMFrame,
  LPDIRECT3DRMFRAME3* lplpD3DRMFrame
  );

Parameters

lpD3DRMFrame
Address of a IDirect3DRMFrame3 object that is to be the parent of the new frame.
lplpD3DRMFrame
Address that will be filled with a pointer to an IDirect3DRMFrame3 interface if the call succeeds.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible return codes, see Direct3D Retained Mode Return Values.

Remarks

The child frame inherits the motion attributes of its parent. For example, if the parent is moving with a given velocity, the child frame will also move with that velocity. Furthermore, if the parent is set rotating, the child frame will rotate about the origin of the parent. Frames that have no parent are called scenes. To create a scene, specify NULL as the parent. An application can create a frame with no parent and then associate it with a parent frame later by using the IDirect3DRMFrame3::AddChild method.

If an application calls IDirect3DRM3::SetOptions to set right-handed geometry, the default axes for root frames (frames with NULL as the parent) becomes v = (0, 0, -1) and u = (0, 1, 0). Therefore IDirect3DRMFrame3::GetOrientation and IDirect3DRMFrame3::SetOrientation work correctly in right-handed mode.

See Also

IDirect3DRMFrame3::AddChild

IDirect3DRM3::CreateLight

IDirect3DRM3

Creates a new light source with the given type and color.

Syntax

HRESULT CreateLight(
  D3DRMLIGHTTYPE d3drmltLightType,
  D3DCOLOR cColor,
  LPDIRECT3DRMLIGHT* lplpD3DRMLight
  );

Parameters

d3drmltLightType
One of the lighting types given in the D3DRMLIGHTTYPE enumerated type.
cColor
Color of the light.
lplpD3DRMLight
Address that will be filled with a pointer to an IDirect3DRMLight interface if the call succeeds.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible return codes, see Direct3D Retained Mode Return Values.

IDirect3DRM3::CreateLightRGB

IDirect3DRM3

Creates a new light source with the given type and color.

Syntax

HRESULT CreateLightRGB(
  D3DRMLIGHTTYPE ltLightType,
  D3DVALUE vRed,
  D3DVALUE vGreen,
  D3DVALUE vBlue,
  LPDIRECT3DRMLIGHT* lplpD3DRMLight
  );

Parameters

ltLightType
One of the lighting types given in the D3DRMLIGHTTYPE enumerated type.
vRed, vGreen, and vBlue
Color of the light. Each component of the color should be in the range 0.0 to 1.0.
lplpD3DRMLight
Address that will be filled with a pointer to an IDirect3DRMLight interface if the call succeeds.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible return codes, see Direct3D Retained Mode Return Values.

Remarks

The following code fragment calls CreateLightRGB to create a bright directional light. It assumes the Direct3D Retained Mode object has already been created using the Direct3DRMCreate function.

LPDIRECT3DRM3 lpD3DRM;
LPDIRECT3DRMLIGHT light;

if (FAILED(lpD3DRM->CreateLightRGB(D3DRMLIGHT_DIRECTIONAL,
                                   D3DVAL(0.9), D3DVAL(0.9), D3DVAL(0.9),
                                   &light))
{
    // error
}

IDirect3DRM3::CreateMaterial

IDirect3DRM3

Creates a material with the given specular property.

Syntax

HRESULT CreateMaterial(
  D3DVALUE vPower,
  LPDIRECT3DRMMATERIAL2 * lplpD3DRMMaterial
  );

Parameters

vPower
Sharpness of the reflected highlights, with a value of 5 giving a metallic look and higher values giving a more plastic look to the rendered surface.
lplpD3DRMMaterial
Address that will be filled with a pointer to an IDirect3DRMMaterial2 interface if the call succeeds.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible return codes, see Direct3D Retained Mode Return Values.

IDirect3DRM3::CreateMesh

IDirect3DRM3

Creates a new mesh object with no faces. The mesh is not visible until it is added to a frame.

Syntax

HRESULT CreateMesh(
  LPDIRECT3DRMMESH* lplpD3DRMMesh
  );

Parameters

lplpD3DRMMesh
Address that will be filled with a pointer to an IDirect3DRMMesh interface if the call succeeds.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible return codes, see Direct3D Retained Mode Return Values.

IDirect3DRM3::CreateMeshBuilder

IDirect3DRM3

Creates a new mesh builder object.

Syntax

HRESULT CreateMeshBuilder(
  LPDIRECT3DRMMESHBUILDER3 * lplpD3DRMMeshBuilder3
  );

Parameters

lplpD3DRMMeshBuilder3
Address that will be filled with a pointer to an IDirect3DRMMeshBuilder3 interface if the call succeeds.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible return codes, see Direct3D Retained Mode Return Values.

Remarks

By default, perspective correction is on.

IDirect3DRM3::CreateObject

IDirect3DRM3

Creates a new object without initializing the object.

Syntax

HRESULT CreateObject(
  REFCLSID rclsid,
  LPUNKNOWN pUnkOuter,
  REFIID riid,
  LPVOID FAR* ppv
  );

Parameters

rclsid
Class identifier for the new object.
pUnkOuter
Pointer to the outer IUnknown that allows COM aggregation features.
riid
Interface identifier of the object to be created.
ppv
Address of a pointer to the object when the method returns.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible return codes, see Direct3D Retained Mode Return Values.

Remarks

An application that uses this method must initialize the object that has been created. (The other creation methods of the IDirect3DRM3 interface initialize the object automatically.) In some cases, for example, for Direct3DRMViewport2 objects, you can use the Init method for that object. An application should use the Init method only once to initialize any given object.

Applications can use this method to implement aggregation in Direct3DRM objects.

IDirect3DRM3::CreateProgressiveMesh

IDirect3DRM3

Creates a new progressive mesh object with no faces. The mesh is not visible until it is added to a frame.

Syntax

HRESULT CreateProgressiveMesh(
  LPDIRECT3DRMPROGRESSIVEMESH* lplpD3DRMProgressiveMesh
  );

Parameters

lplpD3DRMProgressiveMesh
Address that will be filled with a pointer to an IDirect3DRMProgressiveMesh interface if the call succeeds.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible return codes, see Direct3D Retained Mode Return Values.

IDirect3DRM3::CreateShadow

IDirect3DRM3

Creates a shadow by using the specified visual and light, projecting the shadow onto the specified plane. The shadow is a visual that should be added to the frame that contains the visual.

Syntax

HRESULT CreateShadow(
  LPUNKNOWN pUnk,
  LPDIRECT3DRMLIGHT lpLight,
  D3DVALUE px,
  D3DVALUE py,
  D3DVALUE pz,
  D3DVALUE nx,
  D3DVALUE ny,
  D3DVALUE nz,
  LPDIRECT3DRMSHADOW2 * lplpShadow
  );

Parameters

pUnk
Pointer to the object casting the shadow.
lpLight
Address of the IDirect3DRMLight interface that is the light source.
px, py, and pz
Plane that the shadow is to be projected on.
nx, ny, and nz
Normal to the plane that the shadow is to be projected on.
lplpShadow
Address of a pointer to be initialized with a valid pointer to the shadow visual, if the call succeeds.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible return codes, see Direct3D Retained Mode Return Values.

IDirect3DRM3::CreateTexture

IDirect3DRM3

Creates a texture from an image in memory.

Syntax

HRESULT CreateTexture(
  LPD3DRMIMAGE lpImage,
  LPDIRECT3DRMTEXTURE3* lplpD3DRMTexture3
  );

Parameters

lpImage
Address of a D3DRMIMAGE structure describing the source for the texture.
lplpD3DRMTexture3
Address that will be filled with a pointer to an IDirect3DRMTexture3 interface if the call succeeds.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible return codes, see Direct3D Retained Mode Return Values.

Remarks

The memory associated with the image is used each time the texture is rendered, rather than the memory being copied into Direct3D Retained Mode's buffers. This allows the image to be used both as a rendering target and as a texture.

IDirect3DRM3::CreateTextureFromSurface

IDirect3DRM3

Creates a texture from a specified DirectDraw surface.

Syntax

HRESULT CreateTextureFromSurface(
  LPDIRECTDRAWSURFACE lpDDS,
  LPDIRECT3DRMTEXTURE3 * lplpD3DRMTexture3
  );

Parameters

lpDDS
Address of the DirectDrawSurface object containing the texture.
lplpD3DRMTexture3
Address that will be filled with a pointer to an IDirect3DRMTexture3 interface if the call succeeds.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible return codes, see Direct3D Retained Mode Return Values.

Remarks

When you create a texture from a DirectDraw surface, it is best to create the surface in system memory. This enables optimal performance for software devices and allows D3DRM to manage the use of video memory more effectively for hardware devices.

IDirect3DRM3::CreateUserVisual

IDirect3DRM3

Creates an application-defined visual object, which can then be added to a scene and rendered by using an application-defined handler.

Syntax

HRESULT CreateUserVisual(
  D3DRMUSERVISUALCALLBACK fn,
  LPVOID lpArg,
  LPDIRECT3DRMUSERVISUAL * lplpD3DRMUV
  );

Parameters

fn
Application-defined D3DRMUSERVISUALCALLBACK callback function.

lpArg
Address of application-defined data passed to the callback function.
lplpD3DRMUV
Address that will be filled with a pointer to an IDirect3DRMUserVisual interface if the call succeeds.

Return Value

Should return D3DRM_OK if successful, or an error otherwise. For a list of possible return codes, see Direct3D Retained Mode Return Values.

See Also

IDirect3DRMUserVisual::Init

IDirect3DRM3::CreateViewport

IDirect3DRM3

Creates a viewport on a device with device coordinates (dwXPos, dwYPos) to (dwXPos + dwWidth, dwYPos + dwHeight).

Syntax

HRESULT CreateViewport(
  LPDIRECT3DRMDEVICE3 lpDev,
  LPDIRECT3DRMFRAME3 lpCamera,
  DWORD dwXPos,
  DWORD dwYPos,
  DWORD dwWidth,
  DWORD dwHeight,
  LPDIRECT3DRMVIEWPORT2* lplpD3DRMViewport
  );

Parameters

lpDev
Address of a IDirect3DRMDevice3 device on which the viewport is to be created.
lpCamera
Address of a frame that describes the position and direction of the view.
dwXPos, dwYPos, dwWidth, and dwHeight
Position and size of the viewport, in device coordinates. The viewport size cannot be larger than the physical device or the method will fail.
lplpD3DRMViewport
Address that will be filled with a pointer to an IDirect3DRMViewport2 interface if the call succeeds.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. If the viewport size is larger than the physical device, returns D3DRMERR_BADVALUE. For a list of possible return codes, see Direct3D Retained Mode Return Values.

Remarks

The viewport displays objects in the scene that contains the camera, with the view direction and up vector taken from the camera. The viewport size cannot be larger than the physical device.

For more information about devices, see Output Devices and IDirect3DRMDevice3.

IDirect3DRM3::CreateWrap

IDirect3DRM3

Creates a wrapping function that can be used to assign texture coordinates to faces and meshes. The vector [ox oy oz] gives the origin of the wrap, [dx dy dz] gives its z-axis, and [ux uy uz] gives its y-axis. The 2-D vectors [ou ov] and [su sv] give an origin and scale factor in the texture applied to the result of the wrapping function.

Syntax

HRESULT CreateWrap(
  D3DRMWRAPTYPE type,
  LPDIRECT3DRMFRAME3 lpRef,
  D3DVALUE ox,
  D3DVALUE oy,
  D3DVALUE oz,
  D3DVALUE dx,
  D3DVALUE dy,
  D3DVALUE dz,
  D3DVALUE ux,
  D3DVALUE uy,
  D3DVALUE uz,
  D3DVALUE ou,
  D3DVALUE ov,
  D3DVALUE su,
  D3DVALUE sv,
  LPDIRECT3DRMWRAP* lplpD3DRMWrap
  );

Parameters

type
One of the members of the D3DRMWRAPTYPE enumerated type.
lpRef
Reference frame for the wrap.
ox, oy, and oz
Origin of the wrap.
dx, dy, and dz
The z-axis of the wrap.
ux, uy, and uz
The y-axis of the wrap.
ou and ov
Origin in the texture.
su and sv
Scale factor in the texture.
lplpD3DRMWrap
Address that will be filled with a pointer to an IDirect3DRMWrap interface if the call succeeds.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible return codes, see Direct3D Retained Mode Return Values.

See Also

IDirect3DRMWrap

IDirect3DRM3::EnumerateObjects

IDirect3DRM3

Uses the callback function specified by the func parameter on each of the active Direct3DRM objects.

Syntax

HRESULT EnumerateObjects(
  D3DRMOBJECTCALLBACK func,
  LPVOID lpArg
  );

Parameters

func
Application-defined D3DRMOBJECTCALLBACK callback function to be used with each Direct3DRMObject object and the application-defined argument.
lpArg
Address of application-defined data passed to the callback function.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible return codes, see Direct3D Retained Mode Return Values.

IDirect3DRM3::GetDevices

IDirect3DRM3

Returns all the Direct3DRM devices that have been created in the system.

Syntax

HRESULT GetDevices(
  LPDIRECT3DRMDEVICEARRAY* lplpDevArray
  );

Parameters

lplpDevArray
Address of a pointer that will be filled with the resulting array of Direct3DRM devices. For information about the Direct3DRMDeviceArray object, see the IDirect3DRMDeviceArray interface.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible return codes, see Direct3D Retained Mode Return Values.

IDirect3DRM3::GetNamedObject

IDirect3DRM3

Finds a Direct3DRMObject given the Direct3DRMObject name.

Syntax

HRESULT GetNamedObject(
  const char * lpName,
  LPDIRECT3DRMOBJECT* lplpD3DRMObject
  );

Parameters

lpName
Name of the object to be searched for.
lplpD3DRMObject
Address of a pointer to be initialized with a valid Direct3DRMObject pointer if the call succeeds.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible return codes, see Direct3D Retained Mode Return Values.

Remarks

If the system does not find an object with the name specified in the lpName parameter, this method returns D3DRM_OK but the lplpD3DRMObject parameter is NULL.

IDirect3DRM3::GetOptions

IDirect3DRM3

Retrieves whether Direct3D Retained Mode uses left-handed or right-handed geometry.

Syntax

HRESULT GetOptions(
  LPDWORD lpdwOptions);

Parameters

lpdwOptions
Pointer to a flag value that indicates the current Direct3D Retained Mode options. Currently defined flags are:
D3DRMOPTIONS_LEFTHANDED
Use left-handed geometry. This value is the default.
D3DRMOPTIONS_RIGHTHANDED
Use right-handed geometry.

Return Value

Returns one of the following values:
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DD_OK

Remarks

D3DRMOPTIONS_LEFTHANDED and D3DRMOPTIONS_RIGHTHANDED affect the following objects as well as picking and ray picking.

  • IDirect3DRMClippedVisual
  • IDirect3DRMMesh
  • IDirect3DRMMeshBuilder3
  • IDirect3DRMProgressiveMesh
  • IDirect3DRMShadow2
  • IDirect3DRMTexture3
  • IDirect3DRMViewport2

This method was introduced in DirectX version 6.0.

See Also

Direct3D Coordinate System

IDirect3DRM3::SetOptions

IDirect3DRM3::GetSearchPath

IDirect3DRM3

Returns the current search path. For Windows, the path is a list of directories separated by semicolons (;).

Syntax

HRESULT GetSearchPath(
  DWORD * lpdwSize,
  LPSTR lpszPath
  );

Parameters

lpdwSize
Pointer to a DWORD. Should contain the length of lpszPath when GetSearchPath is used. On return, contains the length of the string in lpszPath containing the current search path. This parameter cannot be NULL.
lpszPath
A pointer to a null-terminated string specifying the search path. If lpszPath equals NULL when GetSearchPath is used, the method returns the length of the current string in the location pointed to by the lpdwSize parameter.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible return codes, see Direct3D Retained Mode Return Values.

See Also

IDirect3DRM3::SetSearchPath

IDirect3DRM3::Load

IDirect3DRM3

Loads an object.

Syntax

HRESULT Load(
  LPVOID lpvObjSource,
  LPVOID lpvObjID,
  LPIID * lplpGUIDs,
  DWORD dwcGUIDs,
  D3DRMLOADOPTIONS d3drmLOFlags,
  D3DRMLOADCALLBACK d3drmLoadProc,
  LPVOID lpArgLP,
  D3DRMLOADTEXTURE3CALLBACK d3drmLoadTextureProc,
  LPVOID lpArgLTP,
  LPDIRECT3DRMFRAME3 lpParentFrame
  );

Parameters

lpvObjSource
Source for the object to be loaded. This source can be a file, resource, memory block, or stream, depending on the source flags specified in the d3drmLOFlags parameter.
lpvObjID
Object name or position to be loaded. The use of this parameter depends on the identifier flags specified in the d3drmLOFlags parameter. If the D3DRMLOAD_BYPOSITION flag is specified, this parameter is a pointer to a DWORD value that gives the object's order in the file. This parameter can be NULL.
lplpGUIDs
Address of an array of interface identifiers to be loaded. For example, if this parameter is a two-element array containing IID_IDirect3DRMMeshBuilder3 and IID_IDirect3DRMAnimationSet2, this method loads all the animation sets and mesh-builder objects. Possible GUIDs must be one or more of the following: IID_IDirect3DRMProgressiveMesh, IID_IDirect3DRMMeshBuilder3, IID_IDirect3DRMAnimationSet2, IID_IDirect3DRMAnimation2, and IID_IDirect3DRMFrame3.
dwcGUIDs
Number of elements specified in the lplpGUIDs parameter.
d3drmLOFlags
Value of the D3DRMLOADOPTIONS type describing the load options.
d3drmLoadProc
A D3DRMLOAD3CALLBACK callback function used when the system reads the specified object.
lpArgLP
Address of application-defined data passed to the D3DRMLOADCALLBACK callback function.
d3drmLoadTextureProc
A D3DRMLOADTEXTURE3CALLBACK callback function used to load any textures used by an object that require special formatting. This parameter can be NULL.
lpArgLTP
Address of application-defined data passed to the D3DRMLOADTEXTURE3CALLBACK callback function.
lpParentFrame
Address of a parent Direct3DRMFrame object. This argument only affects the loading of animation sets. When an animation that is loaded from an .x file references an unparented frame in the .x file, the unparented frame's parent is set to the parent frame at lpParentFrame. However, if you use Load to load any frames in the .x file, the parent frame at lpParentFrame will not be used as the parent frame for frames in the .x file with no parent. That is, lpParentFrame is used only when you load animation sets. This value of lpParentFrame can be NULL.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible return codes, see Direct3D Retained Mode Return Values.

Remarks

By default, perspective correction is on.

This method allows great flexibility in loading objects from Microsoft® DirectX® files. Here is an example of how to use it:

Sample Code

#include <windows.h>
#include <stdio.h>
#include <initguid.h>
#include <d3drm.h>

LPDIRECT3DRM d3dApi;

int totalMesh = 0, totalAnim = 0, totalFrames = 0;

HRESULT loadTexture(LPSTR name, LPVOID lpArg, LPDIRECT3DRMTEXTURE *tex)
{
    return d3dApi->lpVtbl->LoadTexture(d3dApi, name, tex);
}

void loadCallback(LPDIRECT3DRMOBJECT lpObject, REFIID objGuid, LPVOID lpArg)
{
    if (IsEqualIID(objGuid, &IID_IDirect3DRMFrame3)) {
        totalFrames ++;
        return;
    }

    if (IsEqualIID(objGuid, &IID_IDirect3DRMAnimationSet2)) {
        totalAnim ++;
        return;
    }

    if (IsEqualIID(objGuid, &IID_IDirect3DRMMeshBuilder)) {
        totalMesh ++;
        return;
    }

    return;
}

BOOL loadObjects(LPSTR filename)
{
    LPGUID guids[] = { (LPGUID)&IID_IDirect3DRMMeshBuilder,
        (LPGUID)&IID_IDirect3DRMAnimationSet2,
        (LPGUID)&IID_IDirect3DRMFrame3 };

    /* Tell the loader which objects you're interested in */

    if (FAILED(d3dApi->lpVtbl->Load(d3dApi, filename, NULL,
            guids, 3, D3DRMLOAD_FROMFILE,
            loadCallback, NULL, loadTexture, NULL, NULL)))
        return FALSE;

    printf("Total Frames loaded = %d\n", totalFrames);
    printf("Total Animation Sets loaded = %d\n", totalAnim);
    printf("Total Meshbuilders loaded = %d\n", totalMesh);

    return TRUE;
}

int main(int argc, char **argv)
{

    if (FAILED(Direct3DRMCreate(&d3dApi)))
        return FALSE;

    if (argc != 2) {
        fprintf(stderr, "usage: %s filename\n", argv[0]);
        return FALSE;
    }

    if (!loadObjects(argv[1])) return FALSE;

  return(0);
}

IDirect3DRM3::LoadTexture

IDirect3DRM3

Loads a Direct3DRMTexture2 texture from the specified file. This texture can have 8, 24, or 32 bits-per-pixel, and it should be in either the Windows bitmap (.bmp) or Portable Pixmap (.ppm) P6 format.

Syntax

HRESULT LoadTexture(
  const char * lpFileName,
  LPDIRECT3DRMTEXTURE3* lplpD3DRMTexture
  );

Parameters

lpFileName
Address of the name of the required .bmp or .ppm file.
lplpD3DRMTexture
Address of a pointer to be initialized with a valid IDirect3DRMTexture3 pointer if the call succeeds.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible return codes, see Direct3D Retained Mode Return Values.

Remarks

LoadTexture checks whether the texture is in BMP or PPM format, which are the formats it can load. If you want to load other formats, you can add code to the callback to load the image into a D3DRMIMAGE structure and then use IDirect3DRM3::CreateTexture.

If you write your own texture callback, the LoadTexture call in the texture callback does not take a reference to the texture. For example:

HRESULT loadTextures(char *name, void *arg, LPDIRECT3DRMTEXTURE2 *tex)
{
    return lpD3DRM2->LoadTexture(name, tex);
}

In this sample, no reference is taken for tex. If you want to keep a reference to each texture loaded by your texture callback, you should AddRef the texture. For example:

LPDIRECT3DRMTEXTURE2 *texarray;

HRESULT loadTextures(char *name, void *arg, LPDIRECT3DRMTEXTURE2 *tex)
{
    if (FAILED(lpD3DRM2->LoadTexture(name, tex)) {
        return NULL;
    }

    texArray[current++] = tex;
    tex->AddRef();

    return tex;
}

IDirect3DRM3::LoadTextureFromResource

IDirect3DRM3

Loads a Direct3DRMTexture2 texture from a specified resource.

Syntax

HRESULT LoadTextureFromResource(
  HMODULE hModule,
  LPCTSTR strName,
  LPCTSTR strType,
  LPDIRECT3DRMTEXTURE3 * lplpD3DRMTexture
  );

Parameters

hModule
Handle of the module whose executable file contains the resource.
strName
A null-terminated string specifying the name of the resource to be used as the texture.
strType
A null-terminated string specifying the type name of the resource. This parameter can be one of the following resource types or a user-defined type:
Value | Meaning
RT_BITMAP | Bitmap reource
RT_RCDATA | Application-defined resource (raw data)
lplpD3DRMTexture
Address of a pointer to be initialized with a valid IDirect3DRMTexture3 object if the call succeeds.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible return codes, see Direct3D Retained Mode Return Values.

IDirect3DRM3::RegisterClient

IDirect3DRM3

Registers a client (application) with which data can be associated.

Syntax

HRESULT RegisterClient(
  REFGUID rguid,
  LPDWORD lpdwID);

Parameters

rguid
Reference to a GUID that represents the application.
lpdwID
Address that receives a unique ID that the application can use with IDirect3DRMObject2::SetClientData and IDirect3DRMObject2::GetClientData to associate data with the Retained Mode object.

Return Value

Returns one of the following values:
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_OUTOFMEMORY
DD_OK

Remarks

The application passes a GUID and receives a DWORD identifier that can then be used with IDirect3DRMObject2::SetClientData and IDirect3DRMObject2::GetClientData to associate data with the Retained Mode object. When an application uses UnregisterClient, any data stored by the application by means of IDirect3DRMObject2::SetClientData is released in a manner dependent on its type. The same ID is returned for multiple invocations of this method with the same GUID. This method was introduced in DirectX version 6.0.

IDirect3DRM3::SetDefaultTextureColors

IDirect3DRM3

Sets the default colors to be used for a Direct3DRMTexture2 object.

Syntax

HRESULT SetDefaultTextureColors(
  DWORD dwColors
  );

Parameters

dwColors
Number of colors.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible return codes, see Direct3D Retained Mode Return Values.

Remarks

This method affects the texture colors only when it is used before the IDirect3DRM3::CreateTexture method; it has no effect on textures that have already been created.

IDirect3DRM3::SetDefaultTextureShades

IDirect3DRM3

Sets the default shades to be used for an Direct3DRMTexture2 object.

Syntax

HRESULT SetDefaultTextureShades(
  DWORD dwShades
  );

Parameters

dwShades
Number of shades.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible return codes, see Direct3D Retained Mode Return Values.

Remarks

This method affects the texture shades only when it is used before the IDirect3DRM3::CreateTexture method; it has no effect on textures that have already been created.

IDirect3DRM3::SetOptions

IDirect3DRM3

Sets whether Direct3D Retained Mode uses left-handed or right-handed geometry.

Syntax

HRESULT SetOptions(
  LPDWORD dwOptions);

Parameters

dwOptions
Flag value that indicates the current Direct3D Retained Mode options. Currently defined flags are:
D3DRMOPTIONS_LEFTHANDED
Use left-handed geometry. This value is the default.
D3DRMOPTIONS_RIGHTHANDED
Use right-handed geometry.

Return Value

Returns one of the following values:
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DD_OK

Remarks

D3DRMOPTIONS_LEFTHANDED and D3DRMOPTIONS_RIGHTHANDED affect the following objects as well as picking and ray picking.

  • IDirect3DRMClippedVisual
  • IDirect3DRMMesh
  • IDirect3DRMMeshBuilder3
  • IDirect3DRMProgressiveMesh
  • IDirect3DRMShadow2
  • IDirect3DRMTexture3
  • IDirect3DRMViewport2

This method was introduced in DirectX version 6.0.

See Also

Direct3D Coordinate System

IDirect3DRM3::GetOptions

IDirect3DRM3::SetSearchPath

IDirect3DRM3

Sets the current file search path from a list of directories. For Windows, the path should be a list of directories separated by semicolons (;).

Syntax

HRESULT SetSearchPath(
  LPCSTR lpPath
  );

Parameters

lpPath
Address of a null-terminated string specifying the path to set as the current search path.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible return codes, see Direct3D Retained Mode Return Values.

Remarks

The default search path is taken from the value of the D3DPATH environment variable. If this is not set, the search path will be empty. When opening a file, the system first looks for the file in the current working directory and then checks every directory in the search path.

D3DPATH is an environment variable that sets the default search path.

See Also

IDirect3DRM3::GetSearchPath

IDirect3DRM3::Tick

IDirect3DRM3

Performs the Direct3DRM system heartbeat. When this method is used, the positions of all moving frames are updated according to their current motion attributes, the scene is rendered to the current device, and relevant callback functions are used at their appropriate times. Control is returned when the rendering cycle is complete.

Syntax

HRESULT Tick(
  D3DVALUE d3dvalTick
  );

Parameters

d3dvalTick
Velocity and rotation step for the IDirect3DRMFrame3::SetRotation and IDirect3DRMFrame3::SetVelocity methods.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible return codes, see Direct3D Retained Mode Return Values.

Remarks

You can implement this method by using other Retained Mode methods to allow more flexibility in rendering a scene.

IDirect3DRM3::UnregisterClient

IDirect3DRM3

Disassociates all data and object associations set by IDirect3DRMObject2::SetClientData and frees the data in a manner dependent on its type.

Syntax

HRESULT UnregisterClient(
  REFGUID rguid);

Parameters

rguid
Reference to a GUID that represents the application.

Return Value

Returns one of the following values:
D3DRMERR_CLIENTNOTREGISTERED
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DD_OK

Remarks

This method was introduced with DirectX version 6.0.


IDirect3DRMAnimation2

Applications use the methods of the IDirect3DRMAnimation2 interface to animate the position, orientation, and scaling of visuals, lights, and viewports.

An animation in Retained Mode is defined by a set of keys. A key is a time value associated with a scaling operation, an orientation, or a position. A Direct3DRMAnimation object defines how a transformation is modified according to the time value. The animation can be set to operate on a Direct3DRMFrame object, so it could be used to animate the position, orientation, and scaling of Direct3DRMVisual, Direct3DRMLight, and Direct3DRMViewport objects.

The IDirect3DRMAnimation2::AddPositionKey, AddRotateKey, and AddScaleKey methods each specify a time value whose units are arbitrary. If an application adds a position key with a time value of 99, for example, a new position key with a time value of 49 would occur exactly halfway between the (zero-based) beginning of the animation and the first position key.

The animation is driven by calling the IDirect3DRMAnimation2::SetTime method. This sets the visual object's transformation to the interpolated position, orientation, and scale of the nearby keys in the animation. As with the methods that add animation keys, the time value for IDirect3DRMAnimation2::SetTime is an arbitrary value, based on the positions of keys the application has already added.

Microsoft DirectX version 6.0 introduces the IDirect3DRMAnimation2 interface. IDirect3DRMAnimation2 extends the older IDirect3DRMAnimation interface that it replaces by adding the AddKey, DeleteKeyByID, GetKeys, and ModifyKey methods that allow access to the keys of an animation. It also adds the GetFrame method that returns the frame of the corresponding animation. For a history of the Direct3D Retained Mode interfaces, see Interface Changes.

The methods of the IDirect3DRMAnimation2 interface can be organized into the following groups:

Keys | AddKey
AddPositionKey
AddRotateKey
AddScaleKey
DeleteKey
DeleteKeyByID
GetKeys
ModifyKey
Miscellaneous | GetFrame
SetFrame
SetTime
Options | GetOptions
SetOptions

The IDirect3DRMAnimation2 interface, like all Component Object Model (COM) interfaces, inherits the IUnknown interface methods. The IUnknown interface supports the following three methods:
AddRef
QueryInterface
Release

In addition, the IDirect3DRMAnimation2 interface inherits the following methods from the IDirect3DRMObject interface:
AddDestroyCallback
Clone
DeleteDestroyCallback
GetAppData
GetClassName
GetName
SetAppData
SetName

The Direct3DRMAnimation object is obtained by calling the IDirect3DRM3::CreateAnimation method.

IDirect3DRMAnimation2::AddKey

IDirect3DRMAnimation2

Adds a new key.

Syntax

HRESULT AddKey
(LPD3DRMANIMATIONKEY lpKey);

Parameters

lpKey
D3DRMANIMATIONKEY structure that defines a new key. The dwID member of the structure is ignored and is filled in with the ID of the new key upon return.

Return Value

Returns one of the following values:
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DD_OK

Remarks

This method was introduced with DirectX version 6.0.

IDirect3DRMAnimation2::AddPositionKey

IDirect3DRMAnimation2

Adds a position key to the animation.

Syntax

HRESULT AddPositionKey(
  D3DVALUE rvTime,
  D3DVALUE rvX,
  D3DVALUE rvY,
  D3DVALUE rvZ
  );

Parameters

rvTime
Time in the animation to store the position key. The time units are arbitrary and zero-based; a key whose rvTime value is 49 occurs exactly in the middle of an animation whose last key has an rvTime value of 99.
rvX, rvY, and rvZ
Position.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

Remarks

The transformation applied by this method is a translation. For information about the matrix mathematics involved in transformations, see 3-D Transformations.

See Also

IDirect3DRMAnimation2::DeleteKey

IDirect3DRMAnimation2::AddRotateKey

IDirect3DRMAnimation2

Adds a rotate key to the animation.

Syntax

HRESULT AddRotateKey(
  D3DVALUE rvTime,
  D3DRMQUATERNION *rqQuat
  );

Parameters

rvTime
Time in the animation to store the rotate key. The time units are arbitrary and zero-based; a key whose rvTime value is 49 occurs exactly in the middle of an animation whose last key has an rvTime value of 99.
rqQuat
Quaternion representing the rotation.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

Remarks

This method applies a rotation transformation. For information about the matrix mathematics involved in transformations, see 3-D Transformations.

See Also

IDirect3DRMAnimation2::DeleteKey

IDirect3DRMAnimation2::AddScaleKey

IDirect3DRMAnimation2

Adds a scale key to the animation.

Syntax

HRESULT AddScaleKey(
  D3DVALUE rvTime,
  D3DVALUE rvX,
  D3DVALUE rvY,
  D3DVALUE rvZ
  );

Parameters

rvTime
Time in the animation to store the scale key. The time units are arbitrary and zero-based; a key whose rvTime value is 49 occurs exactly in the middle of an animation whose last key has an rvTime value of 99.
rvX, rvY, and rvZ
Scale factor.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

Remarks

This method applies a scaling transformation. For information about the matrix mathematics involved in transformations, see 3-D Transformations.

See Also

IDirect3DRMAnimation2::DeleteKey

IDirect3DRMAnimation2::DeleteKey

IDirect3DRMAnimation2

Removes all the keys with the given time from an animation. For example, if an animation has a scale key with time t and a rotation key with time t then both keys will be deleted.

Syntax

HRESULT DeleteKey(
  D3DVALUE rvTime
  );

Parameters

rvTime
Time identifying the key that will be removed from the animation.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

IDirect3DRMAnimation2::DeleteKeyByID

IDirect3DRMAnimation2

Deletes the key corresponding to a particular ID.

Syntax

HRESULT DeleteKeyByID
(DWORD dwID);

Parameters

dwID
ID of the key to delete.

Return Value

Returns one of the following values:
D3DRMERR_NOSUCHKEY
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DD_OK

Remarks

This method was introduced with DirectX version 6.0.

IDirect3DRMAnimation2::GetFrame

IDirect3DRMAnimation2

Retrieves the frame corresponding to the animation.

Syntax

HRESULT GetFrame
(LPDIRECT3DRMFRAME3* lplpFrame);

Parameters

lplpFrame
Pointer to receive an interface of the current Direct3DRMFrame object that the animation references. This can be NULL.

Return Value

Returns one of the following values:
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DD_OK

Remarks

This method was introduced with DirectX version 6.0.

IDirect3DRMAnimation2::GetKeys

IDirect3DRMAnimation2

Retrieves the keys corresponding to a particular time.

Syntax

HRESULT GetKeys
(D3DVALUE dvTimeMin,
D3DVALUE dvTimeMax,
LPDWORD lpdwNumKeys,
LPD3DRMANIMATIONKEY lpKey);

Parameters

dvTimeMin
Minimum time value of keys to be returned.
dvTimeMax
Maximum time value of keys to be returned.
lpdwNumKeys
Pointer to a variable the contains the number of keys to be returned in lpKey. If lpKey is NULL, lpdwNumKeys is filled in with the number of keys at the specified time.
lpKey
Pointer to a D3DRMANIMATIONKEY structure that will be filled in with the key value. If lpKey is NULL, lpdwNumKeys will be filled in with the number of keys at the specified time. If lpKey is non-NULL, it will be filled in with the keys corresponding to the specified time up to a maximum number of keys indicated by lpdwNumKeys.

Return Value

Returns one of the following values:
D3DRMERR_NOSUCHKEY
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DD_OK

Remarks

This method was introduced with DirectX version 6.0.

IDirect3DRMAnimation2::GetOptions

IDirect3DRMAnimation2

Retrieves animation options.

Syntax

D3DRMANIMATIONOPTIONS GetOptions( );

Return Value

Returns the value of the D3DRMANIMATIONOPTIONS type describing the animation options.

See Also

IDirect3DRMAnimation2::SetOptions

IDirect3DRMAnimation2::ModifyKey

IDirect3DRMAnimation2

Modifies the value of a key.

Syntax

HRESULT Modify
(LPD3DRMANIMATIONKEY lpKey);

Parameters

lpKey
D3DRMANIMATIONKEY structure that defines an existing key's value. The dwID member of the structure must be an existing key.

Return Value

Returns one of the following values:
D3DRMERR_INCOMPATIBLEKEY
D3DRMERR_NOSUCHKEY
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DD_OK

Remarks

This method was introduced with DirectX version 6.0.

You cannot modify a key's type. To change a key's type you must delete the original key and then add a new key. You can modify a key's time and position, rotation, and scale values.

IDirect3DRMAnimation2::SetFrame

IDirect3DRMAnimation2

Sets the frame for the animation.

Syntax

HRESULT SetFrame(
  LPDIRECT3DRMFRAME3 lpD3DRMFrame
  );

Parameters

lpD3DRMFrame
Address of a variable representing the frame to set for the animation.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

IDirect3DRMAnimation2::SetOptions

IDirect3DRMAnimation2

Sets the animation options.

Syntax

HRESULT SetOptions(
  D3DRMANIMATIONOPTIONS d3drmanimFlags
  );

Parameters

d3drmanimFlags
Value of the D3DRMANIMATIONOPTIONS type describing the animation options.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

See Also

IDirect3DRMAnimation2::GetOptions

IDirect3DRMAnimation2::SetTime

IDirect3DRMAnimation2

Sets the current time for this animation.

Syntax

HRESULT SetTime(
  D3DVALUE rvTime
  );

Parameters

rvTime
New current time for the animation. The time units are arbitrary and zero-based; a key whose rvTime value is 49 occurs exactly in the middle of an animation whose last key has an rvTime value of 99.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.


IDirect3DRMAnimationArray

The IDirect3DRMAnimationArray interface enables you to retrieve the number of animations in the array and request the interface for an animation.

This interface supports the GetElement and GetSize methods.

The IDirect3DRMAnimationArray interface, like all Component Object Model (COM) interfaces, inherits the IUnknown interface methods. This interface supports the following three methods.
AddRef
QueryInterface
Release

IDirect3DRMAnimationArray::GetElement

IDirect3DRMAnimationArray

Retrieves an interface for the requested animation.

Syntax

DWORD GetElement(
  DWORD dwIndex,
  LPDIRECT3DRMANIMATION2 &lplpDirect3DRMAnimation);

Parameters

dwIndex
Index in the array of the animation to be retrieved.
lplpDirect3DRMAnimation
Pointer to the Direct3DRMAnimation object.

Return Value

Returns one of the following values:
DDERR_INVALIDPARAMS
DD_OK

Remarks

This method was introduced with DirectX version 6.0.

IDirect3DRMAnimationArray::GetSize

IDirect3DRMAnimationArray

Retrieves the number of animations in the array.

Syntax

DWORD GetSize();

Return Value

Number of animations.

Remarks

This method was introduced with DirectX version 6.0.


IDirect3DRMAnimationSet2

Applications use the methods of the IDirect3DRMAnimationSet2 interface to group Direct3DRMAnimation objects together, which can simplify the playback of complex animation sequences.

A Direct3DRMAnimationSet object allows Direct3DRMAnimation objects to be grouped together. This allows all the animations in an animation set to share the same time parameter, simplifying the playback of complex articulated animation sequences. An application can add an animation to an animation set by using the IDirect3DRMAnimationSet2::AddAnimation method, and it can remove one by using the IDirect3DRMAnimationSet2::DeleteAnimation method. Animation sets are driven by calling the IDirect3DRMAnimationSet2::SetTime method.

Microsoft DirectX version 6.0 introduces the IDirect3DRMAnimationSet2 interface. IDirect3DRMAnimationSet2 extends the older IDirect3DRMAnimationSet interface that it replaces by adding the GetAnimations method that allows you to retrieve the constituent animations. For a history of the Direct3D Retained Mode interfaces, see Interface Changes.

The methods of the IDirect3DRMAnimationSet2 interface can be organized into the following groups:

Adding, removing, retrieving, and loading | AddAnimation
DeleteAnimation
GetAnimations
Load
Time | SetTime

The IDirect3DRMAnimationSet2 interface, like all Component Object Model (COM) interfaces, inherits the IUnknown interface methods. The IUnknown interface supports the following three methods:
AddRef
QueryInterface
Release

In addition, the IDirect3DRMAnimationSet2 interface inherits the following methods from the IDirect3DRMObject interface:
AddDestroyCallback
Clone
DeleteDestroyCallback
GetAppData
GetClassName
GetName
SetAppData
SetName

The Direct3DRMAnimationSet object is obtained by calling the IDirect3DRM3::CreateAnimationSet method.

IDirect3DRMAnimationSet2::AddAnimation

IDirect3DRMAnimationSet2

Adds an animation to the animation set.

Syntax

HRESULT AddAnimation(
  LPDIRECT3DRMANIMATION2 lpD3DRMAnimation
  );

Parameters

lpD3DRMAnimation
Address of the Direct3DRMAnimation object to be added to the animation set.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible return codes, see Direct3D Retained Mode Return Values.

IDirect3DRMAnimationSet2::DeleteAnimation

IDirect3DRMAnimationSet2

Removes a previously added animation from the animation set.

Syntax

HRESULT DeleteAnimation(
  LPDIRECT3DRMANIMATION2 lpD3DRMAnimation
  );

Parameters

lpD3DRMAnimation
Address of the Direct3DRMAnimation object to be removed from the animation set.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible return codes, see Direct3D Retained Mode Return Values.

IDirect3DRMAnimationSet2::GetAnimations

IDirect3DRMAnimationSet2

Retrieves an array containing the animations in the animation set.

Syntax

HRESULT GetAnimations
(LPDIRECT3DRMANIMATIONARRAY* lplpArray);

Parameters

lplpArray
Array that receives a pointer to the corresponding Direct3DRMAnimationArray object.

Return Value

Returns one of the following values.

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DD_OK

Remarks

This method was introduced with DirectX version 6.0.

IDirect3DRMAnimationSet2::Load

IDirect3DRMAnimationSet2

Loads an animation set.

Syntax

HRESULT Load(
  LPVOID lpvObjSource,
  LPVOID lpvObjID,
  D3DRMLOADOPTIONS d3drmLOFlags,
  D3DRMLOADTEXTURE3CALLBACK d3drmLoadTextureProc,
  LPVOID lpArgLTP,
  LPDIRECT3DRMFRAME3 lpParentFrame
  );

Parameters

lpvObjSource
Source for the object to be loaded. This source can be a file, resource, memory block, or stream, depending on the source flags specified in the d3drmLOFlags parameter.
lpvObjID
Object name or position to be loaded. The use of this parameter depends on the identifier flags specified in the d3drmLOFlags parameter. If the D3DRMLOAD_BYPOSITION flag is specified, this parameter is a pointer to a DWORD value that gives the object's order in the file. This parameter can be NULL.
d3drmLOFlags
Value of the D3DRMLOADOPTIONS type describing the load options.
d3drmLoadTextureProc
D3DRMLOADTEXTURE3CALLBACK callback function used to load any textures used by the object that require special formatting. This parameter can be NULL.
lpArgLTP
Address of application-defined data passed to the D3DRMLOADTEXTURE3CALLBACK callback function.
lpParentFrame
Address of a parent Direct3DRMFrame object. This argument only affects the loading of animation sets. When an animation that is loaded from an .x file references an unparented frame in the .x file, the frame's parent is set to this parent frame argument. However, if you use Load to load any frames in the .x file, the parent frame argument will not be used as the parent frame for frames in the .x file with no parent. That is, the parent frame argument is used only when you load animation sets. The value of this argument can be NULL.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible return codes, see Direct3D Retained Mode Return Values.

Remarks

By default, this method loads the first animation set in the file specified by the lpvObjSource parameter. By default, perspective correction is on.

IDirect3DRMAnimationSet2::SetTime

IDirect3DRMAnimationSet2

Sets the time for this animation set.

Syntax

HRESULT SetTime(
  D3DVALUE rvTime
  );

Parameters

rvTime
New time.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible return codes, see Direct3D Retained Mode Return Values.


IDirect3DRMArray

The IDirect3DRMArray interface organizes groups of objects. Applications typically use the particular array interface they need (for example, IDirect3DRMFaceArray), rather than using this interface directly.

The IDirect3DRMArray interface supports the GetSize method.

The IDirect3DRMArray interface, like all Component Object Model (COM) interfaces, inherits the IUnknown interface methods. This interface supports the following three methods:
AddRef
QueryInterface
Release

IDirect3DRMArray::GetSize

IDirect3DRMArray

Retrieves the size, in number of objects, of the Direct3DRMArray object.

Syntax

DWORD GetSize( );

Return Value

Returns the size.


IDirect3DRMClippedVisual

Microsoft® DirectX® version 6.0 introduces the IDirect3DRMClippedVisual interface. This interface allows applications to clip visual objects against arbitrary planes, specified in world space, before rendering. You create a clipped visual from another visual in much the same way you create a shadow from another visual. For example, you can create a clipped visual from a sphere and pass a clipping plane straight through the middle of the sphere to have only half of the sphere render. Create clipped visual objects by calling the IDirect3DRM3::CreateClippedVisual method. Then add the clipped visual to the scene by using the IDirect3DRMFrame3::AddVisual method.

IDirect3DRMClippedVisual inherits from IDirect3DRMVisual, as the other visual interfaces do. When the reference frame moves, the clipping plane does not move (see the AddPlane method for more information).

For a history of the Microsoft Direct3D® Retained Mode interfaces, see Interface Changes.

The methods of the IDirect3DRMClippedVisual interface can be organized into the following groups.
Initialization | Init
Planes | AddPlane
DeletePlane
GetPlane
GetPlaneIDs
SetPlane

The IDirect3DRMClippedVisual interface, like all COM interfaces, inherits the IUnknown interface methods. The IUnknown interface supports the following three methods.
AddRef
QueryInterface
Release

In addition, the IDirect3DRMClippedVisual interface inherits the following methods from the IDirect3DRMObject interface.
AddDestroyCallback
Clone
DeleteDestroyCallback
GetAppData
GetClassName
GetName
SetAppData
SetName

You can create an Direct3DRMClippedVisual object by using the IDirect3DRM3 interface.

IDirect3DRMClippedVisual::AddPlane

IDirect3DRMClippedVisual

Adds a clipping plane.

Syntax

HRESULT AddPlane(
  LPDIRECT3DRMFRAME3 lpRef,
  LPD3DVECTOR lpdvPoint,
  LPD3DVECTOR lpdvNormal,
  DWORD dwFlags,
  LPDWORD lpdwReturnID);

Parameters

lpRef
Reference frame for the point and normal paramters.
lpdvPoint
Point on the plane relative to the reference frame.
lpdvNormal
Vector normal to the plane relative to the reference frame.
dwFlags
Unused flags. Must be zero.
lpdwReturnID
Pointer that receives a unique ID number for the plane on successful return.

Return Value

Returns DD_OK or DDERR_INVALIDPARAMS.

Remarks

Clipping planes are stored internally as world coordinates. When the reference frame moves, the clipping plane does not move. Use the SetPlane method to update the position and orientation of the clipping plane, as needed.

This method was introduced with DirectX version 6.0.

IDirect3DRMClippedVisual::DeletePlane

IDirect3DRMClippedVisual

Deletes a clipping plane.

Syntax

HRESULT DeletePlane(
  DWORD dwID,
  DWORD dwFlags);

Parameters

dwID
ID number of the plane to delete.
dwFlags
Unused flags.

Return Value

Returns DD_OK if successful.

Remarks

This method was introduced with DirectX version 6.0.

IDirect3DRMClippedVisual::GetPlane

IDirect3DRMClippedVisual

Retrieves information about a clipping plane.

Syntax

HRESULT GetPlane(
  DWORD dwID,
  LPDIRECT3DRMFRAME3 lpRef,
  LPD3DVECTOR lpdvPoint,
  LPD3DVECTOR lpdvNormal,
  DWORD dwFlags);

Parameters

lpRef
Reference frame for this operation.
dwID
ID of the plane.
lpdvPoint
Pointer that receives a point on the plane relative to the reference frame on successful return.
lpdvNormal
Pointer that receives a vector normal to the plane, relative to the reference frame on successful return.
dwFlags
Unused flags. Must be zero.

Return Value

Returns DD_OK or DDERR_INVALIDPARAMS.

Remarks

This method was introduced with DirectX version 6.0.

IDirect3DRMClippedVisual::GetPlaneIDs

IDirect3DRMClippedVisual

Retrieves an array of IDs.

Syntax

HRESULT GetPlanes(
  LPDWORD lpdwCount,
  LPDWORD lpdwID,
  DWORD dwFlags);

Parameters

lpdwCount
Pointer that receives the number of planes on successful return.
lpdwID
Addresss of a buffer large enough to contain an array of all the plane ID numbers. On successful return, contains the IDs of the planes. If NULL, only the number of planes is returned.
dwFlags
Unused flags. Must be zero.

Return Value

Returns DD_OK or DDERR_INVALIDPARAMS.

Remarks

This method was introduced with DirectX version 6.0.

IDirect3DRMClippedVisual::Init

IDirect3DRMClippedVisual

Initializes the clipped visual.

Syntax

HRESULT Init(
  LPDIRECT3DRMVISUAL lpD3DRMVisual);

Parameters

lpD3DRMVisual
Visual that is to be clipped and rendered.

Return Value

Returns DD_OK if successful.

Remarks

This method was introduced with DirectX version 6.0.

IDirect3DRMClippedVisual::SetPlane

IDirect3DRMClippedVisual

Changes the parameters of a clipping plane that has already been added.

Syntax

HRESULT SetPlane(
  DWORD dwID,
  LPDIRECT3DRMFRAME3 lpRef,
  LPD3DVECTOR lpdvPoint,
  LPD3DVECTOR lpdvNormal,
  DWORD dwFlags);

Parameters

dwID
ID number of the plane to be changed.
lpRef
The reference frame for the point and normal paramters. If this parameter is NULL, lpdvPoint and lpdvNormal are in world space.
lpdvPoint
Point on the plane relative to the reference frame.
lpdvNormal
Vector normal to the plane, relative to the reference frame.
dwFlags
Flag value. Must be zero.
lpdwReturnID
Pointer that receives a unique ID number for the plane on successful return.

Return Value

Returns DD_OK or DDERR_INVALIDPARAMS.

Remarks

This method was introduced with DirectX version 6.0.


IDirect3DRMDevice3

Applications use the IDirect3DRMDevice3, IDirect3DRMDevice2, and IDirect3DRMDevice interfaces to interact with the output device. For a conceptual overview, see Output Devices.

IDirect3DRMDevice3 contains all the methods in the older IDirect3DRMDevice2 and IDirect3DRMDevice interfaces, but adds the FindPreferredTextureFormat method to select a texture format based on certain criteria and also adds four methods that eliminate redundant state changes (setting a state to a value equal to its current value): GetStateChangeOptions, LightStateChange, RenderStateChange, and SetStateChangeOptions.

IDirect3DRMDevice2 contains all the methods in IDirect3DRMDevice, plus: two additional methods that enable you to control transparency, GetRenderMode and SetRenderMode; one additional initialization method, InitFromSurface; and two changed methods, GetDirect3DDevice2 and InitFromD3D2, which get and initialize an IDirect3DRMDevice2 object rather than an IDirect3DRMDevice object.

When you create the IDirect3DRMDevice3 or IDirect3DRMDevice2 interface from the IDirect3DRM3 or IDirect3DRM2 interface, respectively, or initialize either interface using its respective InitFromClipper, InitFromD3D2, or InitFromSurface IDirect3DRMDevice3 methods, the interface works with an IDirect3DDevice3 or IDirect3DDevice2 Immediate Mode device, respectively. The IDirect3DDevice3 and IDirect3DDevice2 devices support the DrawPrimitive interface, as well as execute buffers, and are required for progressive meshes, for alpha blending and sorting of transparent objects. When you create the old IDirect3DRMDevice interface from the IDirect3DRM interface, the IDirect3DRMDevice Retained Mode interface works with an IDirect3DDevice Immediate Mode device.

The InitFromClipper and InitFromSurface methods use the IDirect3DRM3::CreateDevice method to create a Direct3DRMDevice3 object.

The InitFromD3D2 method uses an IDirect3D2 Immediate Mode object and an IDirect3DDevice2 Immediate Mode device to initialize an IDirect3DDevice2 Direct3D Retained Mode device.

You can still query between the IDirect3DRMDevice3, IDirect3DRMDevice2, and IDirect3DRMDevice interfaces. The main difference is in how the underlying Immediate Mode device is created.

The methods of the IDirect3DRMDevice3 interface can be organized into the following groups:
Buffer counts | GetBufferCount
SetBufferCount
Color models | GetColorModel
Dithering | GetDither
SetDither
Eliminating Redundant State Changes | GetStateChangeOptions
LightStateChange
RenderStateChange
SetStateChangeOptions
Initialization | Init
InitFromClipper
InitFromD3D2
InitFromSurface
Miscellaneous | GetDirect3DDevice2
GetHeight
GetTrianglesDrawn
GetViewports
GetWidth
GetWireframeOptions
Update
Notifications | AddUpdateCallback
DeleteUpdateCallback
Rendering quality | GetQuality
SetQuality
Shading | GetShades
SetShades
Textures | FindPreferredTextureFormat
GetTextureQuality
SetTextureQuality
Transparency | GetRenderMode
SetRenderMode

The IDirect3DRMDevice3 interface, like all Component Object Model (COM) interfaces, inherits the IUnknown interface methods. The IUnknown interface supports the following three methods:
AddRef
QueryInterface
Release

In addition, the IDirect3DRMDevice3 interface inherits the following methods from the IDirect3DRMObject interface:
AddDestroyCallback
Clone
DeleteDestroyCallback
GetAppData
GetClassName
GetName
SetAppData
SetName

The Direct3DRMDevice3 object is obtained by calling the IDirect3DRM3::CreateDevice method.

IDirect3DRMDevice3::AddUpdateCallback

IDirect3DRMDevice3

Adds a callback function that alerts the application when a change occurs to the device. The system uses this callback function when the application uses the IDirect3DRMDevice3::Update method.

Syntax

HRESULT AddUpdateCallback(
  D3DRMDEVICE3UPDATECALLBACK d3drmUpdateProc,
  LPVOID arg
  );

Parameters

d3drmUpdateProc
Pointer to an application-defined callback function, D3DRMDEVICE3UPDATECALLBACK.
arg
Pointer to private data to be passed to the update callback function.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible return values, see Direct3D Retained Mode Return Values.

Remarks

IDirect3DRMDevice2::AddUpdateCallback and IDirect3DRMDevice::AddUpdateCallback take a D3DRMUPDATECALLBACK type callback for the d3drmUpdateProc parameter. With DirectX version 6.0, IDirect3DRMDevice3 introduced the newer D3DRMDEVICE3UPDATECALLBACK callback.

See Also

IDirect3DRMDevice3::DeleteUpdateCallback, IDirect3DRMDevice3::Update, D3DRMDEVICE3UPDATECALLBACK

IDirect3DRMDevice3::DeleteUpdateCallback

IDirect3DRMDevice3

Removes an update callback function that was added by using the IDirect3DRMDevice3::AddUpdateCallback method.

Syntax

HRESULT DeleteUpdateCallback(
  D3DRMDEVICE3UPDATECALLBACK d3drmUpdateProc,
  LPVOID arg
  );

Parameters

d3drmUpdateProc
Pointer to an application-defined callback function, D3DRMDEVICE3UPDATECALLBACK.
arg
Pointer to private data that was passed to the update callback function.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible return values, see Direct3D Retained Mode Return Values.

Remarks

IDirect3DRMDevice2::DeleteUpdateCallback and IDirect3DRMDevice::DeleteUpdateCallback take a D3DRMUPDATECALLBACK type callback for the d3drmUpdateProc parameter. With DirectX version 6.0, IDirect3DRMDevice3 introduced the newer D3DRMDEVICE3UPDATECALLBACK callback.

See Also

IDirect3DRMDevice3::AddUpdateCallback, IDirect3DRMDevice3::Update, D3DRMDEVICE3UPDATECALLBACK

IDirect3DRMDevice3::FindPreferredTextureFormat

IDirect3DRMDevice3

Finds a texture format that meets the user criteria and that the underlying Immediate Mode device supports. For optimal performance of the texture cache, use this function to choose the pixel format of texture surfaces.

Syntax

HRESULT FindPreferredTextureFormat(
  DWORD dwBitDepths,
  DWORD dwFlags,
  LPDDPIXELFORMAT  lpDDPF);

Parameters

dwBitDepths
Requested texture format bit depth. Specify zero to indicate that any bit depth is acceptable. Specify other values, using a logical combination of one or more of the following DirectDraw bit-depth flags.
DDBD_4
DDBD_8
DDBD_16
DDBD_24
DDBD_32
dwFlags
Flags that specify additional requirements. Specify zero to use the default preferences. Other valid values must be a logical combination of one or more of the following values.
D3DRMFPTF_ALPHA
The returned texture format must have an alpha channel.
D3DRMFPTF_NOALPHA
The returned texture format must not have an alpha channel. Omit both the D3DRMFPTF_ALPHA and D3DRMFPTF_NOALPHA flags to indicate that the absence of an alpha channel is preferred, but not required.
D3DRMFPTF_PALETTIZED
The returned texture format must be palettized.
D3DRMFPTF_NOTPALETTIZED
The returned texture format must not be palettized. Omit both the D3DRMFPTF_PALETTIZED and D3DRMFPTF_NOTPALETTIZED flags to indicate that the absence of a palette is preferred, but not required.
lpDDPF
Pointer to receive the texture format.

Return Value

Returns one of the following values.
D3DRMERR_TEXTUREFORMATNOTFOUND
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DD_OK

FindPreferredTextureFormat returns D3DRMERR_TEXTUREFORMATNOTFOUND if the does not find an acceptable format.

Remarks

This method was introduced with DirectX version 6.0.

IDirect3DRMDevice3::GetBufferCount

IDirect3DRMDevice3

Retrieves the value set in a call to the IDirect3DRMDevice3::SetBufferCount method.

Syntax

DWORD GetBufferCount( );

Return Value

Returns the number of buffers—one for single-buffering, two for double-buffering, and so on.

IDirect3DRMDevice3::GetColorModel

IDirect3DRMDevice3

Retrieves the color model of a device.

Syntax

D3DCOLORMODEL GetColorModel( );

Return Value

Returns a value from the D3DCOLORMODEL enumerated type that describes the Direct3D color model (RGB or monochrome).

See Also

Color Models

IDirect3DRMDevice3::GetDirect3DDevice2

IDirect3DRMDevice3

Retrieves a pointer to an IDirect3DDevice2 Immediate Mode device.

Syntax

HRESULT GetDirect3DDevice2(
  LPDIRECT3DDEVICE2 * lplpD3DDevice
  );

Parameters

lplpD3DDevice
Address of a pointer that is initialized with a pointer to an IDirect3DDevice2 Immediate Mode device object.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible return codes, see Direct3D Retained Mode Return Values.

Remarks

The IDirect3DDevice2 device will support the DrawPrimitive interface and execute buffers and is required for progressive meshes and for alpha blending and sorting of transparent objects.

IDirect3DRMDevice3::GetDither

IDirect3DRMDevice3

Retrieves the dither flag for the device.

Syntax

BOOL GetDither( );

Return Value

Returns TRUE if the dither flag is set, or FALSE otherwise.

See Also

IDirect3DRMDevice3::SetDither

IDirect3DRMDevice3::GetHeight

IDirect3DRMDevice3

Retrieves the height, in pixels, of a device. This method is a convenience function.

Syntax

DWORD GetHeight( );

Return Value

Returns the height.

IDirect3DRMDevice3::GetQuality

IDirect3DRMDevice3

Retrieves the rendering quality for the device.

Syntax

D3DRMRENDERQUALITY GetQuality( );

Return Value

Returns one or more of the members of the enumerated types represented by the D3DRMRENDERQUALITY enumerated type.

See Also

IDirect3DRMDevice3::SetQuality

IDirect3DRMDevice3::GetRenderMode

IDirect3DRMDevice3

Retrieves the current transparency flags.

Syntax

DWORD GetRenderMode( );

Return Value

Returns the value of the current transparency flags.

Remarks

Transparency flags have the following values.
Flag | Value
No flag set (default) | 0
D3DRMRENDERMODE_BLENDEDTRANSPARENCY | 1
D3DRMRENDERMODE_DISABLESORTEDALPHAZWRITE | 32
D3DRMRENDERMODE_LIGHTINMODELSPACE | 8
D3DRMRENDERMODE_SORTEDTRANSPARENCY | 2
D3DRMRENDERMODE_VIEWDEPENDENTSPECULAR | 16

See Also

IDirect3DRMDevice3::SetRenderMode

IDirect3DRMDevice3::GetShades

IDirect3DRMDevice3

Retrieves the number of shades in a ramp of colors used for shading in the monochromatic (or ramp) model.

Syntax

DWORD GetShades( );

Return Value

Returns the number of shades.

See Also

IDirect3DRMDevice3::SetShades

IDirect3DRMDevice3::GetStateChangeOptions

IDirect3DRMDevice3

Retrieves the state change options flags associated with a render or light state. See Eliminating Redundant State Changes for more details.

Syntax

HRESULT GetStateChangeOptions(
  DWORD dwStateClass,
  DWORD dwStateNum,
  LPDWORD pdwFlags
  );

Parameters

dwStateClass
Class of states to which this state belongs. The value can be D3DRMSTATECHANGE_LIGHT or D3DRMSTATECHANGE_RENDER.
dwStateNum
Appropriate D3DRENDERSTATE or D3DLIGHTSTATE number. A zero value indicates that all states of the given class should be affected.
pdwFlags
Pointer to the options flags. Contains one of the following values:
D3DRMSTATECHANGE_NONVOLATILE
D3DRMSTATECHANGE_VOLATILE

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible return codes, see Direct3D Retained Mode Return Values.

Remarks

This method was introduced with DirectX version 6.0.

The following example code gets the options on the texture handle render state.

lpDirect3DRMDev3->GetStateChangeOptions(D3DRMSTATECHANGE_RENDER,
                          D3DRENDERSTATE_TEXTUREHANDLE, &dwFlags);

See Also

IDirect3DRMDevice3::SetStateChangeOptions

IDirect3DRMDevice3::GetTextureQuality

IDirect3DRMDevice3

Retrieves the current texture quality parameter for the device. Texture quality is relevant only for an RGB device.

Syntax

D3DRMTEXTUREQUALITY GetTextureQuality( );

Return Value

Returns one of the members of the D3DRMTEXTUREQUALITY enumerated type.

See Also

IDirect3DRMDevice3::SetTextureQuality

IDirect3DRMDevice3::GetTrianglesDrawn

IDirect3DRMDevice3

Retrieves the number of triangles drawn to a device since its creation. This method is a convenience function.

Syntax

DWORD GetTrianglesDrawn( );

Return Value

Returns the number of triangles.

Remarks

The number of triangles includes those that were passed to the renderer but were not drawn because they were backfacing (facing away from the camera). The number does not include triangles that were rejected for lying outside of the viewing frustum.

IDirect3DRMDevice3::GetViewports

IDirect3DRMDevice3

Constructs a Direct3DRMViewportArray object that represents the viewports currently constructed from the device.

Syntax

HRESULT GetViewports(
  LPDIRECT3DRMVIEWPORTARRAY* lplpViewports
  );

Parameters

lplpViewports
Address of a pointer that is initialized with a valid Direct3DRMViewportArray object if the call succeeds.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible return codes, see Direct3D Retained Mode Return Values.

IDirect3DRMDevice3::GetWidth

IDirect3DRMDevice3

Retrieves the width, in pixels, of a device. This method is a convenience function.

Syntax

DWORD GetWidth( );

Return Value

Returns the width of the device, in pixels.

IDirect3DRMDevice3::GetWireframeOptions

IDirect3DRMDevice3

Retrieves the wire-frame options of a given device.

Syntax

DWORD GetWireframeOptions( );

Return Value

Returns a bitwise or one of the following values.

D3DRMWIREFRAME_CULL
The backfacing faces are not drawn.
D3DRMWIREFRAME_HIDDENLINE
Wire-frame-rendered lines are obscured by nearer objects.

IDirect3DRMDevice3::Init

IDirect3DRMDevice3

Not implemented on the Microsoft® Windows® platform.

Syntax

HRESULT Init(
  ULONG width,
  ULONG height
  );

IDirect3DRMDevice3::InitFromClipper

IDirect3DRMDevice3

Initializes an IDirect3DDevice2 device from a specified DirectDrawClipper object using IDirect3DRM3::CreateDevice.

Syntax

HRESULT InitFromClipper(
  LPDIRECTDRAWCLIPPER lpDDClipper,
  LPGUID lpGUID,
  int width,
  int height
  );

Parameters

lpDDClipper
Pointer to the DirectDrawClipper object to use as an initializer.
lpGUID
Direct3D device driver to use.
width and height
Width and height of the device in pixels.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible return codes, see Direct3D Retained Mode Return Values.

IDirect3DRMDevice3::InitFromD3D2

IDirect3DRMDevice3

Initializes an IDirect3DRMDevice2 Retained Mode device from an IDirect3D2 Immediate Mode object and an IDirect3DDevice2 Immediate Mode device.

Syntax

HRESULT InitFromD3D2(
  LPDIRECT3D2 lpD3D,
  LPDIRECT3DDEVICE2 lpD3DIMDev
  );

Parameters

lpD3D
Pointer to the IDirect3D2 Immediate Mode object to use to initialize the Retained Mode device.
lpD3DIMDev
Pointer to the IDirect3DDevice2 Immediate Mode device to use to initialize the Retained Mode device.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible return codes, see Direct3D Retained Mode Return Values.

Remarks

The IDirect3DRMDevice2 device initialized from IDirect3DDevice2 will support the DrawPrimitive interface and execute buffers and is required for progressive meshes and for alpha blending and sorting of transparent objects.

IDirect3DRMDevice3::InitFromSurface

IDirect3DRMDevice3

Initializes a IDirect3DDevice2 device from a specified DirectDraw surface, using the IDirect3DRM3::CreateDevice method.

Syntax

HRESULT InitFromSurface(
  LPGUID lpGUID,
  LPDIRECTDRAW lpDD,
  LPDIRECTDRAWSURFACE lpDDSBack
  );

Parameters

lpGUID
Pointer to the globally unique identifier (GUID) that identifies the Direct3D device driver to use.
lpDD
Pointer to the interface of a DirectDraw object that created the DirectDrawSurface.
lpDDSBack
Pointer to the interface of a DirectDrawSurface back buffer onto which the device will render.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible return codes, see Direct3D Retained Mode Return Values.

Remarks

The IDirect3DRMDevice2 device initialized will support the DrawPrimitive methods and execute buffers, and is required for progressive meshes and for alpha blending and sorting of transparent objects.

IDirect3DRMDevice3::LightStateChange

IDirect3DRMDevice3

Changes a light state or informs Direct3D Retained Mode of a change to a render state. If the D3DRMSTATECHANGE_NONVOLATILE flag is associated with the render state, Retained Mode eliminates redundant changes to the state made by using IDirect3DRMDevice3 (it won't set the state to a value equal to its current value). See Eliminating Redundant State Changes for more details.

Syntax

HRESULT LightStateChange(
  DWORD dwStateNum,
  DWORD dwVal,
  DWORD dwFlags
  );

Parameters

dwStateNum
Appropriate D3DLIGHTSTATE number.
dwVal
New value of the state.
dwFlags
Flag that indicates whether Retained Mode should update the cache only. If this flag is set to D3DRMSTATECHANGE_UPDATEONLY, only the value held in the internal cache is updated. You can use D3DRMSTATECHANGE_UPDATEONLY to indicate a state change.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible return codes, see Direct3D Retained Mode Return Values.

Remarks

This method was introduced with DirectX version 6.0.

The following code sets the material handle light state, eliminating redundant changes if the D3DRMSTATECHANGE_NONVOLATILE flag has been associated with the state.

lpDirect3DRMDev3->LightStateChange(D3DLIGHTSTATE_MATERIAL, hMat, 0);

The following indicates a change to the fog mode.

lpDirect3DRMDev3->LightStateChange(D3DLIGHTSTATE_FOGMODE, D3DFOG_NONE,
                                   D3DRMSTATECHANGE_UPDATEONLY);

See Also

IDirect3DRMDevice3::SetStateChangeOptions

IDirect3DRMDevice3::RenderStateChange

IDirect3DRMDevice3

Changes a render state or indicates a change to a render state. If the D3DRMSTATECHANGE_NONVOLATILE flag is associated with the render state, Retained Mode eliminates redundant changes to the state made by using IDirect3DRMDevice3 (it won't set the state to a value equal to its current value). See Eliminating Redundant State Changes for more details.

Syntax

HRESULT RenderStateChange(
  DWORD dwStateNum,
  DWORD dwVal,
  DWORD dwFlags
  );

Parameters

dwStateNum
Appropriate D3DRENDERSTATE number.
dwVal
New value of the state.
dwFlags
Flag that indicates whether to update the cache only. If this flag is set to D3DRMSTATECHANGE_UPDATEONLY, only the value held in the internal cache is updated. You can use D3DRMSTATECHANGE_UPDATEONLY to indicate a change made to the state.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible return codes, see Direct3D Retained Mode Return Values.

Remarks

This method was introduced with DirectX version 6.0.

The following code sets the fill mode render state, eliminating redundant changes if the D3DRMSTATECHANGE_NONVOLATILE flag has been associated with the state.

lpDirect3DRMDev3->RenderStateChange(D3DRENDERSTATE_FILLMODE,
                          D3DFILL_SOLID, 0);

The following code indicates a change to the texture handle render state.

lpDirect3DRMDev3->RenderStateChange(D3DRENDERSTATE_TEXTUREHANDLE, hTex,
                                    D3DRMSTATECHANGE_UPDATEONLY);

See Also

IDirect3DRMDevice3::SetStateChangeOptions

IDirect3DRMDevice3::SetBufferCount

IDirect3DRMDevice3

Sets the number of buffers currently being used by the application.

Syntax

HRESULT SetBufferCount(
  DWORD dwCount
  );

Parameters

dwCount
Number of buffers—one for single-buffering, two for double-buffering, and so on. The default value is one, which is correct only for a single-buffered window operation.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible return codes, see Direct3D Retained Mode Return Values.

Remarks

An application that employs double-buffering or triple-buffering must use this method to inform the system of how many buffers it is using so that the system can calculate how much of the window to clear and update on each frame.

See Also

IDirect3DRMDevice3::GetBufferCount

IDirect3DRMDevice3::SetDither

IDirect3DRMDevice3

Sets the dither flag for the device.

Syntax

HRESULT SetDither(
  BOOL bDither
  );

Parameters

bDither
New dithering mode for the device. The default is TRUE.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible return codes, see Direct3D Retained Mode Return Values.

See Also

IDirect3DRMDevice3::GetDither

IDirect3DRMDevice3::SetQuality

IDirect3DRMDevice3

Sets the rendering quality of a device.

Syntax

HRESULT SetQuality (
  D3DRMRENDERQUALITY rqQuality
  );

Parameters

rqQuality
One or more of the members of the enumerated types represented by the D3DRMRENDERQUALITY enumerated type. The default setting is D3DRMRENDER_FLAT.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible return codes, see Direct3D Retained Mode Return Values.

Remarks

The rendering quality is the maximum quality at which rendering can take place on the rendering surface of that device.

An object's quality has three components: shade mode (flat or Gouraud; Phong is not yet implemented and will default to Gouraud shading), lighting type (on or off), and fill mode (point, wire frame, or solid).

You set the quality of a device with SetQuality. By default it is D3DRMRENDER_FLAT (flat shading, lights on, and solid fill).

You can set the quality of a Direct3DRMProgressiveMesh or Direct3DRMMeshBuilder3 object with their respective SetQuality methods. By default, the quality of these objects is D3DRMRENDER_GOURAUD (Gouraud shading, lights on, and solid fill).

Tip: Gouraud shading gets better performance on progressive mesh objects that change level of detail, often or quickly.

Direct3D Retained Mode renders an object at the lowest quality setting based on the device and the object's current setting for each individual component. For example, if the object's current quality setting is D3DRMRENDER_GOURAUD, and the device is D3DRMRENDER_FLAT, the object will be rendered with flat shading, solid fill, and lights on.

If the object's current quality setting is D3DRMSHADE_GOURAUD|D3DRMLIGHT_OFF|D3DRMFILL_WIREFRAME, and the device's quality setting is D3DRMSHADE_FLAT|D3DRMLIGHT_ON|D3DRMFILL_POINT, the object will be rendered with flat shading, lights off, and point fill mode.

These rules apply to Direct3DRMMeshBuilder3 objects and Direct3DRMProgressiveMesh objects. However, Direct3DRMMesh objects do not follow these rules. Mesh objects ignore the device's quality settings and use the group quality setting (which defaults to D3DRMRENDER_GOURAUD).

See Also

IDirect3DRMDevice3::GetQuality

IDirect3DRMDevice3::SetRenderMode

IDirect3DRMDevice3

Sets the transparency mode. The mode type determines how transparent objects will be rendered. The default mode renders transparent objects with stippled transparency.

Syntax

HRESULT SetRenderMode(
  DWORD dwFlags
  );

Parameters

dwFlags
One or more of the transparent mode flags. The default (dwFlags = 0) sets the transparency mode to stippled transparency. Stippled (or "screen door") transparency is achieved by replacing some of the pixels in one image with pixels from the other image (as if you are seeing one image through a screen door painted with the second image).

In addition, flags can have one or more of the following values:

D3DRMRENDERMODE_BLENDEDTRANSPARENCY (dwFlags = 1) sets the transparency mode to alpha blending. Blended transparency is achieved by combining two images by adding the color values at each pixel.
D3DRMRENDERMODE_DISABLESORTEDALPHAZWRITE (dwFlags = 32) specifies that no depth information will be written to the z-buffer when drawing sorted, transparent objects.
D3DRMRENDERMODE_LIGHTINMODELSPACE (dwFlags = 8). Reserved. Do not use.
D3DRMRENDERMODE_SORTEDTRANSPARENCY (dwFlags = 2) sets the transparency mode so that transparent polygons in the scene are buffered, sorted, and rendered in a second pass. This flag has no effect if the D3DRMRENDERMODE_BLENDEDTRANSPARENCY flag is not also set. Transparent polygons in external visuals or user visuals are not sorted. Only native Direct3D Retained Mode visuals (such as D3DRMMesh objects and D3DRMMeshBuilder objects) are sorted.
D3DRMRENDERMODE_VIEWDEPENDENTSPECULAR (dwFlags = 16) enables more realistic specular lights that depend both on the light direction and the viewer's location. Previous versions of DirectX Foundation only supported flat specular light that did not take into account the viewer's location. If this flag is set, Direct3D Retained Mode uses the D3DLIGHT2 structure to define the light type when calling Direct3D Immediate Mode's IDirect3DLight::SetLight. If this flag is not set, Direct3D Retained Mode uses the D3DLIGHT structure, and you will get the lighting behavior of previous versions of DirectX.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible return codes, see Direct3D Retained Mode Return Values.

Remarks

If the D3DRMRENDERMODE_BLENDEDTRANSPARENCY and D3DRMRENDERMODE_SORTEDTRANSPARENCY flags are set together, it ensures that when two transparent objects are rendered one on top of the other, the image will blend in the correct order to ensure the right visual result.

The D3DRMRENDERMODE_SORTEDTRANSPARENCY turns on the per triangle back-to-front sorting of alpha polygons. Only native Direct3D Retained Mode visuals (such as D3DRMMesh objects and D3DRMMeshBuilder objects) are sorted. You cannot add triangles from external visuals to the sorted list.

The D3DRMRENDERMODE_BLENDEDTRANSPARENCY flag turns on true alpha blending as opposed to stippled alpha. In true alpha blending, the pixels of overlapping triangles are blended together. In stippled alpha, some pixels from the triangle in front are not drawn revealing the triangle below (this is also called screen-door transparency). When doing stippled alpha, it is not necessary to sort triangles since the result is the same no matter what order you render the triangles in.

The only valid parameters to SetSortMode are 0 (stippled alpha with no sorting), BLENDEDTRANSPARENCY (true alpha with no sorting), and both BLENDEDTRANSPARENCY and SORTEDTRANSPARENCY (per triangle sorted true alpha).

See Also

IDirect3DRMDevice3::GetRenderMode

IDirect3DRMDevice3::SetShades

IDirect3DRMDevice3

Sets the number of shades in a ramp of colors used for shading in the monochromatic (or ramp) model.

Syntax

HRESULT SetShades(
  DWORD ulShades
  );

Parameters

ulShades
New number of shades. This parameter must be a power of two. The default is 32.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible return codes, see Direct3D Retained Mode Return Values.

See Also

IDirect3DRMDevice3::GetShades

IDirect3DRMDevice3::SetStateChangeOptions

IDirect3DRMDevice3

Changes the options flags associated with one or more render or light states. The default value for all render and light states is D3DRMSTATECHANGE_VOLATILE. If the D3DRMSTATECHANGE_NONVOLATILE flag is associated with a render or light state, Direct3D Retained Mode caches the value and eliminates redundant changes (it won't set the state to a value equal to its current value). You must, however, indicate when you change the state with either the LightStateChange or RenderStateChange method. See Eliminating Redundant State Changes for more details.

Syntax

HRESULT SetStateChangeOptions(
  DWORD dwStateClass,
  DWORD dwStateNum,
  DWORD dwFlags
  );

Parameters

dwStateClass
Class of states to which this state belongs. The value can be D3DRMSTATECHANGE_LIGHT or D3DRMSTATECHANGE_RENDER.
dwStateNum
Appropriate D3DRENDERSTATE or D3DLIGHTSTATE number. A zero value indicates that all states of the given class should be affected.
dwFlags
Options flags. One of the following values:
D3DRMSTATECHANGE_NONVOLATILE
D3DRMSTATECHANGE_VOLATILE

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible return codes, see Direct3D Retained Mode Return Values.

Remarks

This method was introduced with DirectX version 6.0.

The following code sets the D3DRMSTATECHANGE_NONVOLATILE flag on all render states.

lpDirect3DRMDev3->SetStateChangeOptions(D3DRMSTATECHANGE_RENDER, 0,
                                        D3DRMSTATECHANGE_NONVOLATILE);

The following code sets the D3DRMSTATECHANGE_VOLATILE flag on the texture handle render state.

lpDirect3DRMDev3->SetStateChangeOptions(D3DRMSTATECHANGE_RENDER,
                                        D3DRENDERSTATE_TEXTUREHANDLE,
                                        D3DRMSTATECHANGE_VOLATILE);

See Also

IDirect3DRMDevice3::GetStateChangeOptions

IDirect3DRMDevice3::SetTextureQuality

IDirect3DRMDevice3

Sets the texture quality for the device.

Syntax

HRESULT SetTextureQuality(
  D3DRMTEXTUREQUALITY tqTextureQuality
  );

Parameters

tqTextureQuality
One of the members of the D3DRMTEXTUREQUALITY enumerated type. The default is D3DRMTEXTURE_NEAREST.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible return codes, see Direct3D Retained Mode Return Values.

See Also

IDirect3DRMDevice3::GetTextureQuality

IDirect3DRMDevice3::Update

IDirect3DRMDevice3

Copies the image that has been rendered to the display. It also provides a heartbeat function to the device driver, letting it know when to update the image.

Syntax

HRESULT Update( );

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible return codes, see Direct3D Retained Mode Return Values.

Remarks

Each call to this method causes the system to call an application-defined callback function, D3DRMDEVICE3UPDATECALLBACK. To add a callback function, use the IDirect3DRMDevice3::AddUpdateCallback method.

IDirect3DRMDevice2::Update and IDirect3DRMDevice::Update cause the system to call a D3DRMUPDATECALLBACK type callback. With DirectX version 6.0, IDirect3DRMDevice3 introduced the newer D3DRMDEVICE3UPDATECALLBACK callback.

See Also

IDirect3DRMDevice3::AddUpdateCallback, D3DRMDEVICE3UPDATECALLBACK


IDirect3DRMDeviceArray

Applications use the methods of the IDirect3DRMDeviceArray interface to organize device objects. This section is a reference to the methods of this interface. For a conceptual overview, see Output Devices.

The IDirect3DRMDeviceArray interface supports the following methods:
GetElement
GetSize

The IDirect3DRMDeviceArray interface, like all COM interfaces, inherits the IUnknown interface methods. The IUnknown interface supports the following three methods:
AddRef
QueryInterface
Release

The Direct3DRMDeviceArray object is obtained by calling the IDirect3DRM3::GetDevices method.

IDirect3DRMDeviceArray::GetElement

IDirect3DRMDeviceArray

Retrieves a specified element in a Direct3DRMDeviceArray object.

Syntax

HRESULT GetElement(
  DWORD index,
  LPDIRECT3DRMDEVICE * lplpD3DRMDevice
  );

Parameters

index
Element in the array.
lplpD3DRMDevice
Address that will be filled with a pointer to an IDirect3DRMDevice interface.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

Remarks

You can use QueryInterface to obtain a pointer to the version of IDirect3DRMDevice that you want, for example, IDirect3DRMDevice3. You cannot simply cast the lplpD3DRMDevice parameter to a different version. You must use QueryInterface.

IDirect3DRMDeviceArray::GetSize

IDirect3DRMDeviceArray

Retrieves the number of elements contained in a Direct3DRMDeviceArray object.

Syntax

DWORD GetSize( );

Return Value

Returns the number of elements.


IDirect3DRMFace2

Applications use the methods of the IDirect3DRMFace2 interface to interact with a face. A face represents a single polygon in a mesh. An application can set the color, texture, and material of the face by using the IDirect3DRMFace2::SetColor, IDirect3DRMFace2::SetColorRGB, IDirect3DRMFace2::SetTexture, and IDirect3DRMFace2::SetMaterial methods.

Faces are constructed from vertices by using the IDirect3DRMFace2::AddVertex and IDirect3DRMFace2::AddVertexAndNormalIndexed methods. An application can read the vertices of a face by using the IDirect3DRMFace2::GetVertices and IDirect3DRMFace2::GetVertex methods.

In IDirect3DRMFace2, the SetTexture method can now specify a texture whose width and height are not a power of two.

The methods of the IDirect3DRMFace2 interface can be organized into the following groups:

Color | GetColor
SetColor
SetColorRGB
Materials | GetMaterial
SetMaterial
Textures | GetTexture
GetTextureCoordinateIndex
GetTextureCoordinates
SetTexture
SetTextureCoordinates
SetTextureTopology
Vertices and normals | AddVertex
AddVertexAndNormalIndexed
GetNormal
GetVertex
GetVertexCount
GetVertexIndex
GetVertices

The IDirect3DRMFace2 interface, like all Component Object Model (COM) interfaces, inherits the IUnknown interface methods. The IUnknown interface supports the following three methods:
AddRef
QueryInterface
Release

In addition, the IDirect3DRMFace2 interface inherits the following methods from the IDirect3DRMObject interface:
AddDestroyCallback
Clone
DeleteDestroyCallback
GetAppData
GetClassName
GetName
SetAppData
SetName

The Direct3DRMFace2 object is obtained by using the IDirect3DRM3::CreateFace method.

IDirect3DRMFace2::AddVertex

IDirect3DRMFace2

Adds a vertex to a Direct3DRMFace2 object.

Syntax

HRESULT AddVertex(
  D3DVALUE x,
  D3DVALUE y,
  D3DVALUE z
  );

Parameters

x, y, and z
The x, y, and z components of the new vertex position.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

IDirect3DRMFace2::AddVertexAndNormalIndexed

IDirect3DRMFace2

Adds a vertex and a normal to a Direct3DRMFace2 object, using an index for the vertex and an index for the normal in the containing mesh builder. The face, vertex, and normal must already be part of a Direct3DRMMeshBuilder3 object .

Syntax

HRESULT AddVertexAndNormalIndexed(
  DWORD vertex,
  DWORD normal
  );

Parameters

vertex and normal
Indexes of the vertex and normal to add.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

IDirect3DRMFace2::GetColor

IDirect3DRMFace2

Retrieves the color of a Direct3DRMFace2 object.

Syntax

D3DCOLOR GetColor( );

Return Value

Returns the color.

See Also

IDirect3DRMFace2::SetColor

IDirect3DRMFace2::GetMaterial

IDirect3DRMFace2

Retrieves the material of a Direct3DRMFace2 object.

Syntax

HRESULT GetMaterial(
  LPDIRECT3DRMMATERIAL* lplpMaterial
  );

Parameters

lplpMaterial
Address of the pointer to the Direct3DRMMaterial object applied to the face.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

See Also

IDirect3DRMFace2::SetMaterial

IDirect3DRMFace2::GetNormal

IDirect3DRMFace2

Retrieves the normal vector of a Direct3DRMFace2 object.

Syntax

HRESULT GetNormal(
  D3DVECTOR *lpNormal
  );

Parameters

lpNormal
Address of a D3DVECTOR structure that will be filled with the normal vector of the face.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

IDirect3DRMFace2::GetTexture

IDirect3DRMFace2

Retrieves the Direct3DRMTexture object applied to a Direct3DRMFace2 object.

Syntax

HRESULT GetTexture(
  LPDIRECT3DRMTEXTURE* lplpTexture
  );

Parameters

lplpTexture
Address of a variable that will be filled with a pointer to the texture applied to the face.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

See Also

IDirect3DRMFace2::SetTexture

IDirect3DRMFace2::GetTextureCoordinateIndex

IDirect3DRMFace2

Retrieves the index of the vertex for texture coordinates in the face's mesh. You pass in the face-relative vertex index in the which parameter, and this method returns the corresponding mesh-relative vertex index.

Syntax

int GetTextureCoordinateIndex(
  DWORD which
  );

Parameters

which
Index within the face of the vertex whose coorresponding mesh vertex index is being retrieved.

Return Value

Returns the face's mesh-relative vertex index.

IDirect3DRMFace2::GetTextureCoordinates

IDirect3DRMFace2

Retrieves the texture coordinates of a vertex in a Direct3DRMFace2 object.

Syntax

HRESULT GetTextureCoordinates(
  DWORD index,
  D3DVALUE *lpU,
  D3DVALUE *lpV
  );

Parameters

index
Index of the vertex.
lpU and lpV
Addresses of variables that are filled with the texture coordinates of the vertex.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

IDirect3DRMFace2::GetVertex

IDirect3DRMFace2

Retrieves the position and normal of a vertex in a Direct3DRMFace2 object.

Syntax

HRESULT GetVertex(
  DWORD index,
  D3DVECTOR *lpPosition,
  D3DVECTOR *lpNormal
  );

Parameters

index
Index of the vertex.
lpPosition and lpNormal
Addresses of D3DVECTOR structures that will be filled with the position and normal of the vertex, respectively.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

IDirect3DRMFace2::GetVertexCount

IDirect3DRMFace2

Retrieves the number of vertices in a Direct3DRMFace2 object.

Syntax

int GetVertexCount( );

Return Value

Returns the number of vertices.

IDirect3DRMFace2::GetVertexIndex

IDirect3DRMFace2

Retrieves the index of the vertex in the face's mesh. You pass in the face-relative vertex index in the which parameter, and this method returns the corresponding mesh-relative vertex index.

Syntax

int GetVertexIndex (
  DWORD which
  );

Parameters

which
Index within the face of the vertex whose coorresponding mesh vertex index is being retrieved.

Return Value

Returns the mesh-relative vertex index.

IDirect3DRMFace2::GetVertices

IDirect3DRMFace2

Retrieves the position and normal vector of each vertex in a Direct3DRMFace2 object.

Syntax

HRESULT GetVertices(
  DWORD *lpdwVertexCount,
  D3DVECTOR *lpPosition,
  D3DVECTOR *lpNormal
  );

Parameters

lpdwVertexCount
Address of a variable that contains the number of vertices. If both lpPosition and lpNormal are NULL, lpdwVertexCount is filled with the number of vertices that will be retrieved. This parameter cannot be NULL.
lpPosition and lpNormal
Arrays of D3DVECTOR structures that will be filled with the positions and normal vectors of the vertices, respectively. If both of these parameters are NULL, the method will fill the lpdwVertexCount parameter with the number of vertices that will be retrieved.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

IDirect3DRMFace2::SetColor

IDirect3DRMFace2

Sets a Direct3DRMFace2 object to a given color.

Syntax

HRESULT SetColor(
  D3DCOLOR color
  );

Parameters

color
Color to set. Be sure to set the alpha component as well as the red, green, and blue color components or your objects might not be visible. The RGBA_MAKE DirectX macro allows you to specify these values.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

See Also

IDirect3DRMFace2::GetColor

IDirect3DRMFace2::SetColorRGB

IDirect3DRMFace2

Sets a Direct3DRMFace2 object to a given color.

Syntax

HRESULT SetColorRGB(
  D3DVALUE red,
  D3DVALUE green,
  D3DVALUE blue
  );

Parameters

red, green, and blue
The red, green, and blue components of the color.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

IDirect3DRMFace2::SetMaterial

IDirect3DRMFace2

Sets the material of a Direct3DRMFace2 object.

Syntax

HRESULT SetMaterial(
  LPDIRECT3DRMMATERIAL lpD3DRMMaterial
  );

Parameters

lpD3DRMMaterial
Address of the material.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

See Also

IDirect3DRMFace2::GetMaterial

IDirect3DRMFace2::SetTexture

IDirect3DRMFace2

Sets the texture of a Direct3DRMFace2 object.

Syntax

HRESULT SetTexture(
  LPDIRECT3DRMTEXTURE lpD3DRMTexture
  );

Parameters

lpD3DRMTexture
Address of the texture.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

Remarks

Starting with DirectX Foundation 6, the width and height of the texture are not required to be a power of two.

See Also

IDirect3DRMFace2::GetTexture

IDirect3DRMFace2::SetTextureCoordinates

IDirect3DRMFace2

Sets the texture coordinates of a specified vertex in a Direct3DRMFace2 object.

Syntax

HRESULT SetTextureCoordinates(
  DWORD vertex,
  D3DVALUE u,
  D3DVALUE v
  );

Parameters

vertex
Index of the vertex to be set. For example, if the face were a triangle, the possible vertex indices would be 0, 1, and 2.
u and v
Texture coordinates to assign to the specified vertex.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

IDirect3DRMFace2::SetTextureTopology

IDirect3DRMFace2

Sets the texture topology of a Direct3DRMFace2 object.

Syntax

HRESULT SetTextureTopology(
  BOOL cylU,
  BOOL cylV
  );

Parameters

cylU and cylV
Specify whether the texture has a cylindrical topology in the u and v dimensions.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

Remarks

Several interfaces provide SetTextureTopology methods. See IDirect3DRMeshBuilder3::SetTextureTopology for more information about the relationship between the SetTextureTopology methods, and for more information about the purpose of the cylU and cylV parameters.


IDirect3DRMFaceArray

Applications use the methods of the IDirect3DRMFaceArray interface to organize faces in a mesh. For more information about faces, see IDirect3DRMFace2.

The IDirect3DRMFaceArray interface supports the following methods:
GetElement
GetSize

The IDirect3DRMFaceArray interface, like all COM interfaces, inherits the IUnknown interface methods. The IUnknown interface supports the following three methods:
AddRef
QueryInterface
Release

The Direct3DRMFaceArray object is obtained by calling the IDirect3DRMMeshBuilder3::GetFaces method.

IDirect3DRMFaceArray::GetElement

IDirect3DRMFaceArray

Retrieves a specified element in a Direct3DRMFaceArray object.

Syntax

HRESULT GetElement(
  DWORD index,
  LPDirect3DRMFace * lplpD3DRMFace
  );

Parameters

index
Element in the array.
lplpD3DRMFace
Address that will be filled with a pointer to an IDirect3DRMFace interface.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

IDirect3DRMFaceArray::GetSize

IDirect3DRMFaceArray

Retrieves the number of elements contained in a Direct3DRMFaceArray object.

Syntax

DWORD GetSize( );

Return Value

Returns the number of elements.


IDirect3DRMFrame3

Applications use the methods of the IDirect3DRMFrame3 interface to interact with frames—an object's frame of reference. For a conceptual overview, see Frames.

The IDirect3DRMFrame3 interface is an extension of the IDirect3DRMFrame2 interface. IDirect3DRMFrame3 provides methods that enable additional transformation capabilities, setting and retrieving traversal options, and setting and retrieving the scene fogging method.

IDirect3DRMFrame2 builds upon the functionality of IDirect3DRMFrame by providing additional methods that enable using materials, bounding boxes, and axes with frames. IDirect3DRMFrame2 also adds a RayPick method to calculate the intersections of visuals in the frame with a ray of specified position and direction. In addition, IDirect3DRMFrame2 has one changed method AddMoveCallback2.

See Interface Changes for a list of all the methods added by each interface.

The methods of the IDirect3DRMFrame3 interface can be organized into the following groups:

Axes | GetAxes
GetInheritAxes
SetAxes
SetInheritAxes
Background | GetSceneBackground
GetSceneBackgroundDepth
SetSceneBackground
SetSceneBackgroundDepth
SetSceneBackgroundImage (obsolete)
SetSceneBackgroundRGB
Bounding Box | GetBox
GetBoxEnable
GetHierarchyBox
SetBox
SetBoxEnable
Color | GetColor
SetColor
SetColorRGB
Fog | GetSceneFogColor
GetSceneFogEnable
GetSceneFogMethod
GetSceneFogMode
GetSceneFogParams
SetSceneFogColor
SetSceneFogEnable
SetSceneFogMethod
SetSceneFogMode
SetSceneFogParams
Hierarchies | AddChild
DeleteChild
GetChildren
GetParent
GetScene
Lighting | AddLight
DeleteLight
GetLights
Loading | Load
Material | GetMaterial
GetMaterialOverride
SetMaterial
SetMaterialOverride
Material modes | GetMaterialMode
SetMaterialMode
Positioning and movement | AddMoveCallback
AddRotation
AddScale
AddTranslation
DeleteMoveCallback
GetOrientation
GetPosition
GetRotation
GetVelocity
LookAt
Move
SetOrientation
SetPosition
SetQuaternion
SetRotation
SetVelocity
Ray Picking | RayPick
Sorting | GetSortMode
GetZbufferMode
SetSortMode
SetZbufferMode
Textures | GetTexture
SetTexture
Transformations | AddTransform
GetTransform
InverseTransform
InverseTransformVectors
Transform
TransformVectors
Traversal | GetTraversalOptions
SetTraversalOptions
Visual objects | AddVisual
DeleteVisual
GetVisuals

The IDirect3DRMFrame3 interface, like all Component Object Model (COM) interfaces, inherits the IUnknown interface methods. The IUnknown interface supports the following three methods:
AddRef
QueryInterface
Release

In addition, the IDirect3DRMFrame3 interface inherits the following methods from the IDirect3DRMObject interface:
AddDestroyCallback
Clone
DeleteDestroyCallback
GetAppData
GetClassName
GetName
SetAppData
SetName

Obtain the Direct3DRMFrame3 object by using the IDirect3DRM3::CreateFrame method.


IDirect3DRMFrameArray

Applications use the methods of the IDirect3DRMFrameArray interface to organize frame objects. This section is a reference to the methods of this interface. For a conceptual overview, see Frames.

The IDirect3DRMFrameArray interface supports the following methods:
GetElement
GetSize

The IDirect3DRMFrameArray interface, like all COM interfaces, inherits the IUnknown interface methods. The IUnknown interface supports the following three methods:
AddRef
QueryInterface
Release

The Direct3DRMFrameArray object is obtained by calling the IDirect3DRMPickedArray::GetPick, IDirect3DRMPicked2Array::GetPick, or IDirect3DRMFrame3::GetChildren method.

IDirect3DRMFrameArray::GetElement

IDirect3DRMFrameArray

Retrieves a specified element in a Direct3DRMFrameArray object.

Syntax

HRESULT GetElement(
  DWORD index,
  LPDIRECT3DRMFRAME * lplpD3DRMFrame
  );

Parameters

index
Element in the array.
lplpD3DRMFrame
Address that will be filled with a pointer to an IDirect3DRMFrame interface.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

Remarks

You can use QueryInterface to obtain a pointer to the version of IDirect3DRMFrame that you want, for example, IDirect3DRMFrame3. You cannot simply cast the lplpD3DRMFrame parameter to a different version. You must use QueryInterface.

IDirect3DRMFrameArray::GetSize

IDirect3DRMFrameArray

Retrieves the number of elements contained in a Direct3DRMFrameArray object.

Syntax

DWORD GetSize( );

Return Value

Returns the number of elements.


IDirect3DRMInterpolator

Interpolators provide a way of storing actions and applying them to objects with automatic calculation of in-between values. With an interpolator you can blend colors, move objects smoothly between positions, morph meshes, and perform many other transformations.

The IDirect3DRMInterpolator interface is a superset of the IDirect3DRMAnimation2 interface that increases the kinds of object parameters you can animate. While IDirect3DRMAnimation2 allows animation of an object's position, size, and orientation, IDirect3DRMInterpolator further enables animation of color, meshes, texture, and material.

For a conceptual overview, see IDirect3DRMInterpolator Overview.

In addition to the standard IUnknown and IDirect3DRMObject methods, IDirect3DRMInterpolator contains the following methods:

Attaching Objects | AttachObject
DetachObject
GetAttachedObjects
Interpolating | GetIndex
Interpolate
SetIndex

The IDirect3DRMInterpolator interface, like all Component Object Model (COM) interfaces, inherits the IUnknown interface methods. The IUnknown interface supports the following three methods:
AddRef
QueryInterface
Release

In addition, IDirect3DRMInterpolator interface inherits the following methods from the IDirect3DRMObject interface:
AddDestroyCallback
Clone
DeleteDestroyCallback
GetAppData
GetClassName
GetName
SetAppData
SetName

IDirect3DRMInterpolator::AttachObject

IDirect3DRMInterpolator

Connects an object to the interpolator.

Syntax

HRESULT AttachObject(
  LPDIRECT3DRMOBJECT lpD3DRMObject
  )

Parameters

lpD3DRMObject
Address of the IDirect3DRMObject object to be attached to the interpolator.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

Remarks

The attached object can be another interpolator or an object of type x where the interpolator is of type xInterpolator. For example, a Viewport can be attached to a ViewportInterpolator. The interpolator types are:

  • FrameInterpolator
  • LightInterpolator
  • MaterialInterpolator
  • MeshInterpolator
  • TextureInterpolator
  • ViewportInterpolator

IDirect3DRMInterpolator::DetachObject

IDirect3DRMInterpolator

Detaches an object from the interpolator.

Syntax

HRESULT DetachObject(
  LPDIRECT3DRMOBJECT lpD3DRMObject
  )

Parameters

lpD3DRMObject
Address of the IDirect3DRMObject object to be detached from the interpolator.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

IDirect3DRMInterpolator::GetAttachedObjects

IDirect3DRMInterpolator

Retrieves an array of objects currently attached to the interpolator.

Syntax

HRESULT GetAttachedObjects(
  LPDIRECT3DRMOBJECTARRAY lpD3DRMObjectArray
  )

Parameters

lpD3DRMObjectArray
Address of an IDirect3DRMObjectArray object containing the IDirect3DRMObject objects currently attached to the interpolator.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

IDirect3DRMInterpolator::GetIndex

IDirect3DRMInterpolator

Retrieves the interpolator's current internal index (time).

Syntax

D3DVALUE GetIndex( )

Return Value

Returns a D3DVALUE that contains the interpolator's current internal index.

Remarks

Every key stored in an interpolator has an index value. When a key is recorded (by using a method), the key is stamped with the current interpolator index value. The key's index value does not change after being stamped.

IDirect3DRMInterpolator::Interpolate

IDirect3DRMInterpolator

Generates a series of actions by interpolating between keys stored in the interpolator. The actions are then applied to the specified object. If no object is specified, the actions are applied to the currently attached objects.

Syntax

HRESULT Interpolate(
  D3DVALUE d3dVal,
  LPDIRECT3DRMOBJECT lpD3DRMObject,
  D3DRMINTERPOLATIONOPTIONS d3drmInterpFlags
  )

Parameters

d3dVal
A D3DVALUE that contains the interpolator's current internal index.
lpD3DRMObject
Address of the IDirect3DRMObject object which will be assigned interpolated values for all properties stored in the interpolator. Can be NULL, in which case the property values of all attached objects will be set to interpolated values.
d3drmInterpFlags
One of several flags that control the kind of interpolation done. Possible values are:
D3DRMINTERPOLATION_CLOSED
D3DRMINTERPOLATION_LINEAR
D3DRMINTERPOLATION_NEAREST
D3DRMINTERPOLATION_OPEN
D3DRMINTERPOLATION_SLERPNORMALS
D3DRMINTERPOLATION_SPLINE
D3DRMINTERPOLATION_VERTEXCOLOR
See Interpolation Options for a description of these options.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

IDirect3DRMInterpolator::SetIndex

IDirect3DRMInterpolator

Sets the interpolator's internal index (time) to the specified value. If other interpolators are attached to the interpolator, this method recursively synchronizes their indices to the same value.

Syntax

HRESULT SetIndex(
  D3DVALUE d3dVal
  )

Parameters

d3dVal
The time to set for the interpolator's internal index.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

Remarks

Every key stored in an interpolator has an index value. When a key is recorded (by using a method), the key is stamped with the current interpolator index value. The key's index value does not change after being stamped.


IDirect3DRMLight

Applications use the methods of the IDirect3DRMLight interface to interact with light objects. This section is a reference to the methods of this interface. For a conceptual overview, see Lights.

The methods of the IDirect3DRMLight interface can be organized into the following groups:
Attenuation | GetConstantAttenuation
GetLinearAttenuation
GetQuadraticAttenuation
SetConstantAttenuation
SetLinearAttenuation
SetQuadraticAttenuation
Color | GetColor
SetColor
SetColorRGB
Enable frames | GetEnableFrame
SetEnableFrame
Light types | GetType
SetType
Range | GetRange
SetRange
Spotlight options | GetPenumbra
GetUmbra
SetPenumbra
SetUmbra

The IDirect3DRMLight interface, like all Component Object Model (COM) interfaces, inherits the IUnknown interface methods. The IUnknown interface supports the following three methods:
AddRef
QueryInterface
Release

In addition, the IDirect3DRMLight interface inherits the following methods from the IDirect3DRMObject interface:
AddDestroyCallback
Clone
DeleteDestroyCallback
GetAppData
GetClassName
GetName
SetAppData
SetName

The Direct3DRMLight object is obtained by using the IDirect3DRM3::CreateLight or IDirect3DRM3::CreateLightRGB method.

IDirect3DRMLight::GetColor

IDirect3DRMLight

Retrieves the color of the current Direct3DRMLight object.

Syntax

D3DCOLOR GetColor( );

Return Value

Returns the color.

See Also

IDirect3DRMLight::SetColor

IDirect3DRMLight::GetConstantAttenuation

IDirect3DRMLight

Retrieves the constant attenuation factor for the Direct3DRMLight object.

Syntax

D3DVALUE GetConstantAttenuation( );

Return Value

Returns the constant attenuation value.

Remarks

Lights that have a location (those that are not infinitely far away) can have attenuation factors to calculate the attenuation of the light based on the distance from the light.

The light attenuation formula used depends on whether or not the D3DRMRENDERMODE_VIEWDEPENDENTSPECULAR flag is set. This flag is set in IDirect3DRMDevice3::SetRenderMode.

If the D3DRMRENDERMODE_VIEWDEPENDENTSPECULAR flag is set, the following formulae are used for light attenuation.

The formula for the normalized distance is:

normalized_distance = (distance_from_light - light_range)/light_range

The default light_range value is 256 modeling-space units.

The formula for the total attenuation factor is:

constant_attenuation_factor + normalized_distance * linear_attenuation_factor + (normalized_distance**2) * quadratic_attenuation_factor

If the D3DRMRENDERMODE_VIEWDEPENDENTSPECULAR flag is not set, the following formula is used for light attentuation.

1 / [constant_attenuation_factor + distance * linear_attenuation_factor + (distance**2) * quadratic_attenuation_factor]

The total attenuation factor cannot be greater than 1.

When attenuation factors are not provided, the default values are 1.0 for the constant attenuation factor, 0.0 for the linear attenuation factor, and 0.0 for the quadratic attenuation factor.

See Also

IDirect3DRMLight::SetConstantAttenuation

IDirect3DRMLight::GetEnableFrame

IDirect3DRMLight

Retrieves the enable frame for a light.

Syntax

HRESULT GetEnableFrame(
  LPDIRECT3DRMFRAME * lplpEnableFrame
  );

Parameters

lplpEnableFrame
Address of a pointer that will contain the enable frame for the current Direct3DRMFrame object.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

See Also

IDirect3DRMLight::SetEnableFrame

IDirect3DRMLight::GetLinearAttenuation

IDirect3DRMLight

Retrieves the linear attenuation factor for a light.

Syntax

D3DVALUE GetLinearAttenuation( );

Return Value

Returns the linear attenuation value.

Remarks

Lights that have a location (those that are not infinitely far away) can have attenuation factors to calculate the attenuation of the light based on the distance from the light.

The light attenuation formula used depends on whether or not the D3DRMRENDERMODE_VIEWDEPENDENTSPECULAR flag is set. This flag is set in IDirect3DRMDevice3::SetRenderMode.

If the D3DRMRENDERMODE_VIEWDEPENDENTSPECULAR flag is set, the following formulae are used for light attenuation.

The formula for the normalized distance is:

normalized_distance = (distance_from_light - light_range)/light_range

The default light_range value is 256 modeling-space units.

The formula for the total attenuation factor is:

constant_attenuation_factor + normalized_distance * linear_attenuation_factor + (normalized_distance**2) * quadratic_attenuation_factor

If the D3DRMRENDERMODE_VIEWDEPENDENTSPECULAR flag is not set, the following formula is used for light attentuation.

1 / [constant_attenuation_factor + distance * linear_attenuation_factor + (distance**2) * quadratic_attenuation_factor]

The total attenuation factor cannot be greater than 1.

When attenuation factors are not provided, the default values are 1.0 for the constant attenuation factor, 0.0 for the linear attenuation factor, and 0.0 for the quadratic attenuation factor.

See Also

IDirect3DRMLight::SetLinearAttenuation

IDirect3DRMLight::GetPenumbra

IDirect3DRMLight

Retrieves the penumbra angle of a spotlight.

Syntax

D3DVALUE GetPenumbra( );

Return Value

Returns the penumbra value in radians.

Remarks

For more information see the Spotlight section of the Lights overview.

See Also

IDirect3DRMLight::SetPenumbra

IDirect3DRMLight::GetQuadraticAttenuation

IDirect3DRMLight

Retrieves the quadratic attenuation factor for a light.

Syntax

D3DVALUE GetQuadraticAttenuation( );

Return Value

Returns the quadratic attenuation value.

Remarks

Lights that have a location (those that are not infinitely far away) can have attenuation factors to calculate the attenuation of the light based on the distance from the light.

The light attenuation formula used depends on whether or not the D3DRMRENDERMODE_VIEWDEPENDENTSPECULAR flag is set. This flag is set in IDirect3DRMDevice3::SetRenderMode.

If the D3DRMRENDERMODE_VIEWDEPENDENTSPECULAR flag is set, the following formulae are used for light attenuation.

The formula for the normalized distance is:

normalized_distance = (distance_from_light - light_range)/light_range

The default light_range value is 256 modeling-space units.

The formula for the total attenuation factor is:

constant_attenuation_factor + normalized_distance * linear_attenuation_factor + (normalized_distance**2) * quadratic_attenuation_factor

If the D3DRMRENDERMODE_VIEWDEPENDENTSPECULAR flag is not set, the following formula is used for light attentuation.

1 / [constant_attenuation_factor + distance * linear_attenuation_factor + (distance**2) * quadratic_attenuation_factor]

The total attenuation factor cannot be greater than 1.

When attenuation factors are not provided, the default values are 1.0 for the constant attenuation factor, 0.0 for the linear attenuation factor, and 0.0 for the quadratic attenuation factor.

See Also

IDirect3DRMLight::SetQuadraticAttenuation

IDirect3DRMLight::GetRange

IDirect3DRMLight

Retrieves the range of the current Direct3DRMLight object.

Syntax

D3DVALUE GetRange( );

Return Value

Returns a value describing the range.

See Also

IDirect3DRMLight::SetRange

IDirect3DRMLight::GetType

IDirect3DRMLight

Retrieves the type of a given light.

Syntax

D3DRMLIGHTTYPE GetType( );

Return Value

Returns one of the members of the D3DRMLIGHTTYPE enumerated type.

See Also

IDirect3DRMLight::SetType

IDirect3DRMLight::GetUmbra

IDirect3DRMLight

Retrieves the umbra angle of the Direct3DRMLight object. The default is 0.4 radians.

Syntax

D3DVALUE GetUmbra( );

Return Value

Returns the umbra angle in radians.

Remarks

For more information see the Spotlight section of the Lights overview.

See Also

IDirect3DRMLight::SetUmbra

IDirect3DRMLight::SetColor

IDirect3DRMLight

Sets the color of the given light.

Syntax

HRESULT SetColor(
  D3DCOLOR rcColor
  );

Parameters

rcColor
New color for the light. Be sure to set the alpha component as well as the red, green, and blue color components or your objects might not be visible. The RGBA_MAKE DirectX macro allows you to specify these values.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

Remarks

This method is also used to add a color key to a Direct3DRMLightInterpolator object.

See Also

IDirect3DRMLight::GetColor

IDirect3DRMLight::SetColorRGB

IDirect3DRMLight

Sets the color of the given light.

Syntax

HRESULT SetColorRGB(
  D3DVALUE rvRed,
  D3DVALUE rvGreen,
  D3DVALUE rvBlue
  );

Parameters

rvRed, rvGreen, and rvBlue
New color for the light.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

Remarks

This method is also used to add an RGB color key to a Direct3DRMLightInterpolator object.

IDirect3DRMLight::SetConstantAttenuation

IDirect3DRMLight

Sets the constant attenuation factor for a light.

Syntax

HRESULT SetConstantAttenuation(
  D3DVALUE rvAtt
  );

Parameters

rvAtt
New constant attenuation factor.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

Remarks

Lights that have a location (those that are not infinitely far away) can have attenuation factors to calculate the attenuation of the light based on the distance from the light.

The light attenuation formula used depends on whether or not the D3DRMRENDERMODE_VIEWDEPENDENTSPECULAR flag is set. This flag is set in IDirect3DRMDevice3::SetRenderMode.

If the D3DRMRENDERMODE_VIEWDEPENDENTSPECULAR flag is set, the following formulae are used for light attenuation.

The formula for the normalized distance is:

normalized_distance = (distance_from_light - light_range)/light_range

The default light_range value is 256 modeling-space units.

The formula for the total attenuation factor is:

constant_attenuation_factor + normalized_distance * linear_attenuation_factor + (normalized_distance**2) * quadratic_attenuation_factor

If the D3DRMRENDERMODE_VIEWDEPENDENTSPECULAR flag is not set, the following formula is used for light attentuation.

1 / [constant_attenuation_factor + distance * linear_attenuation_factor + (distance**2) * quadratic_attenuation_factor]

The total attenuation factor cannot be greater than 1.

When attenuation factors are not provided, the default values are 1.0 for the constant attenuation factor, 0.0 for the linear attenuation factor, and 0.0 for the quadratic attenuation factor.

This method is also used to add a constant attenuation key to a Direct3DRMLightInterpolator object.

See Also

IDirect3DRMLight::GetConstantAttenuation

IDirect3DRMLight::SetEnableFrame

IDirect3DRMLight

Sets the enable frame for a light.

Syntax

HRESULT SetEnableFrame(
  LPDIRECT3DRMFRAME lpEnableFrame
  );

Parameters

lpEnableFrame
Address of the light's enable frame. Child frames of this frame are also enabled for this light source.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

See Also

IDirect3DRMLight::GetEnableFrame

IDirect3DRMLight::SetLinearAttenuation

IDirect3DRMLight

Sets the linear attenuation factor for a light.

Syntax

HRESULT SetLinearAttenuation(
  D3DVALUE rvAtt
  );

Parameters

rvAtt
New linear attenuation factor.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

Remarks

Lights that have a location (those that are not infinitely far away) can have attenuation factors to calculate the attenuation of the light based on the distance from the light.

The light attenuation formula used depends on whether or not the D3DRMRENDERMODE_VIEWDEPENDENTSPECULAR flag is set. This flag is set in IDirect3DRMDevice3::SetRenderMode.

If the D3DRMRENDERMODE_VIEWDEPENDENTSPECULAR flag is set, the following formulae are used for light attenuation.

The formula for the normalized distance is:

normalized_distance = (distance_from_light - light_range)/light_range

The default light_range value is 256 modeling-space units.

The formula for the total attenuation factor is:

constant_attenuation_factor + normalized_distance * linear_attenuation_factor + (normalized_distance**2) * quadratic_attenuation_factor

If the D3DRMRENDERMODE_VIEWDEPENDENTSPECULAR flag is not set, the following formula is used for light attentuation.

1 / [constant_attenuation_factor + distance * linear_attenuation_factor + (distance**2) * quadratic_attenuation_factor]

The total attenuation factor cannot be greater than 1.

When attenuation factors are not provided, the default values are 1.0 for the constant attenuation factor, 0.0 for the linear attenuation factor, and 0.0 for the quadratic attenuation factor.

This method is also used to add a linear attenuation key to a Direct3DRMLightInterpolator object.

See Also

IDirect3DRMLight::GetLinearAttenuation

IDirect3DRMLight::SetPenumbra

IDirect3DRMLight

Sets the angle of the penumbra cone.

Syntax

HRESULT SetPenumbra(
  D3DVALUE rvAngle
  );

Parameters

rvAngle
New penumbra angle in radians. This angle must be greater than or equal to the angle of the umbra. If you set the penumbra angle to less than the umbra angle, the umbra angle will be set equal to the penumbra angle. The default value is 0.5 radians.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

Remarks

This method is also used to add a penumbra angle key to a Direct3DRMLightInterpolator object.

For more information see the Spotlight section of the Lights overview.

See Also

IDirect3DRMLight::GetPenumbra

IDirect3DRMLight::SetQuadraticAttenuation

IDirect3DRMLight

Sets the quadratic attenuation factor for a light.

Syntax

HRESULT SetQuadraticAttenuation(
  D3DVALUE rvAtt
  );

Parameters

rvAtt
New quadratic attenuation factor.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

Remarks

Lights that have a location (those that are not infinitely far away) can have attenuation factors to calculate the attenuation of the light based on the distance from the light.

The light attenuation formula used depends on whether or not the D3DRMRENDERMODE_VIEWDEPENDENTSPECULAR flag is set. This flag is set in IDirect3DRMDevice3::SetRenderMode.

If the D3DRMRENDERMODE_VIEWDEPENDENTSPECULAR flag is set, the following formulae are used for light attenuation.

The formula for the normalized distance is:

normalized_distance = (distance_from_light - light_range)/light_range

The default light_range value is 256 modeling-space units.

The formula for the total attenuation factor is:

constant_attenuation_factor + normalized_distance * linear_attenuation_factor + (normalized_distance**2) * quadratic_attenuation_factor

If the D3DRMRENDERMODE_VIEWDEPENDENTSPECULAR flag is not set, the following formula is used for light attentuation.

1 / [constant_attenuation_factor + distance * linear_attenuation_factor + (distance**2) * quadratic_attenuation_factor]

The total attenuation factor cannot be greater than 1.

When attenuation factors are not provided, the default values are 1.0 for the constant attenuation factor, 0.0 for the linear attenuation factor, and 0.0 for the quadratic attenuation factor.

This method is also used to add a quadratic attenuation key to a Direct3DRMLightInterpolator object.

See Also

IDirect3DRMLight::GetQuadraticAttenuation

IDirect3DRMLight::SetRange

IDirect3DRMLight

Sets the range of a spotlight. The light affects objects that are within the range only.

Syntax

HRESULT SetRange(
  D3DVALUE rvRange
  );

Parameters

rvRange
New range. The default value is 256 modeling-space units.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

Remarks

The range property is for spotlights only. This method is also used to add a range key to a Direct3DRMLightInterpolator object.

See Also

IDirect3DRMLight::GetRange

IDirect3DRMLight::SetType

IDirect3DRMLight

Changes the light's type.

Syntax

HRESULT SetType(
  D3DRMLIGHTTYPE d3drmtType
  );

Parameters

d3drmtType
New light type specified by one of the members of the D3DRMLIGHTTYPE enumerated type.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

See Also

IDirect3DRMLight::GetType

IDirect3DRMLight::SetUmbra

IDirect3DRMLight

Sets the angle of the umbra cone.

Syntax

HRESULT SetUmbra(
  D3DVALUE rvAngle
  );

Parameters

rvAngle
New umbra angle in radians. This angle must be less than or equal to the angle of the penumbra. If you set the umbra angle to greater than the penumbra angle, the penumbra angle will be set equal to the umbra angle. The default value is 0.4 radians.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

Remarks

This method is also used to add an umbra angle key to a Direct3DRMLightInterpolator object.

For more information see the Spotlight section of the Lights overview.

See Also

IDirect3DRMLight::GetUmbra


IDirect3DRMLightArray

Applications use the methods of the IDirect3DRMLightArray interface to organize light objects. This section is a reference to the methods of this interface. For a conceptual overview, see Lights.

The IDirect3DRMLightArray interface supports the following methods:
GetElement
GetSize

The IDirect3DRMLightArray interface, like all COM interfaces, inherits the IUnknown interface methods. The IUnknown interface supports the following three methods:
AddRef
QueryInterface
Release

The Direct3DRMLightArray object is obtained by calling the IDirect3DRMFrame3::GetLights method.

IDirect3DRMLightArray::GetElement

IDirect3DRMLightArray

Retrieves a specified element in a Direct3DRMLightArray object.

Syntax

HRESULT GetElement(
  DWORD index,
  LPDIRECT3DRMLIGHT * lplpD3DRMLight
  );

Parameters

index
Element in the array.
lplpD3DRMLight
Address that will be filled with a pointer to an IDirect3DRMLight interface.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

IDirect3DRMLightArray::GetSize

IDirect3DRMLightArray

Retrieves the number of elements contained in a Direct3DRMLightArray object.

Syntax

DWORD GetSize( );

Return Value

Returns the number of elements.


IDirect3DRMMaterial2

Applications use the methods of the IDirect3DRMMaterial2 interface to interact with material objects.

A material defines how a surface reflects light. A material has two components: an emissive property (whether it emits light) and a specular property, whose brightness is determined by a power setting. The value of the power determines the sharpness of the reflected highlights, with a value of 5 giving a metallic appearance and higher values giving a more plastic appearance.

An application can control the emission of a material by using the GetEmissive and SetEmissive methods, the specular component by using the GetSpecular and SetSpecular methods, and the power by using the GetPower and SetPower methods.

Microsoft DirectX version 6.0 introduces the IDirect3DRMMaterial2 interface. IDirect3DRMMaterial2 extends the older IDirect3DRMMaterial interface that it replaces by adding the GetAmbient and SetAmbient methods to allow finer control over material properties. With IDirect3DRMMaterial the ambient color could not be modified and was always equal to the face color. An IDirect3DRMMaterial2 object uses the object's face color as the ambient color until SetAmbient is called. For a history of the Direct3D Retained Mode interfaces, see Interface Changes.

The methods of the IDirect3DRMMaterial2 interface can be organized into the following groups:
Ambient | GetAmbient
SetAmbient
Emission | GetEmissive
SetEmissive
Power for | GetPower
specular exponent | SetPower
Specular | GetSpecular
SetSpecular

The IDirect3DRMMaterial2 interface, like all Component Object Model (COM) interfaces, inherits the IUnknown interface methods. The IUnknown interface supports the following three methods:
AddRef
QueryInterface
Release

In addition, the IDirect3DRMMaterial2 interface inherits the following methods from the IDirect3DRMObject interface:
AddDestroyCallback
Clone
DeleteDestroyCallback
GetAppData
GetClassName
GetName
SetAppData
SetName

The Direct3DRMMaterial object is obtained by using the IDirect3DRM3::CreateMaterial method.

IDirect3DRMMaterial2::GetAmbient

IDirect3DRMMaterial2

Retrieves the current ambient value for the material.

Syntax

HRESULT GetAmbient
(LPD3DVALUE lpdvRed,
LPD3DVALUE lpdvGreen,
LPD3DVALUE lpdvBlue);

Parameters

lpdvRed
Will be filled in with the red component of the ambient color.
lpdvGreen
Will be filled in with the green component of the ambient color.
lpdvBlue
Will be filled in with the blue component of the ambient color.

Return Value

Returns one of the following values:
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DD_OK

Remarks

This method was introduced with DirectX version 6.0.

IDirect3DRMMaterial2::GetEmissive

IDirect3DRMMaterial2

Retrieves the setting for the emissive property of a material. The setting of this property is the color and intensity of the light the object emits.

Syntax

HRESULT GetEmissive(
  D3DVALUE *lpr,
  D3DVALUE *lpg,
  D3DVALUE *lpb
  );

Parameters

lpr, lpg, and lpb
Addresses that will contain the red, green, and blue components of the emissive color when the method returns.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

See Also

IDirect3DRMMaterial2::SetEmissive

IDirect3DRMMaterial2::GetPower

IDirect3DRMMaterial2

Retrieves the power used for the specular exponent in the given material.

Syntax

D3DVALUE GetPower( );

Return Value

Returns the value specifying the power of the specular exponent.

See Also

IDirect3DRMMaterial2::SetPower

IDirect3DRMMaterial2::GetSpecular

IDirect3DRMMaterial2

Retrieves the color of the specular highlights of a material.

Syntax

HRESULT GetSpecular(
  D3DVALUE *lpr,
  D3DVALUE *lpg,
  D3DVALUE *lpb
  );

Parameters

lpr, lpg, and lpb
Addresses that will contain the red, green, and blue components of the color of the specular highlights when the method returns.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

See Also

IDirect3DRMMaterial2::SetSpecular

IDirect3DRMMaterial2::SetAmbient

IDirect3DRMMaterial2

Sets the ambient value for the material. The default is the diffuse color.

Syntax

HRESULT SetAmbient
(D3DVALUE dvRed,
D3DVALUE dvGreen,
D3DVALUE dvBlue);

Parameters

dvRed
The red component of the ambient color.
dvGreen
The green component of the ambient color.
dvBlue
The blue component of the ambient color.

Return Value

Returns one of the following values:
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DD_OK

Remarks

This method was introduced with DirectX version 6.0.

IDirect3DRMMaterial2::SetEmissive

IDirect3DRMMaterial2

Sets the emissive property of a material.

Syntax

HRESULT SetEmissive(
  D3DVALUE r,
  D3DVALUE g,
  D3DVALUE b
  );

Parameters

r, g, and b
Red, green, and blue components of the emissive color.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

Remarks

This method is also used to add an emissive property key to a Direct3DRMMaterialInterpolator object.

See Also

IDirect3DRMMaterial2::GetEmissive

IDirect3DRMMaterial2::SetPower

IDirect3DRMMaterial2

Sets the power used for the specular exponent in a material.

Syntax

HRESULT SetPower(
  D3DVALUE rvPower
  );

Parameters

rvPower
New specular exponent.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

Remarks

This method is also used to add a spectral power key to a Direct3DRMMaterialInterpolator object.

See Also

IDirect3DRMMaterial2::GetPower

IDirect3DRMMaterial2::SetSpecular

IDirect3DRMMaterial2

Sets the color of the specular highlights for a material.

Syntax

HRESULT SetSpecular(
  D3DVALUE r,
  D3DVALUE g,
  D3DVALUE b
  );

Parameters

r, g, and b
Red, green, and blue components of the color of the specular highlights.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

Remarks

This method is also used to add a spectral color key to a Direct3DRMMaterialInterpolator object.

See Also

IDirect3DRMMaterial2::GetSpecular


IDirect3DRMMesh

Applications use the methods of the IDirect3DRMMesh interface to interact with groups of meshes. A mesh is a visual object that is made up of a set of polygonal faces. A mesh defines a set of vertices and a set of faces (the faces are defined in terms of the vertices and normals of the mesh). Changing a vertex or normal that is used by several faces changes the appearance of all faces sharing it.

The vertices of a mesh define the positions of faces in the mesh, and they can also be used to define 2-D coordinates within a texture map.

You can manipulate meshes in Retained Mode by using IDirect3DRMMesh and IDirect3DRMMeshBuilder3.

If an application needs to assign the same characteristics (such as material or texture) to several vertices or faces, it can use the IDirect3DRMMesh interface to combine them in a group. If the application needs to share vertices between two different groups (for example, if neighboring faces in a mesh are different colors), the vertices must be duplicated in both groups. The IDirect3DRMMesh::AddGroup method assigns a group identifier to a collection of faces. This identifier is used to refer to the group in subsequent calls.

The IDirect3DRMMeshBuilder3 and IDirect3DRMMesh interfaces allow an application to create faces with more than three sides. They also automatically split a mesh into multiple buffers if, for example, the hardware the application is rendering to has a limit of 64K and a mesh is larger than that size. These features set the Direct3DRMMesh and Direct3DRMMeshBuilder3 API apart from the Direct3D API.

You can define individual color, texture, and material properties for each face in the mesh, or for all faces in the mesh at once, by using the IDirect3DRMMesh::SetGroupColor, SetGroupColorRGB, SetGroupTexture, and SetGroupMaterial methods.

For a mesh to be rendered, you must first add it to a frame by using the IDirect3DRMFrame3::AddVisual method. You can add a single mesh to multiple frames to create multiple instances of that mesh.

Your application can use flat, Gouraud, and Phong shade modes, as specified by a call to the IDirect3DRMMesh::SetGroupQuality method. (Phong shading is not yet available, however.) This method uses values from the D3DRMRENDERQUALITY enumerated type. For more information about shade modes, see Polygons.

The methods of the IDirect3DRMMesh interface can be organized into the following groups:
Color | GetGroupColor
SetGroupColor
SetGroupColorRGB
Creation and | AddGroup
information | GetBox
GetGroup
GetGroupCount
Materials | GetGroupMaterial
SetGroupMaterial
Miscellaneous | Scale
Translate
Rendering quality | GetGroupQuality
SetGroupQuality
Texture mapping | GetGroupMapping
SetGroupMapping
Textures | GetGroupTexture
SetGroupTexture
Vertex positions | GetVertices
SetVertices

The IDirect3DRMMesh interface, like all Component Object Model (COM) interfaces, inherits the IUnknown interface methods. The IUnknown interface supports the following three methods:
AddRef
QueryInterface
Release

In addition, the IDirect3DRMMesh interface inherits the following methods from the IDirect3DRMObject interface:
AddDestroyCallback
Clone
DeleteDestroyCallback
GetAppData
GetClassName
GetName
SetAppData
SetName

The Direct3DRMMesh object is obtained by using the IDirect3DRM3::CreateMesh method.

IDirect3DRMMesh::AddGroup

IDirect3DRMMesh

Groups a collection of faces and retrieves an identifier for the group. The first group added to a mesh always has index 0. The index of each successive group increases by 1.

Syntax

HRESULT AddGroup(
  unsigned vCount,
  unsigned fCount,
  unsigned vPerFace,
  unsigned *fData,
  D3DRMGROUPINDEX *returnId
  );

Parameters

vCount and fCount
Number of vertices and faces in the group.
vPerFace
Number of vertices per face in the group, if all faces have the same vertex count. If the group contains faces with varying vertex counts, this parameter should be zero.
fData
Address of face data. If the vPerFace parameter specifies a value, this data is simply a list of indices into the group's vertex array. If vPerFace is zero, the vertex indices should be preceded by an integer specifying the number of vertices in that face. For example, if vPerFace is zero and the group is made up of triangular and quadrilateral faces, the data might be in the following form: 3 index index index 4 index index index index 3 index index index ...
returnId
Address of the variable that identifies the group when the method returns.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

Remarks

A newly added group has the following default properties:

  • White
  • No texture
  • No specular reflection
  • Position, normal, and color of each vertex in the vertex array equal to zero

To set the positions of the vertices, use the IDirect3DRMMesh::SetVertices method.

IDirect3DRMMesh::GetBox

IDirect3DRMMesh

Retrieves the bounding box containing a Direct3DRMMesh object. The bounding box gives the minimum and maximum model coordinates in each dimension.

Syntax

HRESULT GetBox(
  D3DRMBOX * lpD3DRMBox
  );

Parameters

lpD3DRMBox
Address of a D3DRMBOX structure filled with the bounding box coordinates.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

IDirect3DRMMesh::GetGroup

IDirect3DRMMesh

Retrieves the data associated with a specified group.

Syntax

HRESULT GetGroup(
  D3DRMGROUPINDEX id,
  unsigned *vCount,
  unsigned *fCount,
  unsigned *vPerFace,
  DWORD *fDataSize,
  unsigned *fData
  );

Parameters

id
Identifier of the group. This identifier must be produced by using the IDirect3DRMMesh::AddGroup method.
vCount and fCount
Addresses of variables that will contain the number of vertices and the number of faces for the group when the method returns. These parameters can be NULL.
vPerFace
Address of a variable that will contain the number of vertices per face for the group when the method returns. This parameter can be NULL.
fDataSize
Address of a variable that specifies the number of unsigned elements in the buffer that the fData parameter points to. This parameter cannot be NULL.
fData
Address of a buffer that will contain the face data for the group when the method returns. The format of this data is the same as was specified in the call to the IDirect3DRMMesh::AddGroup method. If this parameter is NULL, the method returns the required size of the buffer in the fDataSize parameter.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

IDirect3DRMMesh::GetGroupColor

IDirect3DRMMesh

Retrieves the color for a group.

Syntax

D3DCOLOR GetGroupColor(
  D3DRMGROUPINDEX id
  );

Parameters

id
Identifier of the group. This identifier must be produced by using the IDirect3DRMMesh::AddGroup method.

Return Value

Returns a D3DCOLOR variable specifying the color if successful, or zero otherwise.

See Also

IDirect3DRMMesh::SetGroupColor, IDirect3DRMMesh::SetGroupColorRGB

IDirect3DRMMesh::GetGroupCount

IDirect3DRMMesh

Retrieves the number of groups for a given Direct3DRMMesh object.

Syntax

unsigned GetGroupCount( );

Return Value

Returns the number of groups if successful, or zero otherwise.

IDirect3DRMMesh::GetGroupMapping

IDirect3DRMMesh

Retrieves a description of how textures are mapped to a group in a Direct3DRMMesh object.

Syntax

D3DRMMAPPING GetGroupMapping(
  D3DRMGROUPINDEX id
  );

Parameters

id
Identifier of the group. This identifier must be produced by using the IDirect3DRMMesh::AddGroup method.

Return Value

Returns one of the D3DRMMAPPING values that describe how textures are mapped to a group, if successful. Returns zero otherwise.

See Also

IDirect3DRMMesh::SetGroupMapping

IDirect3DRMMesh::GetGroupMaterial

IDirect3DRMMesh

Retrieves a pointer to the material associated with a group in a Direct3DRMMesh object.

Syntax

HRESULT GetGroupMaterial(
  D3DRMGROUPINDEX id,
  LPDIRECT3DRMMATERIAL *returnPtr
  );

Parameters

id
Identifier of the group. This identifier must be produced by using the IDirect3DRMMesh::AddGroup method.
returnPtr
Address of a pointer to a variable that will contain the IDirect3DRMMaterial interface for the group when the method returns.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

See Also

IDirect3DRMMesh::SetGroupMaterial

IDirect3DRMMesh::GetGroupQuality

IDirect3DRMMesh

Retrieves the rendering quality for a specified group in a Direct3DRMMesh object.

Syntax

D3DRMRENDERQUALITY GetGroupQuality(
  D3DRMGROUPINDEX id
  );

Parameters

id
Identifier of the group. This identifier must be produced by using the IDirect3DRMMesh::AddGroup method.

Return Value

Returns values from the enumerated types represented by D3DRMRENDERQUALITY if successful, or zero otherwise. These values include the shading, lighting, and fill modes for the object.

See Also

IDirect3DRMMesh::SetGroupQuality

IDirect3DRMMesh::GetGroupTexture

IDirect3DRMMesh

Retrieves an address of the texture associated with a group in a Direct3DRMMesh object.

Syntax

HRESULT GetGroupTexture(
  D3DRMGROUPINDEX id,
  LPDIRECT3DRMTEXTURE *returnPtr
  );

Parameters

id
Identifier of the group. This identifier must be produced by using the IDirect3DRMMesh::AddGroup method.
returnPtr
Address of a pointer to a variable that will contain the IDirect3DRMTexture interface for the group when the method returns.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

See Also

IDirect3DRMMesh::SetGroupTexture

IDirect3DRMMesh::GetVertices

IDirect3DRMMesh

Retrieves vertex information for a specified group in a Direct3DRMMesh object.

Syntax

HRESULT GetVertices(
  D3DRMGROUPINDEX id,
  DWORD index,
  DWORD count,
  D3DRMVERTEX *returnPtr
  );

Parameters

id
Identifier of the group. This identifier must have been produced by using the IDirect3DRMMesh::AddGroup method.
index
Index into the array of D3DRMVERTEX structures at which to begin returning vertex positions.
count
Number of D3DRMVERTEX structures (vertices) to retrieve following the index given in the index parameter. This parameter cannot be NULL. To retrieve the number of vertices in a group, use the IDirect3DRMMesh::GetGroup method.
returnPtr
Array of D3DRMVERTEX structures that will contain the vertex information (vertex positions, colors, texture coordinates, and so on) when the method returns.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

See Also

IDirect3DRMMesh::GetGroup, IDirect3DRMMesh::SetVertices

IDirect3DRMMesh::Scale

IDirect3DRMMesh

Scales a Direct3DRMMesh object by the given scaling factors, parallel to the x-, y-, and z-axes in model coordinates.

Syntax

HRESULT Scale(
  D3DVALUE sx,
  D3DVALUE sy,
  D3DVALUE sz
  );

Parameters

sx, sy, and sz
Scaling factors that are applied along the x-, y-, and z-axes.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

IDirect3DRMMesh::SetGroupColor

IDirect3DRMMesh

Sets the color of a group in a Direct3DRMMesh object.

Syntax

HRESULT SetGroupColor(
  D3DRMGROUPINDEX id,
  D3DCOLOR value
  );

Parameters

id
Identifier of the group. This identifier must be produced by using the IDirect3DRMMesh::AddGroup method.
value
Color of the group.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

Remarks

This method is also used to add a group color key to a Direct3DRMMeshInterpolator object.

See Also

IDirect3DRMMesh::GetGroupColor, IDirect3DRMMesh::SetGroupColorRGB

IDirect3DRMMesh::SetGroupColorRGB

IDirect3DRMMesh

Sets the color of a group in a Direct3DRMMesh object, using individual RGB values.

Syntax

HRESULT SetGroupColorRGB(
  D3DRMGROUPINDEX id,
  D3DVALUE red,
  D3DVALUE green,
  D3DVALUE blue
  );

Parameters

id
Identifier of the group. This identifier must be produced by using the IDirect3DRMMesh::AddGroup method.
red, green, and blue
Red, green, and blue components of the group color.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

Remarks

This method is also used to add a group RGB key to a Direct3DRMMeshInterpolator object.

See Also

IDirect3DRMMesh::GetGroupColor, IDirect3DRMMesh::SetGroupColor

IDirect3DRMMesh::SetGroupMapping

IDirect3DRMMesh

Sets the mapping for a group in a Direct3DRMMesh object. The mapping controls how textures are mapped to a surface.

Syntax

HRESULT SetGroupMapping(
  D3DRMGROUPINDEX id,
  D3DRMMAPPING value
  );

Parameters

id
Identifier of the group. This identifier must be produced by using the IDirect3DRMMesh::AddGroup method.
value
Value of the D3DRMMAPPING type that describes the mapping for the group.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

See Also

IDirect3DRMMesh::GetGroupMapping

IDirect3DRMMesh::SetGroupMaterial

IDirect3DRMMesh

Sets the material associated with a group in a Direct3DRMMesh object.

Syntax

HRESULT SetGroupMaterial(
  D3DRMGROUPINDEX id,
  LPDIRECT3DRMMATERIAL value
  );

Parameters

id
Identifier of the group. This identifier must be produced by using the IDirect3DRMMesh::AddGroup method.
value
Address of the IDirect3DRMMaterial interface for the Direct3DRMMesh object.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

See Also

IDirect3DRMMesh::GetGroupMaterial

IDirect3DRMMesh::SetGroupQuality

IDirect3DRMMesh

Sets the rendering quality for a specified group in a Direct3DRMMesh object.

Syntax

HRESULT SetGroupQuality(
  D3DRMGROUPINDEX id,
  D3DRMRENDERQUALITY value
  );

Parameters

id
Identifier of the group. This identifier must be produced by using the IDirect3DRMMesh::AddGroup method.
value
Values from the enumerated types represented by the D3DRMRENDERQUALITY type. These values include the shading, lighting, and fill modes for the object.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

See Also

IDirect3DRMMesh::GetGroupQuality

IDirect3DRMMesh::SetGroupTexture

IDirect3DRMMesh

Sets the texture associated with a group in a Direct3DRMMesh object.

Syntax

HRESULT SetGroupTexture(
  D3DRMGROUPINDEX id,
  LPDIRECT3DRMTEXTURE value
  );

Parameters

id
Identifier of the group. This identifier must be produced by using the IDirect3DRMMesh::AddGroup method.
value
Address of the IDirect3DRMTexture interface for the Direct3DRMMesh object.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

See Also

IDirect3DRMMesh::GetGroupTexture

IDirect3DRMMesh::SetVertices

IDirect3DRMMesh

Sets the vertex positions for a specified group in a Direct3DRMMesh object.

Syntax

HRESULT SetVertices(
  D3DRMGROUPINDEX id,
  unsigned index,
  unsigned count,
  D3DRMVERTEX *values
  );

Parameters

id
Identifier of the group. This identifier must be produced by using the IDirect3DRMMesh::AddGroup method.
index
Index of the first vertex in the mesh group to be modified.
count
Number of consecutive vertices to set. The values array must contain at least the number of count elements.
values
Array of D3DRMVERTEX structures specifying the vertex positions to be set.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

Remarks

Vertices are local to the group. If an application needs to share vertices between two different groups (for example, if neighboring faces in a mesh are different colors), the vertices must be duplicated in both groups.

This method is also used to add a vertex position key to a Direct3DRMMeshInterpolator object.

See Also

IDirect3DRMMesh::GetVertices

IDirect3DRMMesh::Translate

IDirect3DRMMesh

Adds the specified offsets to the vertex positions of a Direct3DRMMesh object.

Syntax

HRESULT Translate(
  D3DVALUE tx,
  D3DVALUE ty,
  D3DVALUE tz
  );

Parameters

tx, ty, and tz
Offsets that are added to the x-, y-, and z-coordinates, respectively, of each vertex position.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.


IDirect3DRMMeshBuilder3

Applications use the methods of the IDirect3DRMMeshBuilder3 interface to interact with mesh objects. For more information about meshes, see IDirect3DRMMesh. Microsoft® DirectX® version 6.0 introduces the IDirect3DRMMeshBuilder3 interface. For a history of the Direct3D Retained Mode interfaces, see Interface Changes.

You can add vertices and faces individually to a mesh by using the IDirect3DRMMeshBuilder3::AddVertex, AddFace, and AddFaces methods. You can retrieve an individual face with the GetFace method.

You can set normals (which should be unit vectors), or normals can be calculated by averaging the face normals of the surrounding faces by using the GenerateNormals method.

IDirect3DRMMeshBuilder3 extends the older IDirect3DRMMeshBuilder2 and IDirect3DRMMeshBuilder interfaces that it replaces. It adds the DeleteFace, DeleteNormals, and DeleteVertices methods to delete those objects, and the GetNormal and GetVertex methods to retrieve those objects. IDirect3DRMMeshBuilder3 also adds the Empty and Optimize methods.

Other new IDirect3DRMMeshBuilder3 methods retrieve one or more normals, the number of normals, faces, one or more vertices, and the state (enabled or disabled) of the meshbuilder. This interface enables you to set vertices and normals, and to create and retrieve new submeshes and parent meshes of the meshbuilder. IDirect3DRMMeshBuilder3 also enables the application to add new triangles (as opposed to general polygons) to the IDirect3DRMMeshBuilder3 object and, in the process, implicitly create new faces by using the AddTriangles method.

IDirect3DRMMeshBuilder3 and the older IDirect3DRMMeshBuilder2 include the functionality of IDirect3DRMMeshBuilder and additionally extend the GenerateNormals method to give greater control over the mesh normals generated. IDirect3DRMMeshBuilder3 and IDirect3DRMMeshBuilder2 also enable you to retrieve a single mesh face with GetFace.

In DirectX 6.0, you can create a Direct3DRMMeshBuilder3 object by using the IDirect3DRM3 interface, in which case the Direct3DRMMeshBuilder3 object uses the Immediate Mode DrawPrimitive interface for its the implementation.

The methods of the IDirect3DRMMeshBuilder3 interface can be organized into the following groups.
Color | GetColorSource
SetColor
SetColorRGB
SetColorSource
Creation | GetBox
Faces | AddFace
AddFaces
AddFacesIndexed
CreateFace
DeleteFace
GetFaceCount
GetFace
GetFaces
Loading | Load
Meshes | AddMesh
CreateMesh
Miscellaneous | AddFrame
AddMeshBuilder
AddTriangles
Empty
Enable
GetEnable
Optimize
ReserveSpace
Save
Scale
SetMaterial
Translate
Normals | AddNormal
DeleteNormals
GenerateNormals
GetNormal
GetNormals
GetNormalCount
SetNormal
SetNormals
Perspective | GetPerspective
SetPerspective
Rendering quality | GetQuality
SetQuality
SubMeshes
CreateSubMesh
DeleteSubMesh
GetParentMesh
GetSubMeshes
Textures | GetTextureCoordinates
SetTexture
SetTextureCoordinates
SetTextureTopology
Vertices | AddVertex
DeleteVertices
GetGeometry
GetVertex
GetVertexColor
GetVertexCount
GetVertices
SetVertex
SetVertices
SetVertexColor
SetVertexColorRGB

The IDirect3DRMMeshBuilder3 interface, like all Component Object Model (COM) interfaces, inherits the IUnknown interface methods. The IUnknown interface supports the following three methods.
AddRef
QueryInterface
Release

In addition, the IDirect3DRMMeshBuilder3 interface inherits the following methods from the IDirect3DRMObject interface:
AddDestroyCallback
Clone
DeleteDestroyCallback
GetAppData
GetClassName
GetName
SetAppData
SetName

The Direct3DRMMeshBuilder3 object is obtained by using the IDirect3DRM3::CreateMeshBuilder method.


IDirect3DRMObject

Applications use the methods of the IDirect3DRMObject interface to work with the object superclass of Microsoft® Direct3D® Retained Mode objects.

Direct3DRMObject is the common superclass of all objects in the system. A Direct3DRMObject object has characteristics common to all objects.

Each Direct3DRMObject object is instantiated as a COM object. In addition to the methods of the IUnknown interface, each object has a standard set of methods that are generic to all.

To create an object, the application must first have instantiated a Direct3D Retained Mode object by calling the Direct3DRMCreate function. The application then calls the method of the object's interface that creates an object, and it specifies parameters specific to the object. For example, to create a Direct3DRMAnimation object, the application would call the IDirect3DRM3::CreateAnimation method. The creation method then creates a new object, initializes some of the object's attributes from data passed in the parameters (leaving all others with their default values), and returns the object. Applications can then specify the interface for this object to modify and use the object.

Any object can store 32 bits of application-specific data. This data is not interpreted or altered by Retained Mode. The application can read this data by using the IDirect3DRMObject::GetAppData method, and it can write to it by using the IDirect3DRMObject::SetAppData method. Finding this data is simpler if the application keeps a structure for each Direct3DRMFrame object. For example, if calling the IDirect3DRMFrame3::GetParent method retrieves a Direct3DRMFrame object, the application can easily retrieve the data by using a pointer to its private structure, possibly avoiding a time-consuming search.

You might also want to assign a name to an object to help you organize an application or as part of your application's user interface. You can use the IDirect3DRMObject::SetName and IDirect3DRMObject::GetName methods to set and retrieve object names.

Another example of possible uses for application-specific data is when an application needs to group the faces within a mesh into subsets (for example, for front and back faces). You could use the application data in the face to note in which of these groups a face should be included.

An application can specify a function to call when an object is destroyed, such as when the application needs to deallocate memory associated with the object. To do this, use the IDirect3DRMObject::AddDestroyCallback method. To remove a function previously registered with this method, use the IDirect3DRMObject::DeleteDestroyCallback method.

The callback function is called only when the object is destroyed—that is, when the object's reference count has reached 0 and the system is about to deallocate the memory for the object. If an application kept additional data about an object (so that its dynamics could be implemented, for example), the application could use this callback function as a way to notify itself that it can dispose of the data.

For information about grouping objects, see IDirect3DRMObjectArray.

The methods of the IDirect3DRMObject interface can be organized into the following groups:
Application-specific | GetAppData
data | SetAppData
Cloning | Clone
Naming | GetClassName
GetName
SetName
Notifications | AddDestroyCallback
DeleteDestroyCallback

The IDirect3DRMObject interface, like all Component Object Model (COM) interfaces, inherits the IUnknown interface methods. The IUnknown interface supports the following three methods:
AddRef
QueryInterface
Release

The Direct3DRMObject object is obtained through the appropriate call to the QueryInterface method from any Retained Mode object. All Retained Mode objects inherit the IDirect3DRMObject interface methods.

IDirect3DRMObject::AddDestroyCallback

IDirect3DRMObject

Registers a function that will be called when an object is destroyed.

Syntax

HRESULT AddDestroyCallback(
  D3DRMOBJECTCALLBACK lpCallback,
  LPVOID lpArg
  );

Parameters

lpCallback
User-defined callback function that will be used when the object is destroyed.
lpArg
Address of application-defined data passed to the callback function. Because this function is used after the object has been destroyed, you should not use this function with the object as an argument.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

IDirect3DRMObject::Clone

IDirect3DRMObject

Creates a copy of an object.

Syntax

HRESULT Clone(
  LPUNKNOWN pUnkOuter,
  REFIID riid,
  LPVOID *ppvObj
  );

Parameters

pUnkOuter
Pointer to the outer IUnknown interface that allows COM aggregation features.
riid
Identifier of the object being copied.
ppvObj
Address that will contain the copy of the object when the method returns.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

IDirect3DRMObject::DeleteDestroyCallback

IDirect3DRMObject

Removes a function previously registered with the IDirect3DRMObject::AddDestroyCallback method.

Syntax

HRESULT DeleteDestroyCallback(
  D3DRMOBJECTCALLBACK d3drmObjProc,
  LPVOID lpArg
  );

Parameters

d3drmObjProc
User-defined D3DRMOBJECTCALLBACK callback function that will be used when the object is destroyed.
lpArg
Address of application-defined data passed to the callback function.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

IDirect3DRMObject::GetAppData

IDirect3DRMObject

Retrieves the 32 bits of application-specific data in the object. The default value of the data is 0.

Syntax

DWORD GetAppData( );

Return Value

Returns the data value defined by the application.

See Also

IDirect3DRMObject::SetAppData

IDirect3DRMObject::GetClassName

IDirect3DRMObject

Retrieves the name of the object's class.

Syntax

HRESULT GetClassName(
  LPDWORD lpdwSize,
  LPSTR lpName
  );

Parameters

lpdwSize
Address of a variable containing the size, in bytes, of the buffer pointed to by the lpName parameter.
lpName
Address of a variable that will contain a null-terminated string identifying the class name when the method returns. If this parameter is NULL, the lpdwSize parameter will contain the required size for the string when the method returns.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

IDirect3DRMObject::GetName

IDirect3DRMObject

Retrieves the object's name.

Syntax

HRESULT GetName(
  LPDWORD lpdwSize,
  LPSTR lpName
  );

Parameters

lpdwSize
Address of a variable containing the size, in bytes, of the buffer pointed to by the lpName parameter.
lpName
Address of a variable that will contain a null-terminated string identifying the object's name when the method returns. If this parameter is NULL, the lpdwSize parameter will contain the required size for the string when the method returns.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

See Also

IDirect3DRMObject::SetName

IDirect3DRMObject::SetAppData

IDirect3DRMObject

Sets the 32 bits of application-specific data in the object.

Syntax

HRESULT SetAppData(
  DWORD ulData
  );

Parameters

ulData
User-defined data to be stored with the object.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

See Also

IDirect3DRMObject::GetAppData

IDirect3DRMObject::SetName

IDirect3DRMObject

Sets the object's name.

Syntax

HRESULT SetName(
  const char * lpName
  );

Parameters

lpName
User-defined data to name the object.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

See Also

IDirect3DRMObject::GetName


IDirect3DRMObject2

Applications use the methods of the IDirect3DRMObject2 interface to work with the object2 superclass of Microsoft® Direct3D® Retained Mode objects. Microsoft DirectX version 6.0 introduces the IDirect3DRMObject2 interface which all Retained Mode objects implement. Use QueryInterface on any Direct3D Retained Mode object to obtain a pointer to this interface.

IDirect3DRMObject2 implements the following methods which are equivalent to the IDirect3DRMObject methods of the same name:
AddDestroyCallback
Clone
DeleteDestroyCallback
GetName
SetName

Besides the methods IDirect3DRMObject2 shares with IDirect3DRMObject, it implements the following methods.
GetDirect3DRM
GetClientData
GetAge
SetClientData

IDirect3DRMObject2::GetClientData and IDirect3DRMObject2::SetClientData provide data association with an object, which is more flexible than the older IDirect3DRMObject::GetAppData and IDirect3DRMObject::SetAppData methods.

For a conceptual overview of the older object interface, see IDirect3DRMObject. For a history of the Direct3D Retained Mode interfaces, see Interface Changes.

The methods of the IDirect3DRMObject2 interface can be organized into the following groups:
Application-specific data | GetClientData
SetClientData
Cloning | Clone
Naming | GetName
SetName
Miscellaneous | GetAge
GetDirect3DRM
Notifications | AddDestroyCallback
DeleteDestroyCallback

The IDirect3DRMObject2 interface, like all Component Object Model (COM) interfaces, inherits the IUnknown interface methods. The IUnknown interface supports the following three methods:
AddRef
QueryInterface
Release

The Direct3DRMObject2 object is obtained through the appropriate call to the QueryInterface method from any Retained Mode object. All Retained Mode objects inherit the IDirect3DRMObject2 interface methods.

IDirect3DRMObject2::AddDestroyCallback

IDirect3DRMObject2

Registers a function that will be called when an object is destroyed.

Syntax

HRESULT AddDestroyCallback(
  D3DRMOBJECTCALLBACK lpCallback,
  LPVOID lpArg
  );

Parameters

lpCallback
User-defined callback function that will be used when the object is destroyed.
lpArg
Address of application-defined data passed to the callback function. Because this function is used after the object has been destroyed, you should not use this function with the object as an argument.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

Remarks

This method is equivalent to the IDirect3DRMObject method of the same name.

IDirect3DRMObject2::Clone

IDirect3DRMObject2

Creates a copy of an object.

Syntax

HRESULT Clone(
  LPUNKNOWN pUnkOuter,
  REFIID riid,
  LPVOID *ppvObj
  );

Parameters

pUnkOuter
Pointer to the outer IUnknown interface that allows COM aggregation features.
riid
Identifier of the object being copied.
ppvObj
Address that will contain the copy of the object when the method returns.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

IDirect3DRMObject2::DeleteDestroyCallback

IDirect3DRMObject2

Removes a function previously registered with the IDirect3DRMObject2::AddDestroyCallback method.

Syntax

HRESULT DeleteDestroyCallback(
  D3DRMOBJECTCALLBACK d3drmObjProc,
  LPVOID lpArg
  );

Parameters

d3drmObjProc
User-defined D3DRMOBJECTCALLBACK callback function that will be used when the object is destroyed.
lpArg
Address of application-defined data passed to the callback function.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

Remarks

This method is equivalent to the IDirect3DRMObject method of the same name.

IDirect3DRMObject2::GetAge

IDirect3DRMObject2

Reports the current age of the object.

Syntax

HRESULT GetAge(
  DWORD dwFlags,
  LPDWORD lpdwAge);

Parameters

dwFlags
Flag value. Must be zero if the object is not a meshbuilder. If the object is a meshbuilder, can be one of the following values.
Default (0)
The meshbuilder ages normally (aging is caused by any change to the meshbuilder).
D3DRMMESHBUILDERAGE_GEOMETRY
The meshbuilder ages whenever the mesh geometry is changed (for example, addition of vertices, faces, or another meshbuilder).
D3DRMMESHBUILDERAGE_MATERIALS
The meshbuilder ages whenever a material-related property of the mesh changes, or when faces or another mesh are added.
D3DRMMESHBUILDERAGE_TEXTURES
The meshbuilder ages whenever a texture-related property of the mesh changes, or when faces or another mesh are added.
lpdwAge
Pointer that receives the age.

Return Value

Returns one of the following values.

DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DD_OK

Remarks

The age increases when the object is modified.

This method was introduced in DirectX version 6.0. Aging is only supported in DirectX 6.0 by the following objects.

Direct3DRMDevice3
Direct3DRMTexture3
Direct3DRMMeshBuilder3
Direct3DRMUserVisual
Direct3DRMShadow2
Direct3DRMWrap

IDirect3DRMObject2::GetClientData

IDirect3DRMObject2

Retrieves the data previously associated with an object through a call to SetClientData.

Syntax

HRESULT GetClientData(
  DWORD dwID,
  LPVOID* lplpvData);

Parameters

dwID
An application ID obtained from a call to RegisterClient.
lplpvData
Address of a variable that receives the associated data. A NULL value indicates that no data has been set.

Return Value

Returns one of the following values.

D3DRMERR_CLIENTNOTREGISTERED
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_NOTFOUND
DDERR_NOTINITIALIZED
DD_OK

Remarks

If the data is of type IUnknown, this method increments the reference count before returning the data to the caller. This method was introduced in DirectX version 6.0.

IDirect3DRMObject2::GetDirect3DRM

IDirect3DRMObject2

Retrieves a pointer to an interface of the ultimate Direct3DRM object involved in the creation of this object.

Syntax

HRESULT GetDirect3DRM(
  LPLPDIRECT3DRM lplpD3DRM);

Parameters

lplpD3DRM
Address that receives a pointer to an interface of the ultimate Direct3D Retained Mode object involved in the creation of the object specified by lpDirect3DRMObject.

Return Value

Returns one of the following values:
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DD_OK

Remarks

This method was introduced with DirectX version 6.0.

IDirect3DRMObject2::GetName

IDirect3DRMObject2

Retrieves the object's name.

Syntax

HRESULT GetName(
  LPDWORD lpdwSize,
  LPSTR lpName
  );

Parameters

lpdwSize
Address of a variable containing the size, in bytes, of the buffer pointed to by the lpName parameter.
lpName
Address of a variable that will contain a null-terminated string identifying the object's name when the method returns. If this parameter is NULL, the lpdwSize parameter will contain the required size for the string when the method returns.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

See Also

IDirect3DRMObject2::SetName

Remarks

This method is equivalent to the IDirect3DRMObject method of the same name.

IDirect3DRMObject2::SetClientData

IDirect3DRMObject2

Associates an item of data with a Retained Mode object.

Syntax

HRESULT SetClientData(
  DWORD dwID,
  LPVOID lpvData,
  DWORD dwFlags);

Parameters

dwID
Application ID obtained from a call to IDirect3DRM3::RegisterClient.
lpvData
Application-specific data to be associated with the object.
dwFlags
Flags that determine how the data is interpreted by Retained Mode.
Flag | D3DRMCLIENTDATA_NONE | D3DRMCLIENTDATA_LOCALFREE | D3DRMCLIENTDATA_IUNKNOWN
Interpretation of data | No interpretation | Data has been allocated by client; Direct3DRM should free it upon disassociation | Data is assumed to point to an IUnknown interface
Behavior on SetClientData | No behavior | No behavior | Direct3D Retained Mode increments the reference count on the interface
Behavior on GetClientData | No behavior | No behavior | Direct3D Retained Mode increments the reference count on the interface before passing it to the caller
Behavior when data is disassociated from the object | No behavior | Win32 LocalFree function is used on data | Direct3D Retained Mode decrements the reference count on the interface

Return Value

Returns one of the following values:
D3DRMERR_CLIENTNOTREGISTERED
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DD_OK

Remarks

The data can be removed by means of a call to this method with NULL as an argument, or destruction of the object, or by using IDirect3DRM3::UnregisterClient. If you have previously associated data with the object using the ID specified by dwID, then the previous data is released. The method of destruction depends on the flags passed to this method in the dwFlags parameter. The data can be retrieved by means of a call to GetClientData. This method was introduced in DirectX version 6.0.

IDirect3DRMObject2::SetName

IDirect3DRMObject2

Sets the object's name.

Syntax

HRESULT SetName(
  const char * lpName
  );

Parameters

lpName
User-defined data to name the object.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

Remarks

This method is equivalent to the IDirect3DRMObject method of the same name.

See Also

IDirect3DRMObject2::GetName


IDirect3DRMObjectArray

Applications use the methods of the IDirect3DRMObjectArray interface to organize Direct3DRMObject objects. For more information about Direct3DRMObject, see IDirect3DRMObject.

The IDirect3DRMObjectArray interface supports the following methods:
GetElement
GetSize

The IDirect3DRMObjectArray interface, like all COM interfaces, inherits the IUnknown interface methods. The IUnknown interface supports the following three methods:
AddRef
QueryInterface
Release

The Direct3DRMObjectArray object is obtained by calling the IDirect3DRMInterpolator::GetAttachedObjects method.

IDirect3DRMObjectArray::GetElement

IDirect3DRMObjectArray

Retrieves a specified element in a Direct3DRMObjectArray object.

Syntax

HRESULT GetElement(
  DWORD index,
  LPDIRECT3DRMOBJECT * lplpD3DRMObject
  );

Parameters

index
Element in the array.
lplpD3DRMObject
Address that will be filled with a pointer to an IDirect3DRMObject interface.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

IDirect3DRMObjectArray::GetSize

IDirect3DRMObjectArray

Retrieves the number of elements contained in a Direct3DRMObjectArray object.

Syntax

DWORD GetSize( );

Return Value

Returns the number of elements.


IDirect3DRMPicked2Array

Applications use the methods of the IDirect3DRMPicked2Array interface to organize pick objects and to return more information about the pick objects. See IDirect3DRMPickedArray for more information about picking.

You can use the IDirect3DRMFrame3::RayPick method to retrieve an IDirect3DRMPicked2Array interface, and then call the IDirect3DRMPicked2Array::GetPick method to retrieve an IDirect3DRMFrameArray interface, a visual object, and information about the object intersected by the ray, including the face and group identifiers, pick position, and horizontal and vertical texture coordinates for the vertex, vertex normal, and color of the object. The array of frames is the path through the hierarchy leading to the visual object.

The D3DRMPICKDESC2 structure returned by IDirect3DRMPicked2Array::GetPick contains the face and group identifiers, pick position, horizontal and vertical texture coordinates for the vertex, vertex normal, and color of the intersected objects. A pointer to this interface pointer is returned in the IDirect3DRMFrame3::RayPick method during ray picks.

The IDirect3DRMPicked2Array interface supports the following methods:
GetPick
GetSize

The IDirect3DRMPicked2Array interface, like all COM interfaces, inherits the IUnknown interface methods. The IUnknown interface supports the following three methods:
AddRef
QueryInterface
Release

The Direct3DRMPicked2Array object is obtained by calling the IDirect3DRMFrame3::RayPick method.

IDirect3DRMPicked2Array::GetPick

IDirect3DRMPicked2Array

Retrieves the Direct3DRMVisual and Direct3DRMFrame objects intersected by the specified pick.

Syntax

HRESULT GetPick(
  DWORD index,
  LPDIRECT3DRMVISUAL * lplpVisual,
  LPDIRECT3DRMFRAMEARRAY * lplpFrameArray,
  LPD3DRMPICKDESC2 lpD3DRMPickDesc2
  );

Parameters

index
Index into the pick array identifying the pick for which information will be retrieved.
lplpVisual
Address that will contain a pointer to the Direct3DRMVisual object associated with the specified pick.
lplpFrameArray
Address that will contain a pointer to the Direct3DRMFrameArray object associated with the specified pick.
lpD3DRMPickDesc
Address of a D3DRMPICKDESC2 structure specifying the face and group identifiers, pick position, horizontal and vertical texture coordinates for the vertex, vertex normal, and color of the intersected objects.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Return Values.

Remarks

This method is similar to IDirect3DRMPickedArray::GetPick except that it retrieves the u- and v-values in a D3DRMPICKDESC2 structure rather than a D3DRMPICKDESC structure.

See Also

IDirect3DRMFrame3::RayPick

IDirect3DRMPicked2Array::GetSize

IDirect3DRMPicked2Array

Retrieves the number of elements contained in a Direct3DRMPicked2Array object.

Syntax

DWORD GetSize( );

Return Value

Returns the number of elements.


IDirect3DRMPickedArray

Applications use the methods of the IDirect3DRMPickedArray interface to organize pick objects. Picking is the process of searching for visuals in a scene, given a 2-D coordinate in a viewport or a vector in a frame. For information about ray picking, see the IDirect3DRMPicked2Array interface.

You can use the IDirect3DRMViewport2::Pick method to retrieve an IDirect3DRMPickedArray interface, and then call the IDirect3DRMPickedArray::GetPick method to retrieve an IDirect3DRMFrameArray interface and a visual object. The array of frames is the path through the hierarchy leading to the visual object; that is, a hierarchical list of the visual object's parent frames, with the topmost parent in the hierarchy first in the array.

The IDirect3DRMPickedArray interface supports the following methods:
GetPick
GetSize

The IDirect3DRMPickedArray interface, like all COM interfaces, inherits the IUnknown interface methods. The IUnknown interface supports the following three methods:
AddRef
QueryInterface
Release

The Direct3DRMPickedArray object is obtained by calling the IDirect3DRMViewport2::Pick method.

IDirect3DRMPickedArray::GetPick

IDirect3DRMPickedArray

Retrieves the Direct3DRMVisual and Direct3DRMFrame objects intersected by the specified pick.

Syntax

HRESULT GetPick(
  DWORD index,
  LPDIRECT3DRMVISUAL * lplpVisual,
  LPDIRECT3DRMFRAMEARRAY * lplpFrameArray,
  LPD3DRMPICKDESC lpD3DRMPickDesc
  );

Parameters

index
Index into the pick array identifying the pick for which information will be retrieved.
lplpVisual
Address that will contain a pointer to the Direct3DRMVisual object associated with the specified pick.
lplpFrameArray
Address that will contain a pointer to the Direct3DRMFrameArray object associated with the specified pick.
lpD3DRMPickDesc
Address of a D3DRMPICKDESC structure specifying the pick position and face and group identifiers of the objects being retrieved.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

See Also

IDirect3DRMViewport2::Pick

IDirect3DRMPickedArray::GetSize

IDirect3DRMPickedArray

Retrieves the number of elements contained in a Direct3DRMPickedArray object.

Syntax

DWORD GetSize( );

Return Value

Returns the number of elements.


IDirect3DRMProgressiveMesh

A mesh is a visual object that is made up of a set of polygonal faces. A mesh defines a set of vertices and a set of faces. See IDirect3DRMMesh for more information about meshes.

A progressive mesh is a mesh that is stored as a base mesh (a coarse version) and a set of vertex split records that are used to increasingly refine the mesh. In other words, it allows for progressive refinement. This allows you to set the level of detail rendered for a mesh and also allows progressive download from remote sources.

The progressive mesh is a visual in Microsoft® Direct3D® Retained Mode and can be used in the standard ways that visuals are used. That is, a progressive mesh can be added to frame hierarchies, instantiated a multiple number of times, and picked.

Using the methods of the IDirect3DRMProgressiveMesh interface, you can set the number of vertices or faces to render and thereby control the render detail. You can also specify a minimum level of detail required for rendering. Normally, a progressive mesh is rendered once the base mesh is available, but with the IDirect3DRMProgressiveMesh::SetMinRenderDetail method you can specify that a greater level of detail is necessary before rendering. You can also build a Direct3DRMMesh object from a particular state of the progressive mesh using the IDirect3DRMProgressiveMesh::CreateMesh method.

You can load a progressive mesh from a file, resource, memory, or URL. Loading can be done synchronously or asynchronously. You can check the status of a download with the IDirect3DRMProgressiveMesh::GetLoadStatus method, and terminate a download with the IDirect3DRMProgressiveMesh::Abort method. If loading is asynchronous, it is up to the application to use events through the IDirect3DRMProgressiveMesh::RegisterEvents and IDirect3DRMProgressiveMesh::GetLoadStatus methods to find out how the load is progressing.

The Direct3DRMProgressiveMesh object is created by using the IDirect3DRM3::CreateProgressiveMesh method. After creation, the object can be added to a hierarchy, but will not render until at least the base mesh is available.

In addition to the standard IUnknown and IDirect3DRMObject methods, this API contains the following members:

Creating and Copying Meshes | Clone
CreateMesh
Duplicate
GetBox
Loading | Abort
GetLoadStatus
Load
Setting Quality | SetQuality
GetQuality
Managing Details | GetDetail
GetFaceDetail
GetFaceDetailRange
GetVertexDetail
GetVertexDetailRange
SetDetail
SetFaceDetail
SetMinRenderDetail
SetVertexDetail
Registering Events | RegisterEvents

The IDirect3DRMProgressiveMesh interface, like all COM interfaces, inherits the IUnknown interface methods. The IUnknown interface supports the following three methods:
AddRef
QueryInterface
Release

In addition, the IDirect3DRMProgressiveMesh interface inherits the following methods from the IDirect3DRMObject interface:
AddDestroyCallback
Clone
DeleteDestroyCallback
GetAppData
GetClassName
GetName
SetAppData
SetName

IDirect3DRMProgressiveMesh::Abort

IDirect3DRMProgressiveMesh

Terminates the currently active download.

Syntax

HRESULT Abort(
  DWORD dwFlags
  )

Parameters

dwFlags
Must be set to zero.

Return Value

Returns D3DRM_OK if successful, or one of the following errors:
D3DRMERR_INVALIDOBJECT
D3DRMERR_INVALIDPARAMS

Remarks

If the base mesh has been downloaded before this method is used, the effect is as if the progressive mesh has loaded, the vertex splits are in a valid state, and the progressive mesh is renderable. The other progressive mesh methods will work. If the base mesh has not been downloaded before the IDirect3DRMProgressiveMesh::Abort call and you have added the progressive mesh to a scene, the IDirect3DRMViewport2::Render will succeed but the progressive mesh will not be rendered. Also, if the base mesh has not been downloaded, when you try to use the progressive mesh (to create a mesh or clone, for example) the call will return D3DRMERR_NOTENOUGHDATA.

If there are any outstanding events, they are signaled.

IDirect3DRMProgressiveMesh::Clone

IDirect3DRMProgressiveMesh

Creates a copy of the currently loaded Direct3DRMProgressiveMesh object.

Syntax

HRESULT Clone(
  LPDIRECT3DRMPROGRESSIVEMESH* lplpD3DRMPMesh
  )

Parameters

lplpD3DRMPMesh
Address of a Direct3DRMProgressiveMesh pointer that will be filled in with a pointer to the newly generated Direct3DRMProgressiveMesh object.

Return Value

Returns D3DRM_OK if successful, or one of the following errors:
D3DRMERR_CONNECTIONLOST
D3DRMERR_INVALIDOBJECT
D3DRMERR_INVALIDPARAMS
D3DRMERR_NOTENOUGHDATA

Remarks

The progressive mesh being cloned must have at least its base mesh loaded. If you use this method on a progressive mesh that is currently being asynchronously loaded, the cloned mesh only has as much detail as the loading progressive mesh had at the time it was cloned. Any vertex splits loaded after the duplication are not available to the cloned mesh.

This method does not try to share any of the progressive mesh's internal data, whereas the IDirect3DRMProgressiveMesh::Duplicate does.

See Also

IDirect3DRMProgressiveMesh::Duplicate

IDirect3DRMProgressiveMesh::CreateMesh

IDirect3DRMProgressiveMesh

Builds a mesh from the current level of detail.

Syntax

HRESULT CreateMesh(
  LPDIRECT3DRMMESH* lplpD3DRMMesh
  )

Parameters

lplpD3DRMMesh
Address of a Direct3DRMMesh pointer that will be filled in with a pointer to the newly generated Direct3DRMMesh object.

Return Value

Returns D3DRM_OK if successful, or one of the following errors:
D3DRMERR_CONNECTIONLOST
D3DRMERR_INVALIDOBJECT
D3DRMERR_INVALIDPARAMS
D3DRMERR_NOTENOUGHDATA

Remarks

If the application has requested a level of detail that is not yet available, or the base mesh is not yet available, this method returns the error D3DRMERR_NOTENOUGHDATA.

IDirect3DRMProgressiveMesh::Duplicate

IDirect3DRMProgressiveMesh

Creates a copy of the Direct3DRMProgressiveMesh object. The copy shares all geometry and face data with the original, but has a detail level that can be set independently of the original. This enables the same mesh data to be used in different parts of the hierarchy but with different levels of detail. In essence, you almost have two instances of a progressive mesh within the frame hierarchy.

Syntax

HRESULT Duplicate(
  LPDIRECT3DRMPROGRESSIVEMESH* lplpD3DRMPMesh
  )

Parameters

lplpD3DRMPMesh
Address of a Direct3DRMProgressiveMesh pointer that will be filled with a pointer to the newly generated Direct3DRMProgressiveMesh object.

Return Value

Returns DD_OK if successful, or one of the following errors:
D3DRMERR_CONNECTIONLOST
D3DRMERR_INVALIDOBJECT
D3DRMERR_INVALIDPARAMS
D3DRMERR_NOTENOUGHDATA

Remarks

The progressive mesh being duplicated must have at least its base mesh loaded. If you use this method on a progressive mesh that is currently being asynchronously loaded, the duplicated mesh only has as much detail as the loading progressive mesh had at the time it was duplicated. Any vertex splits loaded after the duplication are not available to the duplicated mesh.

A progressive mesh has a set of data representing the base mesh, and a set of data representing the vertex splits. The base mesh data and data describing the current state of the progressive mesh and the current level of detail isn't shared between meshes that are duplicated, but the vertex splits are. This method creates a new instance of the progressive mesh that shares all geometry and face data with the original, but has a detail level that can be set independently of the original.

IDirect3DRMProgressiveMesh::GetBox

IDirect3DRMProgressiveMesh

Retrieves the bounding box containing a Direct3DRMProgressiveMesh object. The bounding box gives the minimum and maximum coordinates relative to a child frame, in each dimension.

Syntax

HRESULT GetBox(
  D3DRMBOX * lpD3DRMBox
  );

Parameters

lpD3DRMBox
Address of a D3DRMBOX structure that will be filled with the bounding box coordinates.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible return codes, see Direct3D Retained Mode Return Values.

IDirect3DRMProgressiveMesh::GetDetail

IDirect3DRMProgressiveMesh

Returns the current detail level of the progressive mesh normalized between 0.0 and 1.0.

Syntax

HRESULT GetDetail(
  LPD3DVALUE lpdvVal
  )

Parameters

lpdvVal
Address of a D3DVALUE that will be filled with the current detail level of the progressive mesh.

Return Value

Returns D3DRM_OK if successful, or one of the following errors:
D3DRMERR_CONNECTIONLOST
D3DRMERR_INVALIDOBJECT
D3DRMERR_INVALIDPARAMS
D3DRMERR_PENDING

Remarks

If the base mesh has not yet downloaded then this method will return D3DRMERR_PENDING. If a requested level of detail has been set, the return value will increase on each subsequent call until the requested level has been met. If no level has been requested, the detail will increase until all vertex splits have been downloaded.

The normalized value 0.0 represents the minimum number of vertices (the number of vertices in the base mesh), and the normalized value 1.0 represents the maximum number of vertices.

IDirect3DRMProgressiveMesh::GetFaceDetail

IDirect3DRMProgressiveMesh

Retrieves the number of faces in the progressive mesh.

Syntax

HRESULT GetFaceDetail(
  LPDWORD lpdwCount
  )

Parameters

lpdwCount
Address of a DWORD that will be filled in with the number of faces in the progressive mesh.

Return Value

Returns D3DRM_OK if successful, or one of the following errors:
D3DRMERR_CONNECTIONLOST
D3DRMERR_PENDING
D3DRMERR_INVALIDOBJECT
D3DRMERR_INVALIDPARAMS

Remarks

If the number of faces is not available, this method returns D3DRMERR_PENDING.

IDirect3DRMProgressiveMesh::GetFaceDetailRange

IDirect3DRMProgressiveMesh

Retrieves the minimum and maximum face count available in the progressive mesh.

Syntax

HRESULT GetFaceDetailRange(
  LPDWORD lpdwMinFaces,
  LPDWORD lpdwMaxFaces
  )

Parameters

lpdwMinFaces
Address of a DWORD that will be filled in with the minimum number of faces.
lpdwMaxFaces
Address of a DWORD that will be filled in with the maximum number of faces.

Return Value

Returns D3DRM_OK if successful, or one of the following errors:
D3DRMERR_CONNECTIONLOST
D3DRMERR_INVALIDOBJECT
D3DRMERR_INVALIDPARAMS
D3DRMERR_PENDING

Remarks

If the face count is not available, this method returns D3DRMERR_PENDING.

IDirect3DRMProgressiveMesh::GetLoadStatus

IDirect3DRMProgressiveMesh

Allows the application to inquire about the current status of the load.

Syntax

HRESULT GetLoadStatus(
  LPD3DRMPMESHLOADSTATUS lpStatus
  )

Parameters

lpStatus
Address of a D3DRMPMESHLOADSTATUS structure that contains the loading status of the progressive mesh.

Return Value

Returns D3DRM_OK if successful, or one of the following errors:
D3DRMERR_CONNECTIONLOST
D3DRMERR_INVALIDOBJECT
D3DRMERR_INVALIDPARAMS

Remarks

If the mesh is renderable (the base mesh has been downloaded and the data is not corrupt) then the dwFlags member contains D3DRMPMESHSTATUS_RENDERABLE. If the download was interrupted, the dwFlags member will contain D3DRMPMESHSTATUS_INTERRUPTED.

IDirect3DRMProgressiveMesh::GetQuality

IDirect3DRMProgressiveMesh

Retrieves a member of the D3DRMRENDERQUALITY enumerated type that specifies the rendering quality of the progressive mesh.

Syntax

HRESULT GetQuality(
  LPD3DRMRENDERQUALITY lpQuality
  );

Parameters

lpQuality
Pointer to the D3DRMRENDERQUALITY member if successful that specifies rendering quality.

Return Value

Returns D3DRM_OK if successful, or one of the following errors:

D3DRMERR_BADOBJECT
The progressive mesh is invalid.
D3DRMERR_BADVALUE
The pointer to the D3DRMRENDERQUALITY member is invalid.

See Also

IDirect3DRMProgressiveMesh::SetQuality

IDirect3DRMProgressiveMesh::GetVertexDetail

IDirect3DRMProgressiveMesh

Retrieves the number of vertices in the progressive mesh.

Syntax

HRESULT GetVertexDetail(
  LPDWORD lpdwCount
  )

Parameters

lpdwCount
Address of a DWORD that will be filled in with the number of vertices in the progressive mesh.

Return Value

Returns D3DRM_OK if successful, or one of the following errors:
D3DRMERR_CONNECTIONLOST
D3DRMERR_INVALIDOBJECT
D3DRMERR_INVALIDPARAMS
D3DRMERR_PENDING

Remarks

If the number of vertices is not available, this method returns D3DRMERR_PENDING.

IDirect3DRMProgressiveMesh::GetVertexDetailRange

IDirect3DRMProgressiveMesh

Retrieves the minimum and maximum vertex count available in the progressive mesh.

Syntax

HRESULT GetVertexDetailRange(
  LPDWORD lpdwMinVertices,
  LPDWORD lpdwMaxVertices
  )

Parameters

lpdwMinVertices
Address of a DWORD that will be filled in with the minimum number of vertices.
lpdwMaxVertices
Address of a DWORD that will be filled in with the maximum number of vertices.

Return Value

Returns D3DRM_OK if successful, or one of the following errors:
D3DRMERR_CONNECTIONLOST
D3DRMERR_INVALIDOBJECT
D3DRMERR_INVALIDPARAMS
D3DRMERR_PENDING

Remarks

If the vertex count information is not available, this method returns D3DRMERR_PENDING.

IDirect3DRMProgressiveMesh::Load

IDirect3DRMProgressiveMesh

Loads the progressive mesh object from memory, a file, a resource, or a URL. Loading can be done synchronously or asynchronously.

Syntax

HRESULT Load(
  LPVOID lpSource,
  LPVOID lpObjID,
  D3DRMLOADOPTIONS dloLoadflags,
  D3DRMLOADTEXTURECALLBACK lpCallback,
  LPVOID lpArg
  )

Parameters

lpSource
Address of the source for the object to be loaded. This source can be a file, resource, memory block, or stream, depending on the source flags specified in the dloLoadflags parameter.
lpObjID
Address of the ID of the DirectX file record that is a progressive mesh. This can either be a string or a UUID (determined by dloLoadflags). If lpObjID is NULL, dloLoadflags must be D3DRMLOAD_FIRST.
dloLoadflags
Value of the D3DRMLOADOPTIONS type describing how the load is to be performed. One flag from each of the following two groups must be included.
  • To determine which object in the DirectX file is loaded, use:
    D3DRMLOAD_BYNAME
    The lpObjID parameter is interpreted as a string.
    D3DRMLOAD_BYGUID
    The lpObjID parameter is interpreted as a UUID.
    D3DRMLOAD_FIRST
    The first progressive mesh found is loaded.
  • To determine the source of the DirectX file, use:
    D3DRMLOAD_FROMFILE
    The lpSource parameter is interpreted as a string representing a local file name.
    D3DRMLOAD_FROMRESOURCE
    The lpSource parameter is interpreted as a pointer to a D3DRMLOADRESOURCE structure.
    D3DRMLOAD_FROMMEMORY
    The lpSource parameter is interpreted as a pointer to a D3DRMLOADMEMORY structure.
    D3DRMLOAD_FROMURL
    The lpSource parameter is interpreted as a URL.

In addition, you can specify whether the download is synchronous or asynchronous. By default, loading is synchronous and the Load call will not return until all data has been loaded or an error occurs. To specify asynchronous loading, include the following flag:

D3DRMLOAD_ASYNCHRONOUS — The Load call will return immediately. It is up to the application to use events with IDirect3DRMProgressiveMesh::RegisterEvents and IDirect3DRMProgressiveMesh::GetLoadStatus to find out how the load is progressing.

lpCallback
Address of a D3DRMLOADTEXTURECALLBACK callback function that will be used to load any texture encountered. The callback will be used with the texture name as encountered by the loader and the user-defined lpArg parameter. A new thread is not spawned for the callback. If you want the application to download a texture progressively, it must spawn a thread and return with a LPDIRECT3DRMTEXTURE as normal.
lpArg
Address of user-defined data passed to the D3DRMLOADTEXTURECALLBACK callback function.

Return Value

Returns D3DRM_OK if successful, or one of the following errors:
D3DRMERR_BADPMDATA
D3DRMERR_BADFILE
D3DRMERR_CONNECTIONLOST
D3DRMERR_INVALIDOBJECT
D3DRMERR_INVALIDPARAMS

Remarks

The progressive mesh is not useful unless it has been initialized. If asynchronous download is specified, the API returns immediately, and a separate thread is spawned to perform the download.

This method, IDirect3DRMProgressiveMesh::Clone, and IDirect3DRMProgressiveMesh::Duplicate all initialize a progressive mesh. You can only initialize an object once. Therefore, you cannot clone or duplicate a progressive mesh and then try to load into the cloned or duplicated mesh, nor can you load into a previously loaded mesh.

IDirect3DRMProgressiveMesh::RegisterEvents

IDirect3DRMProgressiveMesh

Allows the application to register events with the progressive mesh object that will be signaled when the appropriate conditions are met.

Syntax

HRESULT RegisterEvents(
  HANDLE hEvent,
  DWORD dwFlags,
  DWORD dwReserved
  )

Parameters

hEvent
Event to be signaled when the required condition is met.
dwFlags
Can be one of the following flags:
D3DRMPMESHEVENT_BASEMESH
The event is signaled when the base mesh has been downloaded.
D3DRMPMESHEVENT_COMPLETE
The event is signaled when all data has been downloaded.
dwReserved
Must be zero.

Return Value

Returns D3DRM_OK if successful, or one of the following errors:

D3DRMERR_INVALIDOBJECT
D3DRMERR_INVALIDPARAMS

Remarks

This method can be used to monitor the progress of loads. Events will also be signaled if an error occurs, so your application should always use the IDirect3DRMProgressiveMesh::GetLoadStatus method after being signaled.

IDirect3DRMProgressiveMesh::SetDetail

IDirect3DRMProgressiveMesh

Sets a requested level of detail normalized between 0.0 and 1.0.

Syntax

HRESULT SetDetail(
  D3DVALUE dvVal
  )

Parameters

dvVal
The requested level of detail.

Return Value

Returns D3DRM_OK if successful, or one of the following errors:
D3DRMERR_BADPMDATA
D3DRMERR_CONNECTIONLOST
D3DRMERR_INVALIDOBJECT
D3DRMERR_INVALIDPARAMS
D3DRMERR_PENDING

Remarks

If not enough detail has been downloaded yet (but will be available), the request is acknowledged and D3DRMERR_PENDING is returned. This error is informational and indicates that the requested level will be set as soon as enough detail is available.

The normalized value 0.0 represents the minimum number of vertices (the number of vertices in the base mesh), and the normalized value 1.0 represents the maximum number of vertices.

IDirect3DRMProgressiveMesh::SetFaceDetail

IDirect3DRMProgressiveMesh

Sets the requested level of face detail.

Syntax

HRESULT SetFaceDetail(
  DWORD dwCount
  )

Parameters

dwCount
The number of faces requested.

Return Value

Returns D3DRM_OK if successful, or one of the following errors:
D3DRMERR_BADPMDATA
D3DRMERR_CONNECTIONLOST
D3DRMERR_INVALIDOBJECT
D3DRMERR_INVALIDPARAMS
D3DRMERR_PENDING
D3DRMERR_REQUESTTOOLARGE

Remarks

Sometimes it is not possible to set the progressive mesh to the number of faces requested, though it will always be within 1 of the requested value. This is because a vertex split can add 1 or 2 faces. For example, if you use SetFaceDetail(20), the progressive mesh may only be able to set the face detail to 19 or 21. You can always get the actual number of faces in the progressive mesh by using the IDirect3DRMProgressiveMesh::GetFaceDetail method.

If not enough detail has been downloaded yet (but will be available), the request is be acknowledged and D3DRMERR_PENDING is returned. This error is informational and indicates that the requested level will be set as soon as enough detail is available. If the detail requested is greater that the detail available in the progressive mesh, D3DRMERR_REQUESTTOOLARGE is returned.

See Also

IDirect3DRMProgressiveMesh::GetFaceDetail

IDirect3DRMProgressiveMesh::SetMinRenderDetail

IDirect3DRMProgressiveMesh

Sets the minimum level of detail that will be rendered during a load from 0.0 (minimum detail) to 1.0 (maximum detail). Normally, the progressive mesh will be rendered once the base mesh is available (and the mesh is in the scene graph).

Syntax

HRESULT SetMinRenderDetail(
  D3DVALUE dvCount
  )

Parameters

dvCount
Requested minimum detail.

Return Value

Returns D3DRM_OK if successful, or one of the following errors:
D3DRMERR_CONNECTIONLOST
D3DRMERR_INVALIDOBJECT
D3DRMERR_INVALIDPARAMS
D3DRMERR_PENDING
D3DRMERR_REQUESTTOOLARGE
D3DRMERR_REQUESTTOOSMALL

Remarks

This API sets the minimum number of faces/vertices that will be rendered during the load (larger than the base mesh).

Any subsequent IDirect3DRMProgressiveMesh::SetDetail, IDirect3DRMProgressiveMesh::SetFaceDetail, or IDirect3DRMProgressiveMesh::SetVertexDetail calls will override this.

IDirect3DRMProgressiveMesh::SetQuality

IDirect3DRMProgressiveMesh

Sets the rendering quality of a Direct3DRMProgressiveMesh object.

Syntax

HRESULT SetQuality(
  D3DRMRENDERQUALITY quality
  );

Parameters

quality
Member of the D3DRMRENDERQUALITY enumerated type that specifies the new rendering quality to use.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible return codes, see Direct3D Retained Mode Return Values.

Remarks

An object's quality has three components: shade mode (flat or Gouraud, Phong is not yet implemented and will default to Gouraud shading), lighting type (on or off), and fill mode (point, wire-frame or solid).

You can set the quality of a device with IDirect3DRMDevice3::SetQuality. By default it is D3DRMRENDER_FLAT (flat shading, lights on, and solid fill).

You can set the quality of a Direct3DRMProgressiveMesh object with the SetQuality method. By default, a Direct3DRMProgressiveMesh object's quality is D3DRMRENDER_GOURAUD (Gouraud shading, lights on, and solid fill).

Tip: Gouraud shading performs better on progressive mesh objects that change their level of detail often or quickly.

Direct3D Retained Mode renders an object at the lowest quality setting based on the device and object's current setting for each individual component. For example, if the object's current quality setting is D3DRMRENDER_GOURAUD, and the device is D3DRMRENDER_FLAT, the object will be rendered with flat shading, solid fill and lights on.

If the object's current quality setting is D3DRMSHADE_GOURAUD|D3DRMLIGHT_OFF|D3DRMFILL_WIREFRAME and the device's quality setting is D3DRMSHADE_FLAT|D3DRMLIGHT_ON|D3DRMFILL_POINT, the object will be rendered with flat shading, lights off, and point fill mode.

These rules apply to Direct3DRMMeshBuilder3 objects and Direct3DRMProgressiveMesh objects. However, Direct3DRMMesh objects do not follow these rules. Mesh objects ignore the device's quality settings and use the group quality setting (which defaults to D3DRMRENDER_GOURAUD).

See Also

IDirect3DRMProgressiveMesh::GetQuality

IDirect3DRMProgressiveMesh::SetVertexDetail

IDirect3DRMProgressiveMesh

Sets the requested level of vertex detail.

Syntax

HRESULT SetVertexDetail(
  DWORD dwCount
  )

Parameters

dwCount
The number of vertices requested.

Return Value

Returns D3DRM_OK if successful, or one of the following errors:
D3DRMERR_BADPMDATA
D3DRMERR_CONNECTIONLOST
D3DRMERR_INVALIDOBJECT
D3DRMERR_INVALIDPARAMS
D3DRMERR_PENDING
D3DRMERR_REQUESTTOOLARGE

Remarks

If not enough detail has been downloaded yet (but will be available), the request will be acknowledged and D3DRMERR_PENDING is returned. This error is informational and indicates that the requested level will be set as soon as enough detail is available. If the detail requested is greater than the detail available in the progressive mesh, D3DRMERR_REQUESTTOOLARGE is returned.

See Also

IDirect3DRMProgressiveMesh::GetVertexDetail


IDirect3DRMShadow2

Applications use the IDirect3DRMShadow2 and IDirect3DRMShadow interfaces to initialize Direct3DRMShadow2 and Direct3DRMShadow objects, respectively. Note that this initialization is not necessary if the application uses the IDirect3DRM3::CreateShadow method; it is required only if the application uses the IDirect3DRM3::CreateObject method to create the shadow. An application that calls IDirect3DRM3::CreateObject then calls the IDirect3DRMShadow2::Init method to initialize the shadow.

IDirect3DRMShadow2 extends the functionality of IDirect3DRMShadow by enabling the visual, light, plane, and option shadow parameters to be changed after creation. IDirect3DRMShadow2::SetOptions enables you to set an option that eliminates visual artifacts when blended transparency is enabled. IDirect3DRMShadow2 provides the SetVisual, GetVisual, SetLight, GetLight, SetPlane, GetPlane, SetOptions, and GetOptions methods, in addition to the Init method provided by IDirect3DRMShadow.

The methods of the IDirect3DRMShadow2 interface can be organized into the following groups.

Initialization | Init
Parameter Setting and Retrieval | GetLight
GetOptions
GetPlane
GetVisual
SetLight
SetOptions
SetPlane
SetVisual

The IDirect3DRMShadow2 and IDirect3DRMShadow interfaces, like all Component Object Model (COM) interfaces, inherit the IUnknown interface methods. The IUnknown interface supports the following three methods.
AddRef
QueryInterface
Release

In addition, the IDirect3DRMShadow2 and IDirect3DRMShadow interfaces inherit the following methods from the IDirect3DRMObject interface.
AddDestroyCallback
Clone
DeleteDestroyCallback
GetAppData
GetClassName
GetName
SetAppData
SetName

The Direct3DRMShadow2 object is obtained by using the IDirect3DRM3::CreateShadow method.

IDirect3DRMShadow2::GetLight

IDirect3DRMShadow2

Retrieves the light source used when shadowing. If no light is associated with the shadow, an error is returned.

Syntax

HRESULT GetLight(
  LPDIRECT3DRMLIGHT * lplpDirect3DRMLight);

Parameters

lplpDirect3DRMLight
Pointer to receive the light source.

Return Value

Returns one of the following values.
DD_OK
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS

Remarks

This method was introduced with DirectX version 6.0.

IDirect3DRMShadow2::GetOptions

IDirect3DRMShadow2

Retrieves shadow option flags.

Syntax

HRESULT GetOptions(
  LPDWORD pdwOptions);

Parameters

pdwOptions
Pointer to retrieve the current shadow options. Valid flag is:
D3DRMSHADOW_TRUEALPHA
Creates a shadow that will not have visual artifacts when rendered with true alpha enabled.

Return Value

Returns one of the following values.
DD_OK
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS

Remarks

This method was introduced with DirectX version 6.0.

IDirect3DRMShadow2::GetPlane

IDirect3DRMShadow2

Retrieves the shadow plane. The point is relative to the shadow's frame. The normal is in world space.

Syntax

HRESULT SetPlane(
  LPD3DVALUE pdvPX,
  LPD3DVALUE pdvPY,
  LPD3DVALUE pdvPZ,
  LPD3DVALUE pdvNX,
  LPD3DVALUE pdvNY,
  LPD3DVALUE pdvNZ);

Parameters

pdvPX, pdvPY, pdvPZ
Pointers to receive the x-, y-, and z-values of a point on the shadow plane relative to the shadow's frame. The values are specified as pointers to D3DVALUE data types.
pdvNX, pdvNY, pdvNZ
Pointers to receive the x-, y-, and z-values of the normal to the shadow plane as a world space vector. The values are specified as pointers to D3DVALUE data types.

Return Value

Returns one of the following values.
DD_OK
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS

Remarks

This method was introduced with DirectX version 6.0.

IDirect3DRMShadow2::GetVisual

IDirect3DRMShadow2

Retrieves the visual to be shadowed.

Syntax

HRESULT GetVisual(
  LPDIRECT3DRMVISUAL * lplpDirect3DRMVisual);

Parameters

lplpDirect3DRMVisual
Pointer to receive the visual to be shadowed.

Return Value

Returns one of the following values.
DD_OK
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS

Remarks

This method was introduced with DirectX version 6.0.

IDirect3DRMShadow2::Init

IDirect3DRMShadow2

Initializes a Direct3DRMShadow2 object.

Syntax

HRESULT Init(
  LPUNKNOWN pUnk,
  LPDIRECT3DRMLIGHT lpD3DRMLight,
  D3DVALUE px,
  D3DVALUE py,
  D3DVALUE pz,
  D3DVALUE nx,
  D3DVALUE ny,
  D3DVALUE nz);

Parameters

pUnk
Pointer to the object casting the shadow.
lpD3DRMLight
Pointer to the Direct3DRMLight object that provides the light that defines the shadow.
px, py, and pz
Coordinates of a point on the plane on which the shadow is cast.
nx, ny, and nz
Coordinates of the normal vector of the plane on which the shadow is cast.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

Remarks

After you have called this method to initialize the shadow, add the shadow to the same frame in which the shadowed visual resides, using IDirect3DRMFrame3::AddVisual.

IDirect3DRMShadow2::SetLight

IDirect3DRMShadow2

Sets the light to be used when shadowing.

Syntax

HRESULT SetLight(
  LPDIRECT3DRMLIGHT lpDirect3DRMLight,
  DWORD dwFlags);

Parameters

lpDirect3DRMLight
Light to be used when shadowing.
dwFlags
Reserved. Must be zero.

Return Value

Returns one of the following values.
DD_OK
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS

Remarks

This method was introduced with DirectX version 6.0.

IDirect3DRMShadow2::SetOptions

IDirect3DRMShadow2

Sets the shadow option flags.

Syntax

HRESULT SetOptions(
  DWORD dwOptions);

Parameters

dwOptions
Shadow options. Valid flag is:
D3DRMSHADOW_TRUEALPHA
Creates a shadow that will not have visual artifacts when blended transparency (alpha blending) is enabled. Call IDirect3DRMDevice3::SetRenderMode to enable blended transparency.

Return Value

Returns one of the following values:
DD_OK
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS

Remarks

This method was introduced with DirectX version 6.0.

IDirect3DRMShadow2::SetPlane

IDirect3DRMShadow2

Sets the shadow plane. The point is relative to the shadow's frame. The normal is in world space.

Syntax

HRESULT SetPlane(
  D3DVALUE dvPX,
  D3DVALUE dvPY,
  D3DVALUE dvPZ,
  D3DVALUE dvNX,
  D3DVALUE dvNY,
  D3DVALUE dvNZ,
  DWORD dwFlags);

Parameters

dvPX, dvPY, dvPZ
Point on the shadow plane relative to the shadow's frame, specified as a D3DVALUE data type.
dvNX, dvNY, dvNZ
Normal to the shadow plane as a world space vector, specified as a D3DVALUE data type.
dwFlags
Reserved. Must be zero.

Return Value

Returns one of the following values.
DD_OK
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS

Remarks

This method was introduced with DirectX version 6.0.

IDirect3DRMShadow2::SetVisual

IDirect3DRMShadow2

Sets the visual to be shadowed.

Syntax

HRESULT SetVisual(
    LPDIRECT3DRMVISUAL lpDirect3DRMVisual,
    DWORD dwFlags);

Parameters

lpDirect3DRMVisual
Visual to be shadowed.
dwFlags
Reserved. Must be zero.

Return Value

Returns one of the following values.
DD_OK
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS

Remarks

This method was introduced with DirectX version 6.0.


IDirect3DRMTexture3

Microsoft DirectX version 6.0 introduces the IDirect3DRMTexture3 interface. IDirect3DRMTexture3 extends the older IDirect3DRMTexture2 and IDirect3DRMTexture interfaces that it replaces and it allows finer control over texture management. For a conceptual overview, see Textures. For a history of the Direct3D Retained Mode interfaces, see Interface Changes.

IDirect3DRMTexture3 extends the functionality of the Changed method by allowing you to specify the changed region of the texture. It also provides the texture management caching methods GetCacheOptions and SetCacheOptions. GetSurface, SetDownSampleCallback, and SetValidationCallback are the other new methods IDirect3DRMTexture3 provides.

Previously new methods, added by the older IDirect3DRMTexture2, and also supported by IDirect3DRMTexture3 include InitFromResource2, which allows resources to be loaded from DLLs and executables other than the currently executing file. The InitFromImage method creates a texture from an image in memory. This method is equivalent to the IDirect3DRM3::CreateTexture method. The GenerateMIPMap method generates a mipmap from a source image.

To avoid unnecessary delays when creating textures, hold onto textures you want to use again, instead of creating them each time they're needed. For optimal performance, use a texture surface format that is supported by the device you are using. This will avoid a costly format conversion when the texture is created and any time it changes.

See the remarks in IDirect3DRM3::LoadTexture for an example showing how to keep a reference to textures loaded in a texture callback through IDirect3DRM3::LoadTexture.

The methods of the IDirect3DRMTexture3 interface can be organized into the following groups:
Color | GetColors
SetColors
Decals | GetDecalOrigin
GetDecalScale
GetDecalSize
GetDecalTransparency
GetDecalTransparentColor
SetDecalOrigin
SetDecalScale
SetDecalSize
SetDecalTransparency
SetDecalTransparentColor
Images | GetImage
Initialization | InitFromFile
InitFromImage
InitFromResource2
InitFromSurface
Mipmap generation | GenerateMIPMap
Miscellaneous | GetCacheOptions
GetSurface
SetCacheOptions
SetDownsampleCallback
SetValidationCallback
Renderer notification | Changed
Shading | GetShades
SetShades

The IDirect3DRMTexture3 interface, like all COM interfaces, inherits the IUnknown interface methods. The IUnknown interface supports the following three methods:
AddRef
QueryInterface
Release

In addition, the IDirect3DRMTexture3 interface inherits the following methods from the IDirect3DRMObject interface:
AddDestroyCallback
Clone
DeleteDestroyCallback
GetAppData
GetClassName
GetName
SetAppData
SetName

You can create an IDirect3DRMTexture3 object by calling IDirect3DRM3::CreateTexture or IDirect3DRM3::CreateTextureFromSurface.

IDirect3DRMTexture3::Changed

IDirect3DRMTexture3

Enables the application to specify which region of the texture has changed.

Syntax

HRESULT Changed(
  DWORD dwFlags,
  DWORD dwcRects,
  LPRECT pRects);

Parameters

dwFlags
The following flags are defined:
D3DRMTEXTURE_CHANGEDPIXELS
Indicates that the pixel values have changed.
D3DRMTEXTURE_CHANGEDPALETTE
Indicates that the palette has changed.
D3DRMTEXTURE_INVALIDATEONLY
Indicates that the texture regions are invalidated but do not need to be updated by the application. Before Direct3D Retained Mode renders the texture, it calls the application to update the primary source. This callback is set by SetValidationCallback.
dwcRects
Number of RECT structures pointed to by pRects. If this value is zero, and dwFlags contains D3DRMTEXTURE_CHANGEDPIXELS or D3DRMTEXTURE_INVALIDATEONLY, the whole texture is updated.
pRects
Array of RECT structures describing the regions of pixels that have changed. The pRects parameter is only valid if dwFlags contains D3DRMTEXTURE_CHANGEDPIXELS or D3DRMTEXTURE_INVALIDATEONLY.

Return Value

Returns one of the following values:
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DD_OK

Remarks

This method was introduced with DirectX version 6.0. This method replaces the old IDirect3DRMTexture::Changed method. This old method has two Boolean parameters that indicate whether the application has changed the pixels or the palette of a texture.

IDirect3DRMTexture3::GenerateMIPMap

IDirect3DRMTexture3

Generates a mipmap from a single image source.

Syntax

HRESULT GenerateMIPMap(
  DWORD dwFlags
  );

Parameters

dwFlags
Should be set to zero.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible return codes, see Direct3D Retained Mode Return Values.

Remarks

This method can be called any time after a texture is created. It will generate a mipmap of the source image down to a resolution of 1×1 by using bilinear filtering between levels. Once a mipmap has been generated, it will always be available and will be updated whenever IDirect3DRMTexture3::Changed is called. When using mipmapping, remember to change the texture quality to D3DRMTEXTURE_MIPNEAREST, D3DRMTEXTURE_MIPLINEAR, D3DRMTEXTURE_LINEARMIPNEAREST, or D3DRMTEXTURE_LINEARMIPLINEAR using IDirect3DRMDevice3::SetTextureQuality. Extra mipmap levels will not be put into video memory for hardware devices unless the texture quality includes a mipmapping type and the hardware device supports mipmapping.

See Also

Mipmaps

IDirect3DRMTexture3::GetCacheOptions

IDirect3DRMTexture3

Retrieves information about how texture management treats the current texture if texture memory is restricted.

Syntax

HRESULT GetCacheOptions(
  LPLONG lplImportance,
  LPDWORD lpdwFlags);

Parameters

lplImportance
A signed value that indicates the relative importance of a texture. The default is zero. Higher values indicate a greater importance. This value is used to calculate which textures should be downsampled last if texture memory is restricted.
lpdwFlags
Flags that control the texture management system with respect to the current texture. The currently defined flags are:
D3DRMTEXTURE_FORCERESIDENT
Indicates that the texture should be kept in video memory (in a hardware scenario).
D3DRMTEXTURE_STATIC
Indicates that the texture will not change. The application guarantees not to use the Changed method.
D3DRMTEXTURE_DOWNSAMPLEPOINT
Indicates that when the texture is downsampled, point filtering will be used.
D3DRMTEXTURE_DOWNSAMPLEBILINEAR
Indicates that when the texture is downsampled, bilinear filtering will be used.
D3DRMTEXTURE_DOWNSAMPLEREDUCEDEPTH
Indicates that when the texture is downsampled, the pixel depth will be reduced.
D3DRMTEXTURE_DOWNSAMPLENONE
Indicates that the texture should never be downsampled.

Return Value

Returns one of the following values:
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DD_OK

Remarks

This method was introduced with DirectX version 6.0.

IDirect3DRMTexture3::GetColors

IDirect3DRMTexture3

Retrieves the maximum number of colors used for rendering a Direct3DRMTexture2 object.

Syntax

DWORD GetColors( );

Return Value

Returns the number of colors.

Remarks

This method returns the number of colors that the Direct3DRMTexture2 object has been quantized to, not the number of colors in the image from which the Direct3DRMTexture2 object was created. Consequently, the number of colors that are returned usually matches the colors that were set by calling the IDirect3DRM3::SetDefaultTextureColors method, unless you used the IDirect3DRMTexture3::SetColors method explicitly to change the colors for the Direct3DRMTexture2 object.

See Also

IDirect3DRMTexture3::SetColors

IDirect3DRMTexture3::GetDecalOrigin

IDirect3DRMTexture3

Retrieves the current origin of the decal.

Syntax

HRESULT GetDecalOrigin(
  LONG * lplX,
  LONG * lplY
  );

Parameters

lplX and lplY
Addresses of variables that will be filled with the origin of the decal when the method returns.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible return codes, see Direct3D Retained Mode Return Values.

See Also

IDirect3DRMTexture3::SetDecalOrigin

IDirect3DRMTexture3::GetDecalScale

IDirect3DRMTexture3

Retrieves the scaling property of the given decal.

Syntax

DWORD GetDecalScale( );

Return Value

Returns the scaling property if successful, or -1 otherwise.

See Also

IDirect3DRMTexture3::SetDecalScale

IDirect3DRMTexture3::GetDecalSize

IDirect3DRMTexture3

Retrieves the size of the decal.

Syntax

HRESULT GetDecalSize(
  D3DVALUE *lprvWidth,
  D3DVALUE *lprvHeight
  );

Parameters

lprvWidth and lprvHeight
Addresses of variables that will be filled with the width and height of the decal when the method returns.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible return codes, see Direct3D Retained Mode Return Values.

See Also

IDirect3DRMTexture3::SetDecalSize

IDirect3DRMTexture3::GetDecalTransparency

IDirect3DRMTexture3

Retrieves the transparency property of the decal.

Syntax

BOOL GetDecalTransparency( );

Return Value

Returns TRUE if the decal has a transparent color, FALSE otherwise.

See Also

IDirect3DRMTexture3::SetDecalTransparency

IDirect3DRMTexture3::GetDecalTransparentColor

IDirect3DRMTexture3

Retrieves the transparent color of the decal.

Syntax

D3DCOLOR GetDecalTransparentColor( );

Return Value

Returns the value of the transparent color.

See Also

IDirect3DRMTexture3::SetDecalTransparentColor

IDirect3DRMTexture3::GetImage

IDirect3DRMTexture3

Returns an address of the image that the texture was created with.

Syntax

D3DRMIMAGE * GetImage( );

Return Value

Returns the address of the D3DRMIMAGE structure that the current Direct3DRMTexture2 object was created with.

IDirect3DRMTexture3::GetShades

IDirect3DRMTexture3

Retrieves the number of shades used for each color in the texture when rendering.

Syntax

DWORD GetShades( );

Return Value

Returns the number of shades.

See Also

IDirect3DRMTexture3::SetShades

IDirect3DRMTexture3::GetSurface

IDirect3DRMTexture3

Retrieves the DirectDraw surface that was used to create the texture. This only retrieves a surface if CreateTextureFromSurface or InitFromSurface was used to create the texture.

Syntax

HRESULT GetSurface(
  DWORD dwFlags,
  LPDIRECTDRAWSURFACE* lplpDDS);

Parameters

dwFlags
Flag value. Must be zero.
lplpDDS
Address of a variable that receives a pointer to the interface of the corresponding DirectDraw surface. Note that the interface's reference count is incremented before the interface is handed to the caller.

Return Value

Returns one of the following values:
D3DRMERR_NOTCREATEDFROMDDS
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DD_OK

Remarks

This method was introduced with DirectX version 6.0.

IDirect3DRMTexture3::InitFromFile

IDirect3DRMTexture3

Initializes a Direct3DRMTexture2 object using the information in a given file.

Syntax

HRESULT InitFromFile(
  LPCSTR filename
  );

Parameters

filename
A string that specifies the file from which the texture initialization information is drawn.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible return codes, see Direct3D Retained Mode Return Values.

Remarks

You must have created the Direct3DRMTexture2 object to be initialized using the IDirect3DRM3::CreateTexture or IDirect3DRM3::CreateTextureFromSurface methods.

See Also

IDirect3DRMTexture3::InitFromImage, IDirect3DRMTexture3::InitFromResource2, IDirect3DRMTexture3::InitFromSurface

IDirect3DRMTexture3::InitFromImage

IDirect3DRMTexture3

Initializes a texture from an image in memory.

Syntax

HRESULT InitFromImage(
  LPD3DRMIMAGE lpImage
  );

Parameters

lpImage
Address of a D3DRMIMAGE structure describing the source of the texture.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible return codes, see Direct3D Retained Mode Return Values.

Remarks

You must have created the IDirect3DRMTexture3 object to be initialized using the IDirect3DRM3::CreateTexture or IDirect3DRM3::CreateTextureFromSurface methods.

See Also

IDirect3DRMTexture3::InitFromFile, IDirect3DRMTexture3::InitFromResource2, IDirect3DRMTexture3::InitFromSurface

IDirect3DRMTexture3::InitFromResource2

IDirect3DRMTexture3

Initializes a Direct3DRMTexture2 object from a specified resource.

Syntax

HRESULT InitFromResource2(
  HModule hModule,
  LPCTSTR strName,
  LPCTSTR strType
  );

Parameters

hModule
Handle of the specified resource.
strName
The name of the resource to be used to initialize the texture.
strType
The type name of the resource used to initialize the texture. Textures can be stored in RT_BITMAP and RT_RCDATA resource types, or user-defined types. If the resource type is user-defined, this method passes the resource module handle, the resource name, and the resource type to the FindResource Win32 API.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible return codes, see Direct3D Retained Mode Return Values.

Remarks

You must have created the IDirect3DRMTexture3 object to be initialized using the IDirect3DRM3::CreateTexture or IDirect3DRM3::CreateTextureFromSurface methods.

See Also

IDirect3DRMTexture3::InitFromFile, IDirect3DRMTexture3::InitFromImage, IDirect3DRMTexture3::InitFromSurface

IDirect3DRMTexture3::InitFromSurface

IDirect3DRMTexture3

Initializes a Direct3DRMTexture2 object by using the data from a given DirectDraw surface. This method performs the same as IDirect3DRMTexture3::InitFromSurface.

Syntax

HRESULT InitFromSurface(
  LPDIRECTDRAWSURFACE lpDDS
  );

Parameters

lpDDS
Address of a DirectDraw surface from which initialization information is drawn.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible return codes, see Direct3D Retained Mode Return Values.

Remarks

When you create a texture from a DirectDraw surface, it is best to create the surface in system memory. This enables optimal performance for software devices and allows Direct3D Retained Mode to manage the use of video memory more effectively for hardware devices.

See Also

IDirect3DRMTexture3::InitFromFile, IDirect3DRMTexture3::InitFromImage, IDirect3DRMTexture3::InitFromResource2

IDirect3DRMTexture3::SetCacheOptions

IDirect3DRMTexture3

Provides information about how texture management should treat this texture if texture memory is restricted.

Syntax

HRESULT SetCacheOptions(
  LONG lImportance,
  DWORD dwFlags);

Parameters

lImportance
A signed value that indicates the relative importance of a texture. The default value is zero. Higher values indicate a greater importance. This value is used to calculate which textures should be downsampled last if texture memory is restricted.
dwFlags
Flags that control the texture-management system with respect to the current texture. The currently defined flags are:
D3DRMTEXTURE_FORCERESIDENT
Indicates that the texture should be kept in video memory (in a hardware scenario).
D3DRMTEXTURE_STATIC
Indicates that the texture will not change.
D3DRMTEXTURE_DOWNSAMPLEPOINT
Indicates that when the texture is downsampled, point filtering should be used.
D3DRMTEXTURE_DOWNSAMPLEBILINEAR
Indicates that when the texture is downsampled, bilinear filtering should be used.
D3DRMTEXTURE_DOWNSAMPLEREDUCEDEPTH
Indicates that when the texture is downsampled, the pixel depth should be reduced. If no lower bit depth is available, the size of the texture will be reduced.
D3DRMTEXTURE_DOWNSAMPLENONE
Indicates that the texture should never be downsampled. The default value is D3DRMTEXTURE_DOWNSAMPLEPOINT.

Return Value

Returns one of the following values:
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DD_OK

Remarks

This method was introduced with DirectX version 6.0.

IDirect3DRMTexture3::SetColors

IDirect3DRMTexture3

Sets the maximum number of colors used for rendering a Direct3DRMTexture2 object. This method is required only in the ramp color model.

Syntax

HRESULT SetColors(
  DWORD ulColors
  );

Parameters

ulColors
Number of colors. The default value is 8.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible return codes, see Direct3D Retained Mode Return Values.

See Also

IDirect3DRMTexture3::GetColors

IDirect3DRMTexture3::SetDecalOrigin

IDirect3DRMTexture3

Sets the origin of the decal as an offset from the top left of the decal.

Syntax

HRESULT SetDecalOrigin(
  LONG lX,
  LONG lY
  );

Parameters

lX and lY
New origin, in decal coordinates, for the decal. The default origin is [0, 0].

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible return codes, see Direct3D Retained Mode Return Values.

Remarks

The decal's origin is mapped to its frame's position when rendering. For example, the origin of a decal of a cross would be set to the middle of the decal, and the origin of an arrow pointing down would be set to midway along the bottom edge.

This method is also used to add a decal origin key to a Direct3DRMTextureInterpolator object.

See Also

IDirect3DRMTexture3::GetDecalOrigin

IDirect3DRMTexture3::SetDecalScale

IDirect3DRMTexture3

Sets the scaling property for a decal.

Syntax

HRESULT SetDecalScale(
  DWORD dwScale
  );

Parameters

dwScale
If this parameter is TRUE, depth is taken into account when the decal is scaled and, when the decal is a texture on a frame in a scene, the decal will be scaled smaller when it is farther from the viewer and larger when it closer to the viewer. If this parameter is FALSE, depth information is ignored, and the decal will be the same size whether it is close to or far from the viewer. The default value is TRUE.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible return codes, see Direct3D Retained Mode Return Values.

See Also

IDirect3DRMTexture3::GetDecalScale

IDirect3DRMTexture3::SetDecalSize

IDirect3DRMTexture3

Sets the size of the decal to be used if the decal is being scaled according to its depth in the scene.

Syntax

HRESULT SetDecalSize(
  D3DVALUE rvWidth,
  D3DVALUE rvHeight
  );

Parameters

rvWidth and rvHeight
New width and height, in model coordinates, of the decal. The default size is [1, 1].

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible return codes, see Direct3D Retained Mode Return Values.

Remarks

This method is also used to add a decal size key to a Direct3DRMTextureInterpolator object.

See Also

IDirect3DRMTexture3::GetDecalSize

IDirect3DRMTexture3::SetDecalTransparency

IDirect3DRMTexture3

Sets the transparency property of the decal.

Syntax

HRESULT SetDecalTransparency(
  BOOL bTransp
  );

Parameters

bTransp
If this parameter is TRUE, the decal has a transparent color. If it is FALSE, it has an opaque color. The default value is FALSE.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible return codes, see Direct3D Retained Mode Return Values.

See Also

IDirect3DRMTexture3::GetDecalTransparency

IDirect3DRMTexture3::SetDecalTransparentColor

IDirect3DRMTexture3

Sets the transparent color for a decal.

Syntax

HRESULT SetDecalTransparentColor(
  D3DCOLOR rcTransp
  );

Parameters

rcTransp
New transparent color. The default transparent color is black.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible return codes, see Direct3D Retained Mode Return Values.

Remarks

This method is also used to add a decal transparent color key to a Direct3DRMTextureInterpolator object.

See Also

IDirect3DRMTexture3::GetDecalTransparentColor

IDirect3DRMTexture3::SetDownsampleCallback

IDirect3DRMTexture3

Specifies a callback that texture management will use when a texture is to be downsampled, rather than using the D3DRM built-in method. If a callback has already been specified, the new callback replaces the old one. If the callback is NULL, the current callback is removed.

Syntax

typedef HRESULT (CDECL *D3DRMDOWNSAMPLECALLBACK)
  (LPVOID pArg,
  LPDIRECTDRAWSURFACE pDDSSrc,
  LPDIRECTDRAWSURFACE pDDSDst);

HRESULT SetDownsampleCallback(
  LPDIRECT3DRMTEXTURE3 lpDirect3DRMTexture,
  D3DRMDOWNSAMPLECALLBACK pCallback,
  LPVOID pArg);

Parameters

pCallback
Pointer to a callback function that will be invoked to perform the downsampling. A value of NULL indicates that the current callback is to be removed.
pArg
Application-specific data that will be passed to the callback upon invocation.

Return Value

Returns one of the following values:
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DD_OK

Remarks

Downsampling is done when the video memory is getting overloaded and the texture surfaces need to be reduced in size. Direct3D Retained Mode provides default methods for reducing texure sizes, such as DirectDraw blitting and bilinear filtering, but users can define a callback with their own method to scale down texture size.

This method was introduced with DirectX version 6.0.

See Also

D3DRMDOWNSAMPLECALLBACK

IDirect3DRMTexture3::SetShades

IDirect3DRMTexture3

Sets the maximum number of shades to use for each color for the Direct3DRMTexture2 object when rendering. This method is required only in the ramp color model.

Syntax

HRESULT SetShades(
  DWORD ulShades
  );

Parameters

ulShades
New number of shades. This value must be a power of 2. The default value is 16.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible return codes, see Direct3D Retained Mode Return Values.

See Also

IDirect3DRMTexture3::GetShades

IDirect3DRMTexture3::SetValidationCallback

IDirect3DRMTexture3

Sets the callback function that will validate and update the primary source texture.

Syntax

typedef HRESULT (CDECL *D3DRMVALIDATIONCALLBACK)
  (LPVOID pArg,
  DWORD dwFlags,
  DWORD dwcRects,
  LPRECT pRects);

HRESULT SetValidationCallback(
  LPDIRECT3DRMTEXTURE3 lpDirect3DRMTexture,
  D3DRMVALIDATIONCALLBACK pCallback,
  LPVOID pArg);

Parameters

pCallback
Pointer to a callback function that will be invoked to perform the validation. If a callback has already been specified, the new callback replaces the old one. Specify NULL to remove the current callback.
pArg
Application-specific data that will be passed to the callback upon invocation.

Return Value

Returns one of the following values:
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DD_OK

Remarks

Direct3D Retained Mode calls the texture validation callback when a texture region that has previously been marked as invalid, meaning it has changed but not been updated, now needs to be updated. The application updates the primary source and returns.

This method was introduced with DirectX version 6.0.

See Also

D3DRMVALIDATIONCALLBACK


IDirect3DRMUserVisual

Applications use the IDirect3DRMUserVisual interface to initialize Direct3DRMUserVisual objects. Note that this initialization is not necessary if the application uses the IDirect3DRM3::CreateUserVisual method; it is required only if the application uses the IDirect3DRM3::CreateObject method to create the user-visual object. An application that calls IDirect3DRM3::CreateObject then calls the IDirect3DRMUserVisual::Init method to initialize the object.

User-visual objects are application-defined data that an application can add to a scene and then render, typically by using a customized rendering module. For example, an application could add sound as a user-visual object in a scene, and then render the sound during playback. If an application changes the render state during the D3DRMUSERVISUALCALLBACK callback function it should also restore the render state before that function returns.

The IDirect3DRMUserVisual interface supports the Init method.

The IDirect3DRMUserVisual interface, like all Component Object Model (COM) interfaces, inherits the IUnknown interface methods. The IUnknown interface supports the following three methods:
AddRef
QueryInterface
Release

In addition, the IDirect3DRMUserVisual interface inherits the following methods from the IDirect3DRMObject interface:
AddDestroyCallback
Clone
DeleteDestroyCallback
GetAppData
GetClassName
GetName
SetAppData
SetName

The Direct3DRMUserVisual object is obtained by using the IDirect3DRM3::CreateUserVisual method.

IDirect3DRMUserVisual::Init

IDirect3DRMUserVisual

Initializes a Direct3DRMUserVisual object.

Syntax

HRESULT Init(
  D3DRMUSERVISUALCALLBACK d3drmUVProc,
  void * lpArg
  );

Parameters

d3drmUVProc
Application-defined D3DRMUSERVISUALCALLBACK callback function.
lpArg
Application-defined data to be passed to the callback function.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

Remarks

Applications can use the IDirect3DRM3::CreateUserVisual method to create and initialize a user-visual object at the same time. It is necessary to use IDirect3DRMUserVisual::Init only when the application has created the user-visual object by using the IDirect3DRM3::CreateObject method.


IDirect3DRMViewport2

Applications use the methods of the IDirect3DRMViewport2 interface to work with viewport objects. For a conceptual overview, see Viewports. Microsoft DirectX version 6.0 introduces the IDirect3DRMViewport2 interface. IDirect3DRMViewport2 extends the older IDirect3DRMViewport interface that it replaces by adding a flag parameter to the Clear method to indicate what should be cleared. For a history of the Direct3D Retained Mode interfaces, see Interface Changes.

The methods of the IDirect3DRMViewport2 interface can be organized into the following groups:

Camera | GetCamera
SetCamera
Clipping planes | GetBack
GetFront
GetPlane
SetBack
SetFront
SetPlane
Dimensions | GetHeight
GetWidth
Field of view | GetField
SetField
Initialization | Init
Miscellaneous | Clear
Configure
ForceUpdate
GetDevice
GetDirect3DViewport
Pick
Render
Offsets | GetX
GetY
Projection types | GetProjection
SetProjection
Scaling | GetUniformScaling
SetUniformScaling
Transformations | InverseTransform
InverseTransformVectors
Transform
TransformVectors

The IDirect3DRMViewport2 interface, like all Component Object Model (COM) interfaces, inherits the IUnknown interface methods. The IUnknown interface supports the following three methods:
AddRef
QueryInterface
Release

In addition, the IDirect3DRMViewport2 interface inherits the following methods from the IDirect3DRMObject interface:
AddDestroyCallback
Clone
DeleteDestroyCallback
GetAppData
GetClassName
GetName
SetAppData
SetName

The Direct3DRMViewport object is obtained by using the IDirect3DRM3::CreateViewport method.

IDirect3DRMViewport2::Clear

IDirect3DRMViewport2

Clears the given viewport to the current background color. This is an enhanced version of IDirect3DRMViewport::Clear that provides flags that indicate what should be cleared. IDirect3DRMViewport::Clear takes no parameters.

Syntax

HRESULT Clear(
  DWORD dwFlags);

Parameters

dwFlags
The following flags are currently defined and can be logically combined.
D3DRMCLEAR_TARGET
Clear only the destination rendering surface.
D3DRMCLEAR_ZBUFFER
Clear only the z-buffer surface.
D3DRMCLEAR_DIRTYRECTS
Clear only the dirty rectangle list.
D3DRMCLEAR_ALL
Clear the target, z-buffer, and dirty rectangle list. This flag is analogous to using IDirect3DRMViewport::Clear.

Return Value

Returns one of the following values:
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DD_OK

Remarks

This method was introduced with DirectX version 6.0.

IDirect3DRMViewport2::Configure

IDirect3DRMViewport2

Reconfigures the origin and dimensions of a viewport.

Syntax

HRESULT Configure(
  LONG lX,
  LONG lY,
  DWORD dwWidth,
  DWORD dwHeight
  );

Parameters

lX and lY
New position of the viewport.
dwWidth and dwHeight
New width and height of the viewport.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

Remarks

This method returns D3DRMERR_BADVALUE if lX + dwWidth or lY + dwHeight are greater than the width or height of the device, or if any value of lX, lY, dwWidth, or dwHeight is less than zero.

IDirect3DRMViewport2::ForceUpdate

IDirect3DRMViewport2

Forces an area of the viewport to be updated. The specified area will be copied to the screen at the next call to the IDirect3DRMDevice3::Update method.

Syntax

HRESULT ForceUpdate(
  DWORD dwX1,
  DWORD dwY1,
  DWORD dwX2,
  DWORD dwY2
  );

Parameters

dwX1 and dwY1
Upper-left corner of area to be updated.
dwX2 and dwY2
Lower-right corner of area to be updated.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

Remarks

The system might update any region that is larger than the specified rectangle, possibly including the entire window.

IDirect3DRMViewport2::GetBack

IDirect3DRMViewport2

Retrieves the position of the back clipping plane for a viewport.

Syntax

D3DVALUE GetBack( );

Return Value

Returns a value describing the distance between the back clipping plane and the camera.

See Also

IDirect3DRMViewport2::SetBack, Viewing Frustum

IDirect3DRMViewport2::GetCamera

IDirect3DRMViewport2

Retrieves the camera for a viewport.

Syntax

HRESULT GetCamera(
  LPDIRECT3DRMFRAME3 *lpCamera
  );

Parameters

lpCamera
Pointer to the Direct3DRMFrame object representing the camera.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

See Also

IDirect3DRMViewport2::SetCamera, Camera

IDirect3DRMViewport2::GetDevice

IDirect3DRMViewport2

Retrieves the device associated with a viewport.

Syntax

HRESULT GetDevice(
  LPDIRECT3DRMDEVICE3 *lpD3DRMDevice
  );

Parameters

lpD3DRMDevice
Address of a variable that represents the device object. For more information about devices, see Output Devices.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

IDirect3DRMViewport2::GetDirect3DViewport

IDirect3DRMViewport2

Retrieves the Direct3D viewport corresponding to the current Direct3DRMViewport.

Syntax

HRESULT GetDirect3DViewport(
  LPDIRECT3DVIEWPORT * lplpD3DViewport
  );

Parameters

lplpD3DViewport
Address of a pointer that is initialized with a pointer to the Direct3DViewport object.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

IDirect3DRMViewport2::GetField

IDirect3DRMViewport2

Retrieves the field of view for a viewport.

Syntax

D3DVALUE GetField( );

Return Value

Returns a value describing the field of view.

See Also

IDirect3DRMViewport2::SetField, Viewing Frustum

IDirect3DRMViewport2::GetFront

IDirect3DRMViewport2

Retrieves the position of the front clipping plane for a viewport.

Syntax

D3DVALUE GetFront( );

Return Value

Returns a value describing the distance from the camera to the front clipping plane.

See Also

IDirect3DRMViewport2::SetFront, Viewing Frustum

IDirect3DRMViewport2::GetHeight

IDirect3DRMViewport2

Retrieves the height, in pixels, of the viewport.

Syntax

DWORD GetHeight( );

Return Value

Returns the pixel height.

IDirect3DRMViewport2::GetPlane

IDirect3DRMViewport2

Retrieves the dimensions of the viewport on the front clipping plane.

Syntax

HRESULT GetPlane(
  D3DVALUE *lpd3dvLeft,
  D3DVALUE *lpd3dvRight,
  D3DVALUE *lpd3dvBottom,
  D3DVALUE *lpd3dvTop
  );

Parameters

lpd3dvLeft, lpd3dvRight, lpd3dvBottom, and lpd3dvTop
Addresses of variables that will be filled with the dimensions of the viewport on the front clipping plane.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

See Also

IDirect3DRMViewport2::SetPlane

IDirect3DRMViewport2::GetProjection

IDirect3DRMViewport2

Retrieves the viewport's projection type. A viewport can use either orthographic or perspective projection.

Syntax

D3DRMPROJECTIONTYPE GetProjection( );

Return Value

Returns one of the members of the D3DRMPROJECTIONTYPE enumerated type.

See Also

IDirect3DRMViewport2::SetProjection

IDirect3DRMViewport2::GetUniformScaling

IDirect3DRMViewport2

Retrieves the scaling property used to scale the viewing volume into the larger window dimension.

Syntax

BOOL GetUniformScaling( );

Return Value

Returns TRUE if the viewport scales uniformly, or FALSE otherwise.

See Also

IDirect3DRMViewport2::SetUniformScaling

IDirect3DRMViewport2::GetWidth

IDirect3DRMViewport2

Retrieves the width, in pixels, of the viewport.

Syntax

DWORD GetWidth( );

Return Value

Returns the pixel width.

IDirect3DRMViewport2::GetX

IDirect3DRMViewport2

Retrieves the x-offset of the start of the viewport on a device.

Syntax

LONG GetX( );

Return Value

Returns the x-offset.

IDirect3DRMViewport2::GetY

IDirect3DRMViewport2

Retrieves the y-offset of the start of the viewport on a device.

Syntax

LONG GetY( );

Return Value

Returns the y-offset.

IDirect3DRMViewport2::Init

IDirect3DRMViewport2

Initializes a Direct3DRMViewport object.

Syntax

HRESULT Init(
  LPDIRECT3DRMDEVICE3 lpD3DRMDevice,
  LPDIRECT3DRMFRAME3 lpD3DRMFrameCamera,
  DWORD xpos,
  DWORD ypos,
  DWORD width,
  DWORD height
  );

Parameters

lpD3DRMDevice
Address of the device object associated with this viewport. For more information about devices, see Output Devices.
lpD3DRMFrameCamera
Address of the camera frame associated with this viewport.
xpos and ypos
The x- and y-coordinates of the upper-left corner of the viewport.
width and height
Width and height of the viewport.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

IDirect3DRMViewport2::InverseTransform

IDirect3DRMViewport2

Transforms the vector in the lprvSrc parameter in screen coordinates to world coordinates, and returns the result in the lprvDst parameter.

Syntax

HRESULT InverseTransform(
  D3DVECTOR * lprvDst,
  D3DRMVECTOR4D * lprvSrc
  );

Parameters

lprvDst
Address of a D3DVECTOR structure that will be filled with the result of the operation when the method returns.
lprvSrc
Address of a D3DRMVECTOR4D structure that represents the source of the operation.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

See Also

IDirect3DRMViewport2::InverseTransformVectors, IDirect3DRMViewport2::Transform

IDirect3DRMViewport2::InverseTransformVectors

IDirect3DRMViewport2

This transforms an array of vectors in the lpSrcVectors parameter in screen coordinates to world coordinates, and returns the result in the lprvDstVectors parameter

Syntax

HRESULT InverseTransformVectors(
   DWORD dwNumVectors,
   LPD3DVECTOR	lpDstVectors,
   LPD3DRMVECTOR4D lpSrcVectors);

Parameters

dwNumVectors
The number of vectors whose coordinates are to be transformed.
lpDstVectors
Destination of the transformation.
lpSrcVectors
Array of D3DRMVECTOR4D structures representing the vectors to transform.

Return Value

Returns one of the following values:
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DD_OK

Remarks

This method was introduced with DirectX version 6.0.

See Also

IDirect3DRMViewport2::TransformVectors, IDirect3DRMViewport2::InverseTransform

IDirect3DRMViewport2::Pick

IDirect3DRMViewport2

Finds a depth-sorted list of objects (and faces, if relevant) that includes the path taken in the hierarchy from the root down to the frame that contained the object.

Syntax

HRESULT Pick(
  LONG lX,
  LONG lY,
  LPDIRECT3DRMPICKEDARRAY* lplpVisuals
  );

Parameters

lX and lY
Coordinates used for picking.
lplpVisuals
Address of a pointer that is initialized with a valid pointer to the IDirect3DRMPickedArray interface if the call succeeds.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

IDirect3DRMViewport2::Render

IDirect3DRMViewport2

Renders a frame hierarchy to the given viewport. Only those visuals on the given frame and any frames below it in the hierarchy are rendered.

Syntax

HRESULT Render(
  LPDIRECT3DRMFRAME lpD3DRMFrame
  );

Parameters

lpD3DRMFrame
Address of a variable that represents the Direct3DRMFrame object that represents the frame hierarchy to be rendered.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values. This method returns an error if you try to use the IDirect3DRM3::SetOptions method to indicate right-handed support and at the same time use the older means (IDirect3DRMViewport2::SetProjection) for providing right-handed support.

IDirect3DRMViewport2::SetBack

IDirect3DRMViewport2

Sets the position of the back clipping plane for a viewport.

Syntax

HRESULT SetBack(
  D3DVALUE rvBack
  );

Parameters

rvBack
Distance between the camera and the back clipping plane. The default value is 100.0. Reasonable values depend on other viewing frustrum settings. For more information, see Viewports.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

Remarks

This method is also used to add a back clipping plane position key to a Direct3DRMViewportInterpolator object.

See Also

IDirect3DRMViewport2::GetBack, IDirect3DRMViewport2::SetFront, Viewing Frustum

IDirect3DRMViewport2::SetCamera

IDirect3DRMViewport2

Sets a camera for a viewport.

Syntax

HRESULT SetCamera(
  LPDIRECT3DRMFRAME3 lpCamera
  );

Parameters

lpCamera
Address of a variable that represents the Direct3DRMFrame object that represents the camera.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

Remarks

This method sets a viewport's position, direction, and orientation to that of the given camera frame. The view is oriented along the positive z-axis of the camera frame, with the up direction being in the direction of the positive y-axis.

See Also

IDirect3DRMViewport2::GetCamera, Camera

IDirect3DRMViewport2::SetField

IDirect3DRMViewport2

Sets the field of view for a viewport.

Syntax

HRESULT SetField(
  D3DVALUE rvField
  );

Parameters

rvField
New field of view. This value is a fraction of the viewing angle. The default value is 0.5. If this value is less than or equal to zero, this method returns the D3DRMERR_BADVALUE error. The viewing angle is defined as the 2 times the arctangent of the front clipping plane over the distance from the camera. See Viewing Frustum for more information on the viewing angle. An rvField value of 0.5 would be one-half the viewing angle A shown in the Viewing Frustum section.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

Remarks

This method is also used to add a field of view key to a Direct3DRMViewportInterpolator object.

See Also

IDirect3DRMViewport2::GetField, Viewing Frustum

IDirect3DRMViewport2::SetFront

IDirect3DRMViewport2

Sets the position of the front clipping plane for a viewport.

Syntax

HRESULT SetFront(
  D3DVALUE rvFront
  );

Parameters

rvFront
Distance from the camera to the front clipping plane. The default value is 1.0. Reasonable values depend on other viewing frustrum settings. For more information, see Viewports.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

Remarks

If the value passed is less than or equal to zero, this method returns the D3DRMERR_BADVALUE error.

This method is also used to add a front clipping plane position key to a Direct3DRMViewportInterpolator object.

See Also

IDirect3DRMViewport2::GetFront, Viewing Frustum

IDirect3DRMViewport2::SetPlane

IDirect3DRMViewport2

Sets the dimensions of the viewport on the front clipping plane, relative to the camera's z-axis.

Syntax

HRESULT SetPlane(
  D3DVALUE rvLeft,
  D3DVALUE rvRight,
  D3DVALUE rvBottom,
  D3DVALUE rvTop
  );

Parameters

rvLeft, rvRight, rvBottom, and rvTop
Minimum x-, maximum x-, minimum y-, and maximum y-coordinates, respectively, of the four sides of the viewport.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

Remarks

Unlike the IDirect3DRMViewport2::SetField method, which specifies a centered proportional viewport, this method allows you to specify a viewport of arbitrary proportion and position. For example, this method could be used to construct a sheared viewing frustum to implement a right- or left-eye stereo view.

This method is also used to add a plane key to a Direct3DRMViewportInterpolator object.

See Also

IDirect3DRMViewport2::GetPlane, IDirect3DRMViewport2::SetField

IDirect3DRMViewport2::SetProjection

IDirect3DRMViewport2

Sets the projection type for a viewport.

Syntax

HRESULT SetProjection(
  D3DRMPROJECTIONTYPE rptType
  );

Parameters

rptType
One of the members of the D3DRMPROJECTIONTYPE enumerated type.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

Remarks

Beginning with DirectX version 6.0, use IDirect3DRM3::SetOptions to specify right-handed geometry.

See Also

IDirect3DRMViewport2::GetProjection

IDirect3DRMViewport2::SetUniformScaling

IDirect3DRMViewport2

Sets the scaling property used to scale the viewing volume into the larger dimension of the window.

Syntax

HRESULT SetUniformScaling(
  BOOL bScale
  );

Parameters

bScale
New scaling property. If this parameter is TRUE, the same horizontal and vertical scaling factor is used to scale the viewing volume. Otherwise, different scaling factors are used to scale the viewing volume exactly into the window. The default setting is TRUE.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

Remarks

This method is typically used with the IDirect3DRMViewport2::SetPlane method to support banding.

See Also

IDirect3DRMViewport2::GetUniformScaling

IDirect3DRMViewport2::Transform

IDirect3DRMViewport2

Transforms the vector in the lprvSrc parameter in world coordinates to screen coordinates, and returns the result in the lprvDst parameter.

Syntax

HRESULT Transform(
  D3DRMVECTOR4D * lprvDst,
  D3DVECTOR * lprvSrc
  );

Parameters

lprvDst
Address of a D3DRMVECTOR4D structure that acts as the destination for the transformation operation.
lprvSrc
Address of a D3DVECTOR structure that acts as the source for the transformation operation.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

Remarks

The result of the transformation is a four-element homogeneous vector. The point represented by the resulting vector is visible if the following equations are true:

Equations for testing whether the point is visible

See Also

IDirect3DRMViewport2::TransformVectors, IDirect3DRMViewport2::InverseTransform

IDirect3DRMViewport2::TransformVectors

IDirect3DRMViewport2

Transforms an array of vectors in the lprvSrcVectors parameter in world coordinates to screen coordinates, and returns the result in the lprvDstVectors parameter.

Syntax

HRESULT TransformVectors(
  DWORD dwNumVectors,
  LPD3DRMVECTOR4D lpDstVectors,
  LPD3DVECTOR lpSrcVectors);

Parameters

dwNumVectors
The number of vectors to be transformed.
lpDstVectors
Array of D3DRMVECTOR4D structures representing the vectors transformed to screen coordinates.
lpSrcVectors
Array of vectors to transform.

Return Value

Returns one of the following values:
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DD_OK

Remarks

This method was introduced with DirectX version 6.0.

See Also

IDirect3DRMViewport2::Transform, IDirect3DRMViewport2::InverseTransformVectors


IDirect3DRMViewportArray

Applications use the methods of the IDirect3DRMViewportArray interface to organize viewport objects. This section is a reference to the methods of this interface. For a conceptual overview, see Viewports.

The IDirect3DRMViewportArray interface supports the following methods:
GetElement
GetSize

The IDirect3DRMViewportArray interface, like all COM interfaces, inherits the IUnknown interface methods. The IUnknown interface supports the following three methods:
AddRef
QueryInterface
Release

The Direct3DRMViewportArray object is obtained by calling the IDirect3DRM3::CreateFrame method.

IDirect3DRMViewportArray::GetElement

IDirect3DRMViewportArray

Retrieves a specified element in a Direct3DRMViewportArray object.

Syntax

HRESULT GetElement(
  DWORD index,
  LPDIRECT3DRMVIEWPORT * lplpD3DRMViewport
  );

Parameters

index
Element in the array.
lplpD3DRMViewport
Address that will be filled with a pointer to an IDirect3DRMViewport interface.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

Remarks

You can use QueryInterface to obtain a pointer to the version of IDirect3DRMViewport that you want, for example, IDirect3DRMViewport2. You cannot simply cast the lplpD3DRMViewport parameter to a different version. You must use QueryInterface.

IDirect3DRMViewportArray::GetSize

IDirect3DRMViewportArray

Retrieves the number of elements contained in a Direct3DRMViewportArray object.

Syntax

DWORD GetSize( );

Return Value

Returns the number of elements.


IDirect3DRMVisual

IDirect3DRMVisual does not provide any Microsoft® Direct3D® Retained Mode methods, but the interfaces for the visual objects derive from the IDirect3DRMVisual interface. For a complete interface hierarchy, see the Interface Hierarchy Chart.

Visuals are objects that can be rendered in a scene. Visuals are visible only when they are added to a frame in that scene. An application can add a visual to a frame by using the IDirect3DRMFrame3::AddVisual method. The frame provides the visual with position and orientation for rendering.

The following interfaces derive from IDirect3DRMVisual.

  • IDirect3DRMFrame3
  • IDirect3DRMMesh
  • IDirect3DRMMeshBuilder3
  • IDirect3DRMProgressiveMesh
  • IDirect3DRMShadow2
  • IDirect3DRMTexture3
  • IDirect3DRMUserVisual

The IDirect3DRMVisual interface, like all Component Object Model (COM) interfaces, inherits the IUnknown interface methods. The IUnknown interface supports the following three methods:
AddRef
QueryInterface
Release


IDirect3DRMVisualArray

Applications use the methods of the IDirect3DRMVisualArray interface to organize groups of visual objects.

Visuals are objects that can be rendered in a scene. Visuals are visible only when they are added to a frame in that scene. An application can add a visual to a frame by using the IDirect3DRMFrame3::AddVisual method. The frame provides the visual with position and orientation for rendering.

Note: although there is a IDirect3DRMVisual COM interface, it has no Direct3D Retained Mode-specific methods.

The most common visual types are Direct3DRMMeshBuilder3 and Direct3DRMTexture objects.

The IDirect3DRMVisualArray interface supports the following methods:
GetElement
GetSize

The IDirect3DRMVisualArray interface, like all COM interfaces, inherits the IUnknown interface methods. The IUnknown interface supports the following three methods:
AddRef
QueryInterface
Release

The Direct3DRMVisualArray object is obtained by calling the IDirect3DRMFrame3::GetVisuals method.

IDirect3DRMVisualArray::GetElement

IDirect3DRMVisualArray

Retrieves a specified element in a Direct3DRMVisualArray object.

Syntax

HRESULT GetElement(
  DWORD index,
  LPDIRECT3DRMVISUAL * lplpD3DRMVisual
  );

Parameters

index
Element in the array.
lplpD3DRMVisual
Address that will be filled with a pointer to an IDirect3DRMVisual interface.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

IDirect3DRMVisualArray::GetSize

IDirect3DRMVisualArray

Retrieves the number of elements contained in a Direct3DRMVisualArray object.

Syntax

DWORD GetSize( );

Return Value

Returns the number of elements.


IDirect3DRMWinDevice

Applications use the methods of the IDirect3DRMWinDevice interface to respond to window messages in a window procedure. This section is a reference to the methods of this interface. For a conceptual overview, see Window Management.

The IDirect3DRMWinDevice interface supports the following methods:
HandleActivate
HandlePaint

The IDirect3DRMWinDevice interface, like all Component Object Model (COM) interfaces, inherits the IUnknown interface methods. The IUnknown interface supports the following three methods:
AddRef
QueryInterface
Release

The Direct3DRMWinDevice object is obtained by calling the IDirect3DRMObject::QueryInterface method and specifying IID_IDirect3DRMWinDevice, or by calling a method such as IDirect3DRM3::CreateDeviceFromD3D. The IDirect3DRMWinDevice methods are inherited from the IDirect3DRMDevice3 interface.

IDirect3DRMWinDevice::HandleActivate

IDirect3DRMWinDevice

Responds to a Microsoft® Windows®w WM_ACTIVATE message. This ensures that the colors are correct in the active rendering window.

Syntax

HRESULT HandleActivate(
  WORD wParam
  );

Parameters

wParam
WPARAM parameter passed to the message-processing procedure with the WM_ACTIVATE message.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

IDirect3DRMWinDevice::HandlePaint

IDirect3DRMWinDevice

Responds to a Windows WM_PAINT message. The hDC parameter should be taken from the PAINTSTRUCT structure given to the Windows BeginPaint function. This method should be called before repainting any application areas in the window because it may repaint areas outside the viewports that have been created on the device.

Syntax

HRESULT HandlePaint(
  HDC hDC
  );

Parameters

hDC
Handle of the device context (DC).

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.


IDirect3DRMWrap

Applications use the methods of the IDirect3DRMWrap interface to work with wrap objects. This section is a reference to the methods of this interface. For a conceptual overview, see Wraps.

The methods of the IDirect3DRMWrap interface can be organized into the following groups:
Initialization | Init
Wrap | Apply
ApplyRelative

The IDirect3DRMWrap interface, like all Component Object Model (COM) interfaces, inherits the IUnknown interface methods. The IUnknown interface supports the following three methods:
AddRef
QueryInterface
Release

In addition, the IDirect3DRMWrap interface inherits the following methods from the IDirect3DRMObject interface:
AddDestroyCallback
Clone
DeleteDestroyCallback
GetAppData
GetClassName
GetName
SetAppData
SetName

The Direct3DRMWrap object is obtained by using the IDirect3DRM3::CreateWrap method.

IDirect3DRMWrap::Apply

IDirect3DRMWrap

Applies a Direct3DRMWrap object to its destination object. The destination object is typically a face or a mesh.

Syntax

HRESULT Apply(
  LPDIRECT3DRMOBJECT lpObject
  );

Parameters

lpObject
Address of the destination object.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

See Also

IDirect3DRM3::CreateWrap

IDirect3DRMWrap::ApplyRelative

IDirect3DRMWrap

Applies the wrap to the vertices of the object, first transforming each vertex by the frame's world transformation and the inverse world transformation of the wrap's reference frame.

Syntax

HRESULT ApplyRelative(
  LPDIRECT3DRMFRAME frame,
  LPDIRECT3DRMOBJECT mesh
  );

Parameters

frame
Direct3DRMFrame object containing the object to wrap.
mesh
Direct3DRMWrap object to apply.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

See Also

IDirect3DRM3::CreateWrap

IDirect3DRMWrap::Init

IDirect3DRMWrap

Initializes a Direct3DRMWrap object.

Syntax

HRESULT Init(
  D3DRMWRAPTYPE d3drmwt,
  LPDIRECT3DRMFRAME lpd3drmfRef,
  D3DVALUE ox,
  D3DVALUE oy,
  D3DVALUE oz,
  D3DVALUE dx,
  D3DVALUE dy,
  D3DVALUE dz,
  D3DVALUE ux,
  D3DVALUE uy,
  D3DVALUE uz,
  D3DVALUE ou,
  D3DVALUE ov,
  D3DVALUE su,
  D3DVALUE sv
  );

Parameters

d3drmwt
One of the members of the D3DRMWRAPTYPE enumerated type.
lpd3drmfRef
Address of a Direct3DRMFrame object representing the reference frame for this Direct3DRMWrap object.
ox, oy, and oz
Origin of the wrap.
dx, dy, and dz
The z-axis of the wrap.
ux, uy, and uz
The y-axis of the wrap.
ou and ov
Origin of the texture.
su and sv
Scale factor of the texture.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

See Also

IDirect3DRM3::CreateWrap


Nonmember Functions

The Microsoft® Direct3D® Retained Mode nonmember functions are:

  • D3DRMColorGetAlpha
  • D3DRMColorGetBlue
  • D3DRMColorGetGreen
  • D3DRMColorGetRed
  • D3DRMCreateColorRGB
  • D3DRMCreateColorRGBA
  • D3DRMMatrixFromQuaternion
  • D3DRMQuaternionFromRotation
  • D3DRMQuaternionMultiply
  • D3DRMQuaternionSlerp
  • D3DRMVectorAdd
  • D3DRMVectorCrossProduct
  • D3DRMVectorDotProduct
  • D3DRMVectorModulus
  • D3DRMVectorNormalize
  • D3DRMVectorRandom
  • D3DRMVectorReflect
  • D3DRMVectorRotate
  • D3DRMVectorScale
  • D3DRMVectorSubtract
  • Direct3DRMCreate

D3DRMColorGetAlpha

Retrieves the alpha component of a color.

Syntax

D3DVALUE D3DRMColorGetAlpha(
  D3DCOLOR d3drmc
  );

Parameters

d3drmc
Color from which the alpha component is retrieved. A value between 0 and 255.

Return Value

Returns the alpha value if successful, or zero otherwise.

See Also

D3DRMColorGetBlue, D3DRMColorGetGreen, D3DRMColorGetRed

D3DRMColorGetBlue

Retrieves the blue component of a color.

Syntax

D3DVALUE D3DRMColorGetBlue(
  D3DCOLOR d3drmc
  );

Parameters

d3drmc
Color from which the blue component is retrieved. A value between 0 and 255.

Return Value

Returns the blue value if successful, or zero otherwise.

See Also

D3DRMColorGetAlpha, D3DRMColorGetGreen, D3DRMColorGetRed

D3DRMColorGetGreen

Retrieves the green component of a color.

Syntax

D3DVALUE D3DRMColorGetGreen(
  D3DCOLOR d3drmc
  );

Parameters

d3drmc
Color from which the green component is retrieved. A value between 0 and 255.

Return Value

Returns the green value if successful, or zero otherwise.

See Also

D3DRMColorGetAlpha, D3DRMColorGetBlue, D3DRMColorGetRed

D3DRMColorGetRed

Retrieves the red component of a color.

Syntax

D3DVALUE D3DRMColorGetRed(
  D3DCOLOR d3drmc
  );

Parameters

d3drmc
Color from which the red component is retrieved.

Return Value

Returns the red value if successful, or zero otherwise.

See Also

D3DRMColorGetAlpha, D3DRMColorGetBlue, D3DRMColorGetGreen

D3DRMCreateColorRGB

Creates an RGB color from supplied red, green, and blue components.

Syntax

D3DCOLOR D3DRMCreateColorRGB(
  D3DVALUE red,
  D3DVALUE green,
  D3DVALUE blue
  );

Parameters

red, green, and blue
Components of the RGB color.

Return Value

Returns the new RGB value if successful, or zero otherwise.

See Also

D3DRMCreateColorRGBA

D3DRMCreateColorRGBA

Creates an RGBA color from supplied red, green, blue, and alpha components.

Syntax

D3DCOLOR D3DRMCreateColorRGBA(
  D3DVALUE red,
  D3DVALUE green,
  D3DVALUE blue,
  D3DVALUE alpha
  );

Parameters

red, green, blue, and alpha
Components of the RGBA color. Values between 0 and 1.

Return Value

Returns the new RGBA value if successful, or zero otherwise.

See Also

D3DRMCreateColorRGB

D3DRMMatrixFromQuaternion

Calculates the matrix for the rotation that a unit quaternion represents.

Syntax

void D3DRMMatrixFromQuaternion (
  D3DRMMATRIX4D mat,
  LPD3DRMQUATERNION lpquat
  );

Parameters

mat
Address that will contain the calculated matrix when the function returns. (The D3DRMMATRIX4D type is an array.)
lpquat
Address of the D3DRMQUATERNION structure.

Return Value

No return value.

D3DRMQuaternionFromRotation

Retrieves a unit quaternion that represents a rotation of a specified number of radians around the given axis.

Syntax

LPD3DRMQUATERNION D3DRMQuaternionFromRotation(
  LPD3DRMQUATERNION lpquat,
  LPD3DVECTOR lpv,
  D3DVALUE theta
  );

Parameters

lpquat
Address of a D3DRMQUATERNION structure that will contain the result of the operation.
lpv
Address of a D3DVECTOR structure specifying the axis of rotation.
theta
Number of radians to rotate around the axis specified by the lpv parameter.

Return Value

Returns the address of the unit quaternion that was passed as the first parameter if successful, or zero otherwise.

D3DRMQuaternionMultiply

Calculates the product of two quaternion structures.

Syntax

LPD3DRMQUATERNION D3DRMQuaternionMultiply(
  LPD3DRMQUATERNION lpq,
  LPD3DRMQUATERNION lpa,
  LPD3DRMQUATERNION lpb
  );

Parameters

lpq
Address of the D3DRMQUATERNION structure that will contain the product of the multiplication.
lpa and lpb
Addresses of the D3DRMQUATERNION structures that will be multiplied together.

Return Value

Returns the address of the quaternion that was passed as the first parameter if successful, or zero otherwise.

D3DRMQuaternionSlerp

Interpolates between two quaternion structures, using spherical linear interpolation.

Syntax

LPD3DRMQUATERNION D3DRMQuaternionSlerp(
  LPD3DRMQUATERNION lpq,
  LPD3DRMQUATERNION lpa,
  LPD3DRMQUATERNION lpb,
  D3DVALUE alpha
  );

Parameters

lpq
Address of the D3DRMQUATERNION structure that will contain the interpolation.
lpa and lpb
Addresses of the D3DRMQUATERNION structures that are used as the starting and ending points for the interpolation, respectively.
alpha
Value between 0 and 1 that specifies how far to interpolate between lpa and lpb.

Return Value

Returns the address of the quaternion that was passed as the first parameter if successful, or zero otherwise.

D3DRMVectorAdd

Adds two vectors.

Syntax

LPD3DVECTOR D3DRMVectorAdd(
  LPD3DVECTOR lpd,
  LPD3DVECTOR lps1,
  LPD3DVECTOR lps2
  );

Parameters

lpd
Address of a D3DVECTOR structure that will contain the result of the addition.
lps1 and lps2
Addresses of the D3DVECTOR structures that will be added together.

Return Value

Returns the address of the vector that was passed as the first parameter if successful, or zero otherwise.

D3DRMVectorCrossProduct

Calculates the cross product of the two vector arguments.

Syntax

LPD3DVECTOR D3DRMVectorCrossProduct(
  LPD3DVECTOR lpd,
  LPD3DVECTOR lps1,
  LPD3DVECTOR lps2
  );

Parameters

lpd
Address of a D3DVECTOR structure that will contain the result of the cross product.
lps1 and lps2
Addresses of the D3DVECTOR structures from which the cross product is produced.

Return Value

Returns the address of the vector that was passed as the first parameter if successful, or zero otherwise.

D3DRMVectorDotProduct

Returns the vector dot product.

Syntax

D3DVALUE D3DRMVectorDotProduct(
  LPD3DVECTOR lps1,
  LPD3DVECTOR lps2
  );

Parameters

lps1 and lps2
Addresses of the D3DVECTOR structures from which the dot product is produced.

Return Value

Returns the result of the dot product if successful, or zero otherwise.

D3DRMVectorModulus

Returns the length of a vector according to the following formula:

Square root of x squared plus y squared plus z squared

Syntax

D3DVALUE D3DRMVectorModulus(
  LPD3DVECTOR lpv
  );

Parameters

lpv
Address of the D3DVECTOR structure whose length is returned.

Return Value

Returns the length of the D3DVECTOR structure if successful, or zero otherwise.

D3DRMVectorNormalize

Scales a vector so that its modulus is 1.

Syntax

LPD3DVECTOR D3DRMVectorNormalize(
  LPD3DVECTOR lpv
  );

Parameters

lpv
Address of a D3DVECTOR structure that will contain the result of the scaling operation.

Return Value

Returns the address of the vector that was passed as the first parameter if successful, or zero if an error occurs. An example of an error is if a zero vector were passed.

D3DRMVectorRandom

Returns a random unit vector.

Syntax

LPD3DVECTOR D3DRMVectorRandom(
  LPD3DVECTOR lpd
  );

Parameters

lpd
Address of a D3DVECTOR structure that will contain a random unit vector.

Return Value

Returns the address of the vector that was passed as the first parameter if successful, or zero otherwise.

D3DRMVectorReflect

Reflects a ray about a given normal.

Syntax

LPD3DVECTOR D3DRMVectorReflect(
  LPD3DVECTOR lpd,
  LPD3DVECTOR lpRay,
  LPD3DVECTOR lpNorm
  );

Parameters

lpd
Address of a D3DVECTOR structure that will contain the result of the operation.
lpRay
Address of a D3DVECTOR structure that will be reflected about a normal.
lpNorm
Address of a D3DVECTOR structure specifying the normal about which the vector specified in lpRay is reflected.

Return Value

Returns the address of the vector that was passed as the first parameter if successful, or zero otherwise.

D3DRMVectorRotate

Rotates a vector around a given axis. Returns a normalized vector if successful.

Syntax

LPD3DVECTOR D3DRMVectorRotate(
  LPD3DVECTOR lpr,
  LPD3DVECTOR lpv,
  LPD3DVECTOR lpaxis,
  D3DVALUE theta
  );

Parameters

lpr
Address of a D3DVECTOR structure that will contain the normalized result of the operation.
lpv
Address of a D3DVECTOR structure that will be rotated around the given axis.
lpaxis
Address of a D3DVECTOR structure that is the axis of rotation.
theta
The amount of rotation in radians.

Return Value

Returns the address of the vector that was passed as the first parameter if successful, or zero otherwise. This vector is normalized.

D3DRMVectorScale

Scales a vector uniformly in all three axes.

Syntax

LPD3DVECTOR D3DRMVectorScale(
  LPD3DVECTOR lpd,
  LPD3DVECTOR lps,
  D3DVALUE factor
  );

Parameters

lpd
Address of a D3DVECTOR structure that will contain the result of the operation.
lps
Address of a D3DVECTOR structure that this function scales.
factor
Scaling factor. A value of 1 does not change the scaling; a value of 2 doubles it, and so on.

Return Value

Returns the address of the vector that was passed as the first parameter if successful, or zero otherwise.

D3DRMVectorSubtract

Subtracts two vectors.

Syntax

LPD3DVECTOR D3DRMVectorSubtract(
  LPD3DVECTOR lpd,
  LPD3DVECTOR lps1,
  LPD3DVECTOR lps2
  );

Parameters

lpd
Address of a D3DVECTOR structure that will contain the result of the operation.
lps1
Address of the D3DVECTOR structure from which lps2 is subtracted.
lps2
Address of the D3DVECTOR structure that is subtracted from lps1.

Return Value

Returns the address of the vector that was passed as the first parameter if successful, or zero otherwise.

Direct3DRMCreate

Creates an instance of a Direct3DRM object.

Syntax

HRESULT Direct3DRMCreate(
  LPDIRECT3DRM FAR * lplpD3DRM
  );

Parameters

lplpD3DRM
Address of a pointer that will be initialized with a valid Direct3DRM pointer if the call succeeds.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

See Also

IDirect3DRMObject


Constants

Microsoft® Direct3D® Retained Mode includes other type definitions, not included in structures or enumerated types. These are:

  • D3DRMANIMATIONOPTIONS
  • D3DRMCOLORMODEL
  • D3DRMINTERPOLATIONOPTIONS
  • D3DRMLOADOPTIONS
  • D3DRMMAPPING
  • D3DRMMATRIX4D
  • D3DRMSAVEOPTIONS

D3DRMANIMATIONOPTIONS

Specifies values used by the IDirect3DRMAnimation2::GetOptions and IDirect3DRMAnimation2::SetOptions methods and the D3DRMANIMATIONKEY structure to define how animations are played.

Syntax

typedef DWORD D3DRMANIMATIONOPTIONS;
#define D3DRMANIMATION_CLOSED             0x02L
#define D3DRMANIMATION_LINEARPOSITION     0x04L
#define D3DRMANIMATION_OPEN               0x01L
#define D3DRMANIMATION_POSITION           0x00000020L
#define D3DRMANIMATION_SCALEANDROTATION   0x00000010L
#define D3DRMANIMATION_SPLINEPOSITION     0x08L

Parameters

D3DRMANIMATION_CLOSED
Animation plays continually, looping back to the beginning when it reaches the end. In a closed animation, if you want a smooth transition from the end to the beginning, the last key in the animation should be a repeat of the first. This repeated key is used to indicate the time difference between the last and first keys in the looping animation. However, if the last key is not a repeat of the first, it is no longer being ignored in the new interfaces (IDirect3DRMAnimation2, IDirect3DRMAnimationSet2). It takes effect, and then the animation jumps immediately back to the beginning.
D3DRMANIMATION_LINEARPOSITION
Animation's position is set linearly.
D3DRMANIMATION_OPEN
Animation plays once and stops.
D3DRMANIMATION_POSITION
Animation's position matrix should overwrite any transformation matrices that could be set by other methods.
D3DRMANIMATION_SCALEANDROTATION
Animation's scale and rotation matrix should overwrite any transformation matrices that could be set by other methods.
D3DRMANIMATION_SPLINEPOSITION
Animation's position is set using splines.

D3DRMCOLORMODEL

Describes the color model implemented by the device. For more information, see the D3DCOLORMODEL enumerated type.

Syntax

typedef D3DCOLORMODEL D3DRMCOLORMODEL;

See Also

D3DCOLORMODEL

D3DRMINTERPOLATIONOPTIONS

Defines options for the IDirect3DRMInterpolator::Interpolate method. These options modify how the object is loaded.

Syntax

typedef DWORD D3DRMINTERPOLATIONOPTIONS;
#define D3DRMINTERPOLATION_OPEN 0x01L
#define D3DRMINTERPOLATION_CLOSED 0x02L
#define D3DRMINTERPOLATION_NEAREST 0x0100L
#define D3DRMINTERPOLATION_LINEAR 0x04L
#define D3DRMINTERPOLATION_SPLINE 0x08L
#define D3DRMINTERPOLATION_VERTEXCOLOR 0x40L
#define D3DRMINTERPOLATION_SLERPNORMALS 0x80L

Parameters

D3DRMINTERPOLATION_OPEN
First and last keys of each key chain will fix the interpolated values outside of the index span.
D3DRMINTERPOLATION_CLOSED
The interpolation is cyclic. The keys effectively repeat infinitely with a period equal to the index span. For compatibility with animations, any key with an index equal to the end of the span is ignored.
D3DRMINTERPOLATION_NEAREST
Nearest key value is used for determining in-between values on each key chain (execution thread).
D3DRMINTERPOLATION_LINEAR
Linear interpolation between the two nearest keys is used for determining in-between values on each key chain.
D3DRMINTERPOLATION_SPLINE
B-spline blending function on the four nearest keys is used for determining in-between values on each key chain.
D3DRMINTERPOLATION_VERTEXCOLOR
Specifies that vertex colors should be interpolated. Only affects the interpolation of IDirect3DRMMesh::SetVertices.
D3DRMINTERPOLATION_SLERPNORMALS
Specifies that vertex normals should be spherically interpolated (not currently implemented). Only affects the interpolation of IDirect3DRMMesh::SetVertices.

D3DRMLOADOPTIONS

Defines options for the IDirect3DRM3::Load, IDirect3DRMAnimationSet2::Load, IDirect3DRMFrame3::Load, IDirect3DRMMeshBuilder3::Load, and IDirect3DRMProgressiveMesh::Load methods. These options modify how the object is loaded.

Syntax

typedef DWORD D3DRMLOADOPTIONS;
#define D3DRMLOAD_FROMFILE             0x00L
#define D3DRMLOAD_FROMRESOURCE         0x01L
#define D3DRMLOAD_FROMMEMORY           0x02L
#define D3DRMLOAD_FROMURL              0x08L
#define D3DRMLOAD_BYNAME               0x10L
#define D3DRMLOAD_BYPOSITION           0x20L
#define D3DRMLOAD_BYGUID               0x30L
#define D3DRMLOAD_FIRST                0x40L
#define D3DRMLOAD_INSTANCEBYREFERENCE  0x100L
#define D3DRMLOAD_INSTANCEBYCOPYING    0x200L
#define D3DRMLOAD_ASYNCHRONOUS         0x400L

Parameters

Source flags
D3DRMLOAD_FROMFILE
Load from a file. This is the default setting.
D3DRMLOAD_FROMRESOURCE
Load from a resource. If this flag is specified, the lpvObjSource parameter of the calling Load method must point to a D3DRMLOADRESOURCE structure.
D3DRMLOAD_FROMMEMORY
Load from memory. If this flag is specified, the lpvObjSource parameter of the calling Load method must point to a D3DRMLOADMEMORY structure.
D3DRMLOAD_FROMURL
Load from an URL.
Identifier flags
D3DRMLOAD_BYNAME
Load any object by using a specified name.
D3DRMLOAD_BYPOSITION
Load a stand-alone object based on a given zero-based position (that is, the nth object in the file). Stand-alone objects can contain other objects, but are not contained by any other objects.
D3DRMLOAD_BYGUID
Load any object by using a specified globally unique identifier (GUID).
D3DRMLOAD_FIRST
The default setting. Load the first stand-alone object of the given type (for example, a mesh if the application uses IDirect3DRMMeshBuilder3::Load). Stand-alone objects can contain other objects, but are not contained by any other objects.
Instance flags
D3DRMLOAD_INSTANCEBYREFERENCE
Check whether an object already exists with the same name as specified and, if so, use an instance of that object instead of creating a new one.
D3DRMLOAD_INSTANCEBYCOPYING
Check whether an object already exists with the same name as specified and, if so, copy that object.
Source flags
D3DRMLOAD_ASYNCHRONOUS
The Load call will return immediately. It is up to the application to use events to find out how the load is progressing. By default, loading is done synchronously, and the Load call will not return until all data has been loaded or an error occurs.

Remarks

Each of the Load methods uses an lpvObjSource parameter to specify the source of the object and an lpvObjID parameter to identify the object. The system interprets the contents of the lpvObjSource parameter based on the choice of source flags, and it interprets the contents of the lpvObjID parameter based on the choice of identifier flags.

The instance flags do not change the interpretation of any of the parameters. By using the D3DRMLOAD_INSTANCEBYREFERENCE flag, it is possible for an application to load the same file twice without creating any new objects. If an object does not have a name, setting the D3DRMLOAD_INSTANCEBYREFERENCE flag has the same effect as setting the D3DRMLOAD_INSTANCEBYCOPYING flag—the loader creates each unnamed object as a new one, even if some of the objects are identical.

D3DRMMAPPING

Specifies values used by the IDirect3DRMMesh::GetGroupMapping and IDirect3DRMMesh::SetGroupMapping methods to define how textures are mapped to a group.

Syntax

typedef DWORD D3DRMMAPPING, D3DRMMAPPINGFLAG;
static const D3DRMMAPPINGFLAG D3DRMMAP_WRAPU = 1;
static const D3DRMMAPPINGFLAG D3DRMMAP_WRAPV = 2;
static const D3DRMMAPPINGFLAG D3DRMMAP_PERSPCORRECT = 4;

Parameters

D3DRMMAPPINGFLAG
Type equivalent to D3DRMMAPPING.
D3DRMMAP_WRAPU
Texture wraps in the u-direction.
D3DRMMAP_WRAPV
Texture wraps in the v-direction.
D3DRMMAP_PERSPCORRECT
Texture wrapping is perspective-corrected.

Remarks

The D3DRMMAP_WRAPU and D3DRMMAP_WRAPV flags determine how the rasterizer interprets texture coordinates. The rasterizer always interpolates the shortest distance between texture coordinates; that is, a line. The path taken by this line, and the valid values for the u- and v-coordinates, varies with the use of the wrapping flags. If either or both flags are set, the line can wrap around the texture edge in the u- or v- direction, as if the texture had a cylindrical or toroidal topology. For more information, see Wraps.

See Also

Wraps, IDirect3DRMMesh::GetGroupMapping, IDirect3DRMMesh::SetGroupMapping

D3DRMMATRIX4D

Expresses a transformation as an array. The organization of the matrix entries is D3DRMMATRIX4D[row][column].

Syntax

typedef D3DVALUE D3DRMMATRIX4D[4][4];

See Also

IDirect3DRMFrame3::AddTransform, IDirect3DRMFrame3::GetTransform

D3DRMSAVEOPTIONS

Defines options for the IDirect3DRMMeshBuilder3::Save method.

Syntax

typedef DWORD D3DRMSAVEOPTIONS;
#define D3DRMXOFSAVE_NORMALS 1
#define D3DRMXOFSAVE_TEXTURECOORDINATES 2
#define D3DRMXOFSAVE_MATERIALS 4
#define D3DRMXOFSAVE_TEXTURENAMES 8
#define D3DRMXOFSAVE_ALL 15
#define D3DRMXOFSAVE_TEMPLATES 16
#define D3DRMSAVE_TEXTURETOPOLOGY 32

Parameters

D3DRMXOFSAVE_NORMALS
Save normal vectors in addition to the basic geometry.
D3DRMXOFSAVE_TEXTURECOORDINATES
Save texture coordinates in addition to the basic geometry.
D3DRMXOFSAVE_MATERIALS
Save materials in addition to the basic geometry.
D3DRMXOFSAVE_TEXTURENAMES
Save texture names in addition to the basic geometry.
D3DRMXOFSAVE_ALL
Save normal vectors, texture coordinates, materials, and texture names in addition to the basic geometry.
D3DRMXOFSAVE_TEMPLATES
Save templates with the file. By default, templates are not saved.
D3DRMSAVE_TEXTURETOPOLOGY
Save the mesh's face wrap values (set by IDirect3DRMMeshBuilder3::SetTextureTopology or IDirect3DRMFace2::SetTextureTopology). This flag is not included when you pass D3DRMXOFSAVE_ALL to the Save method. You should pass D3DRMSAVE_TEXTURETOPOLOGY|D3DRMXOFSAVE_ALL if you want to save everything. You only need to pass this flag when you have called IDirect3DRMMeshBuilder3::SetTextureTopology or IDirect3DRMFace2::SetTextureTopology and want to preserve the values you set.


Enumerated Types

The Microsoft® Direct3D® Retained Mode enumerated types are:

  • D3DRMCOLORSOURCE
  • D3DRMCOMBINETYPE
  • D3DRMFILLMODE
  • D3DRMFOGMODE
  • D3DRMFRAMECONSTRAINT
  • D3DRMLIGHTMODE
  • D3DRMLIGHTTYPE
  • D3DRMMATERIALMODE
  • D3DRMPALETTEFLAGS
  • D3DRMPROJECTIONTYPE
  • D3DRMRENDERQUALITY
  • D3DRMSHADEMODE
  • D3DRMSORTMODE
  • D3DRMTEXTUREQUALITY
  • D3DRMUSERVISUALREASON
  • D3DRMWRAPTYPE
  • D3DRMXOFFORMAT
  • D3DRMZBUFFERMODE

D3DRMCOLORSOURCE

Describes the color source of a Direct3DRMMeshBuilder3 object. You can set the color source by using the IDirect3DRMMeshBuilder3::SetColorSource method. To retrieve it, use the IDirect3DRMMeshBuilder3::GetColorSource method.

Syntax

typedef enum _D3DRMCOLORSOURCE{
    D3DRMCOLOR_FROMFACE,
    D3DRMCOLOR_FROMVERTEX
} D3DRMCOLORSOURCE;

Values

D3DRMCOLOR_FROMFACE
Object's color source is a face.
D3DRMCOLOR_FROMVERTEX
Object's color source is a vertex.

See Also

IDirect3DRMMeshBuilder3::SetColorSource, IDirect3DRMMeshBuilder3::GetColorSource

D3DRMCOMBINETYPE

Specifies how to combine two matrices.

Syntax

typedef enum _D3DRMCOMBINETYPE{
    D3DRMCOMBINE_REPLACE,
    D3DRMCOMBINE_BEFORE,
    D3DRMCOMBINE_AFTER
} D3DRMCOMBINETYPE;

Values

D3DRMCOMBINE_REPLACE
Supplied matrix replaces the frame's current matrix.
D3DRMCOMBINE_BEFORE
Supplied matrix is multiplied with the frame's current matrix and precedes the current matrix in the calculation.
D3DRMCOMBINE_AFTER
Supplied matrix is multiplied with the frame's current matrix and follows the current matrix in the calculation.

Remarks

The order of the supplied and current matrices when they are multiplied is important because matrix multiplication is not commutative.

See Also

IDirect3DRMFrame3::AddRotation, IDirect3DRMFrame3::AddScale, IDirect3DRMFrame3::AddTransform, IDirect3DRMFrame3::AddTranslation

D3DRMFILLMODE

Used to define the D3DRMRENDERQUALITY type.

Syntax

typedef enum _D3DRMFILLMODE {
    D3DRMFILL_POINTS    = 0 * D3DRMLIGHT_MAX,
    D3DRMFILL_WIREFRAME = 1 * D3DRMLIGHT_MAX,
    D3DRMFILL_SOLID     = 2 * D3DRMLIGHT_MAX,
    D3DRMFILL_MASK      = 7 * D3DRMLIGHT_MAX,
    D3DRMFILL_MAX       = 8 * D3DRMLIGHT_MAX
} D3DRMFILLMODE;

Values

D3DRMFILL_POINTS
Fills points only; minimum fill mode.
D3DRMFILL_WIREFRAME
Fill wire frames.
D3DRMFILL_SOLID
Fill solid objects.
D3DRMFILL_MASK
Fill using a mask.
D3DRMFILL_MAX
Maximum value for fill mode.

See Also

D3DRMLIGHTMODE, D3DRMSHADEMODE, D3DRMRENDERQUALITY

D3DRMFOGMODE

Contains values that specify how rapidly and in what ways the fog effect intensifies with increasing distance from the camera.

In monochromatic (ramp) lighting mode, fog works properly only when the fog color is black. (If there is no lighting, any fog color will work, since in this case any fog color is effectively black.)

Syntax

typedef enum _D3DRMFOGMODE{
    D3DRMFOG_LINEAR,
    D3DRMFOG_EXPONENTIAL,
    D3DRMFOG_EXPONENTIALSQUARED
} D3DRMFOGMODE;

Values

D3DRMFOG_LINEAR
Fog effect intensifies linearly between the start and end points, according to the following formula:

Equation showing linear increase of fog effect with distance

This is the only fog mode currently supported.

D3DRMFOG_EXPONENTIAL
Fog effect intensifies exponentially, according to the following formula:

Equation showing exponential increase of fog effect with distance

D3DRMFOG_EXPONENTIALSQUARED
Fog effect intensifies exponentially with the square of the distance, according to the following formula:

Equation showing exponential increase of fog effect with distance squared

Remarks

Note that fog can be considered a measure of visibility—the lower the fog value produced by one of the fog equations, the less visible an object is.

You can specify the fog's density and start and end points by using the IDirect3DRMFrame3::SetSceneFogParams method. In the formulas for the exponential fog modes, e is the base of the natural logarithms; its value is approximately 2.71828.

See Also

IDirect3DRMFrame3::SetSceneFogMode, IDirect3DRMFrame3::SetSceneFogParams

D3DRMFRAMECONSTRAINT

Describes the axes of rotation to constrain when viewing a Direct3DRMFrame object. The IDirect3DRMFrame3::LookAt method uses this enumerated type.

Syntax

typedef enum _D3DRMFRAMECONSTRAINT {
    D3DRMCONSTRAIN_Z,
    D3DRMCONSTRAIN_Y,
    D3DRMCONSTRAIN_X
} D3DRMFRAMECONSTRAINT;

Values

D3DRMCONSTRAIN_Z
Use only x- and y- rotations.
D3DRMCONSTRAIN_Y
Use only x- and z- rotations.
D3DRMCONSTRAIN_X
Use only y- and z- rotations.

See Also

IDirect3DRMFrame3::LookAt

D3DRMLIGHTMODE

Used to define the D3DRMRENDERQUALITY type.

Syntax

typedef enum _D3DRMLIGHTMODE {
    D3DRMLIGHT_OFF      = 0 * D3DRMSHADE_MAX,
    D3DRMLIGHT_ON       = 1 * D3DRMSHADE_MAX,
    D3DRMLIGHT_MASK     = 7 * D3DRMSHADE_MAX,
    D3DRMLIGHT_MAX      = 8 * D3DRMSHADE_MAX
} D3DRMLIGHTMODE;

Values

D3DRMLIGHT_OFF
Lighting is off.
D3DRMLIGHT_ON
Lighting is on.
D3DRMLIGHT_MASK
Lighting uses a mask.
D3DRMLIGHT_MAX
Maximum lighting mode.

See Also

D3DRMFILLMODE, D3DRMSHADEMODE, D3DRMRENDERQUALITY

D3DRMLIGHTTYPE

Defines the light type in uses to the IDirect3DRM3::CreateLight method.

Syntax

typedef enum _D3DRMLIGHTTYPE{
    D3DRMLIGHT_AMBIENT,
    D3DRMLIGHT_POINT,
    D3DRMLIGHT_SPOT,
    D3DRMLIGHT_DIRECTIONAL,
    D3DRMLIGHT_PARALLELPOINT
} D3DRMLIGHTTYPE;

Values

D3DRMLIGHT_AMBIENT
Light is an ambient source.
D3DRMLIGHT_POINT
Light is a point source.
D3DRMLIGHT_SPOT
Light is a spotlight source.
D3DRMLIGHT_DIRECTIONAL
Light is a directional source.
D3DRMLIGHT_PARALLELPOINT
Light is a parallel point source.

D3DRMMATERIALMODE

Describes the source of material information for visuals rendered with a frame.

Syntax

typedef enum _D3DRMMATERIALMODE{
    D3DRMMATERIAL_FROMMESH,
    D3DRMMATERIAL_FROMPARENT,
    D3DRMMATERIAL_FROMFRAME
} D3DRMMATERIALMODE;

Values

D3DRMMATERIAL_FROMMESH
Material information is retrieved from the visual object (the mesh) itself. This is the default setting.
D3DRMMATERIAL_FROMPARENT
Material information, along with color or texture information, is inherited from the parent frame.
D3DRMMATERIAL_FROMFRAME
Material information is retrieved from the frame, overriding any previous material information that the visual object may have possessed.

See Also

IDirect3DRMFrame3::GetMaterialMode, IDirect3DRMFrame3::SetMaterialMode

D3DRMPALETTEFLAGS

Used to define how a color can be used in the D3DRMPALETTEENTRY structure.

Syntax

typedef enum _D3DRMPALETTEFLAGS {
    D3DRMPALETTE_FREE,
    D3DRMPALETTE_READONLY,
    D3DRMPALETTE_RESERVED
} D3DRMPALETTEFLAGS;

Values

D3DRMPALETTE_FREE
Renderer can use this entry freely.
D3DRMPALETTE_READONLY
Fixed but can be used by renderer.
D3DRMPALETTE_RESERVED
Cannot be used by renderer.

See Also

D3DRMPALETTEENTRY

D3DRMPROJECTIONTYPE

Defines the type of projection used in a Direct3DRMViewport object. The IDirect3DRMViewport2::GetProjection and IDirect3DRMViewport2::SetProjection methods use this enumerated type. The right-hand types enable right-handed projection.

Note: Beginning with DirectX version 6.0, use IDirect3DRM3::SetOptions to specify right-handed geometry.

The axes of the camera (see IDirect3DRMFrame3::SetAxes) are used in both left-handed and right-handed projection to determine what direction the camera is facing.

Syntax

typedef enum _D3DRMPROJECTIONTYPE{
    D3DRMPROJECT_PERSPECTIVE,
    D3DRMPROJECT_ORTHOGRAPHIC,
    D3DRMPROJECT_RIGHTHANDPERSPECTIVE,
    D3DRMPROJECT_RIGHTHANDORTHOGRAPHIC
} D3DRMPROJECTIONTYPE;

Values

D3DRMPROJECT_PERSPECTIVE
Projection is perspective and left-handed.
D3DRMPROJECT_ORTHOGRAPHIC
Projection is orthographic and left-handed.
D3DRMPROJECT_RIGHTHANDPERSPECTIVE
Projection is perspective and right-handed.
D3DRMPROJECT_RIGHTHANDORTHOGRAPHIC
Projection is orthographic and right-handed.

See Also

IDirect3DRMViewport2::GetProjection, IDirect3DRMViewport2::SetProjection

D3DRMRENDERQUALITY

Combines descriptions of the shading mode, lighting mode, and filling mode for a Direct3DRMMesh object.

Syntax

typedef enum _D3DRMSHADEMODE {
    D3DRMSHADE_FLAT        = 0,
    D3DRMSHADE_GOURAUD     = 1,
    D3DRMSHADE_PHONG       = 2,
    D3DRMSHADE_MASK        = 7,
    D3DRMSHADE_MAX         = 8
} D3DRMSHADEMODE;
typedef enum _D3DRMLIGHTMODE {
    D3DRMLIGHT_OFF          = 0 * D3DRMSHADE_MAX,
    D3DRMLIGHT_ON           = 1 * D3DRMSHADE_MAX,
    D3DRMLIGHT_MASK         = 7 * D3DRMSHADE_MAX,
    D3DRMLIGHT_MAX          = 8 * D3DRMSHADE_MAX
} D3DRMLIGHTMODE;
typedef enum _D3DRMFILLMODE {
    D3DRMFILL_POINTS        = 0 * D3DRMLIGHT_MAX,
    D3DRMFILL_WIREFRAME     = 1 * D3DRMLIGHT_MAX,
    D3DRMFILL_SOLID         = 2 * D3DRMLIGHT_MAX,
    D3DRMFILL_MASK          = 7 * D3DRMLIGHT_MAX,
    D3DRMFILL_MAX           = 8 * D3DRMLIGHT_MAX
} D3DRMFILLMODE;

typedef DWORD D3DRMRENDERQUALITY;

#define D3DRMRENDER_WIREFRAME   (D3DRMSHADE_FLAT+D3DRMLIGHT_OFF+D3DRMFILL_WIREFRAME)
#define D3DRMRENDER_UNLITFLAT   (D3DRMSHADE_FLAT+D3DRMLIGHT_OFF+D3DRMFILL_SOLID)
#define D3DRMRENDER_FLAT        (D3DRMSHADE_FLAT+D3DRMLIGHT_ON+D3DRMFILL_SOLID)
#define D3DRMRENDER_GOURAUD     (D3DRMSHADE_GOURAUD+D3DRMLIGHT_ON+D3DRMFILL_SOLID)
#define D3DRMRENDER_PHONG       (D3DRMSHADE_PHONG+D3DRMLIGHT_ON+D3DRMFILL_SOLID)

Values

D3DRMSHADEMODE, D3DRMLIGHTMODE, and D3DRMFILLMODE
These enumerated types describe the shade, light, and fill modes for Direct3DRMMesh objects.

D3DRMRENDER_WIREFRAME
Display only the edges.
D3DRMRENDER_UNLITFLAT
Flat shaded without lighting.
D3DRMRENDER_FLAT
Flat shaded.
D3DRMRENDER_GOURAUD
Gouraud shaded.
D3DRMRENDER_PHONG
Phong shaded. Phong shading is not currently supported.

See Also

IDirect3DRMMesh::GetGroupQuality, IDirect3DRMMesh::SetGroupQuality,IDirect3DRMDevice3::SetRenderMode

D3DRMSHADEMODE

Used to define the D3DRMRENDERQUALITY type.

Syntax

typedef enum _D3DRMSHADEMODE {
    D3DRMSHADE_FLAT     = 0,
    D3DRMSHADE_GOURAUD  = 1,
    D3DRMSHADE_PHONG    = 2,
    D3DRMSHADE_MASK     = 7,
    D3DRMSHADE_MAX      = 8
} D3DRMSHADEMODE;

See Also

D3DRMFILLMODE, D3DRMLIGHTMODE, D3DRMRENDERQUALITY

D3DRMSORTMODE

Describes how child frames are sorted in a scene.

Syntax

typedef enum _D3DRMSORTMODE {
    D3DRMSORT_FROMPARENT,
    D3DRMSORT_NONE,
    D3DRMSORT_FRONTTOBACK,
    D3DRMSORT_BACKTOFRONT
} D3DRMSORTMODE;

Values

D3DRMSORT_FROMPARENT
Child frames inherit the sorting order of their parents. This is the default setting.
D3DRMSORT_NONE
Child frames are not sorted.
D3DRMSORT_FRONTTOBACK
Child frames are sorted front-to-back.
D3DRMSORT_BACKTOFRONT
Child frames are sorted back-to-front.

See Also

IDirect3DRMFrame3::GetSortMode, IDirect3DRMFrame3::SetSortMode

D3DRMTEXTUREQUALITY

Describes how a device interpolates between pixels in a texture and pixels in a viewport. This enumerated type is used by the IDirect3DRMDevice3::SetTextureQuality and IDirect3DRMDevice3::GetTextureQuality methods.

Syntax

typedef enum _D3DRMTEXTUREQUALITY{
    D3DRMTEXTURE_NEAREST,
    D3DRMTEXTURE_LINEAR,
    D3DRMTEXTURE_MIPNEAREST,
    D3DRMTEXTURE_MIPLINEAR,
    D3DRMTEXTURE_LINEARMIPNEAREST,
    D3DRMTEXTURE_LINEARMIPLINEAR
} D3DRMTEXTUREQUALITY;

Values

D3DRMTEXTURE_NEAREST
Choose the nearest pixel in the texture. Does not support mipmapping.
D3DRMTEXTURE_LINEAR
Linearly interpolate the four nearest pixels. Does not support mipmapping.
D3DRMTEXTURE_MIPNEAREST
Similar to D3DRMTEXTURE_NEAREST, but uses the appropriate mipmap instead of the texture. Pixel sampling and mipmapping are both nearest.
D3DRMTEXTURE_MIPLINEAR
Similar to D3DRMTEXTURE_LINEAR, but uses the appropriate mipmap instead of the texture. Pixel sampling is linear; mipmapping is nearest.
D3DRMTEXTURE_LINEARMIPNEAREST
Similar to D3DRMTEXTURE_MIPNEAREST, but interpolates between the two nearest mipmaps. Pixel sampling is nearest; mipmapping is linear.
D3DRMTEXTURE_LINEARMIPLINEAR
Similar to D3DRMTEXTURE_MIPLINEAR, but interpolates between the two nearest mipmaps. Both pixel sampling and mipmapping are linear.

D3DRMUSERVISUALREASON

Defines the reason the system has used the D3DRMUSERVISUALCALLBACK callback function.

Syntax

typedef enum _D3DRMUSERVISUALREASON {
    D3DRMUSERVISUAL_CANSEE,
    D3DRMUSERVISUAL_RENDER
} D3DRMUSERVISUALREASON;

Values

D3DRMUSERVISUAL_CANSEE
Callback function should return TRUE if the user-visual object is visible in the viewport.
D3DRMUSERVISUAL_RENDER
Callback function should render the user-visual object.

See Also

D3DRMUSERVISUALCALLBACK

D3DRMWRAPTYPE

Defines the type of Direct3DRMWrap object created by the IDirect3DRM3::CreateWrap method. You can also use this enumerated type to initialize a Direct3DRMWrap object in a call to the IDirect3DRMWrap::Init method.

Syntax

typedef enum _D3DRMWRAPTYPE{
    D3DRMWRAP_FLAT,
    D3DRMWRAP_CYLINDER,
    D3DRMWRAP_SPHERE,
    D3DRMWRAP_CHROME
} D3DRMWRAPTYPE;

Values

D3DRMWRAP_FLAT
Wrap is flat.
D3DRMWRAP_CYLINDER
Wrap is cylindrical.
D3DRMWRAP_SPHERE
Wrap is spherical.
D3DRMWRAP_CHROME
Wrap allocates texture coordinates so that the texture appears to be reflected onto the objects.

See Also

IDirect3DRM3::CreateWrap, IDirect3DRMWrap::Init, Wraps

D3DRMXOFFORMAT

Defines the file type used by the IDirect3DRMMeshBuilder3::Save method.

Syntax

typedef enum _D3DRMXOFFORMAT{
    D3DRMXOF_BINARY,
    D3DRMXOF_COMPRESSED,
    D3DRMXOF_TEXT
} D3DRMXOFFORMAT;

Values

D3DRMXOF_BINARY
File is in binary format. This is the default setting.
D3DRMXOF_COMPRESSED
Not currently supported.
D3DRMXOF_TEXT
File is in text format.

Remarks

The D3DRMXOF_BINARY and D3DRMXOF_TEXT settings are mutually exclusive.

See Also

IDirect3DRMMeshBuilder3::Save

D3DRMZBUFFERMODE

Describes whether z-buffering is enabled.

Syntax

typedef enum _D3DRMZBUFFERMODE {
    D3DRMZBUFFER_FROMPARENT,
    D3DRMZBUFFER_ENABLE,
    D3DRMZBUFFER_DISABLE
} D3DRMZBUFFERMODE;

Values

D3DRMZBUFFER_FROMPARENT
The frame inherits the z-buffer setting from its parent frame. This is the default setting.
D3DRMZBUFFER_ENABLE
Z-buffering is enabled.
D3DRMZBUFFER_DISABLE
Z-buffering is disabled.

See Also

IDirect3DRMFrame3::GetZbufferMode, IDirect3DRMFrame3::SetZbufferMode


Structures

The Microsoft® Direct3D® Retained Mode structures are:

  • D3DRMANIMATIONKEY
  • D3DRMBOX
  • D3DRMIMAGE
  • D3DRMLOADMEMORY
  • D3DRMLOADRESOURCE
  • D3DRMMATERIALOVERRIDE
  • D3DRMPALETTEENTRY
  • D3DRMPICKDESC
  • D3DRMPICKDESC2
  • D3DRMPMESHLOADSTATUS
  • D3DRMQUATERNION
  • D3DRMRAY
  • D3DRMVECTOR4D
  • D3DRMVERTEX

D3DRMANIMATIONKEY

Defines the keys used by the IDirect3DRMAnimation2::AddKey, GetKeys, and ModifyKey methods.

Syntax

typedef struct _D3DRMANIMATIONKEY
{
    DWORD dwSize;
    DWORD dwKeyType;
    D3DVALUE dvTime;
    DWORD dwId ;
    union
    {
        D3DRMQUATERNION dqRotateKey;
        D3DVECTOR dvScaleKey;
        D3DVECTOR dvPositionKey;
    };
} D3DRMANIMATIONKEY;
typedef D3DRMANIMATIONKEY *LPD3DRMANIMATIONKEY;

Members

dwSize
Size of the animation.
dwKeyType
Type of key. One of the following values:
D3DRMANIMATION_ROTATEKEY = 0x01
D3DRMANIMATION_SCALEKEY = 0x02
D3DRMANIMATION_POSITIONKEY = 0x03
dvTime
Time value in arbitrary units and a member of the D3DVALUE type.
dwId
Key identifier.
dqRotateKey
Value of the D3DRMQUATERNION strucure type defining the rotation.
dvScaleKey
Value of the D3DVECTOR structure type defining the scale.
dvPositionKey
Value of the D3DVECTOR structure type defining the position.

D3DRMBOX

Defines the bounding box retrieved by the IDirect3DRMMesh::GetBox and IDirect3DRMMeshBuilder3::GetBox methods.

Syntax

typedef struct _D3DRMBOX {
    D3DVECTOR min, max;
}D3DRMBOX;
typedef D3DRMBOX *LPD3DRMBOX;

Members

min and max
Values defining the bounds of the box. These values are D3DVECTOR structures.

See Also

D3DVECTOR, IDirect3DRMMesh::GetBox, IDirect3DRMMeshBuilder3::GetBox

D3DRMIMAGE

Describes an image that is attached to a texture by the IDirect3DRM3::CreateTexture method. IDirect3DRMTexture3::GetImage returns the address of this image.

Syntax

typedef struct _D3DRMIMAGE {
    int                width, height;
    int                aspectx, aspecty;
    int                depth;
    int                rgb;
    int                bytes_per_line;
    void*              buffer1;
    void*              buffer2;
    unsigned long      red_mask;
    unsigned long      green_mask;
    unsigned long      blue_mask;
    unsigned long      alpha_mask;
    int                palette_size;
    D3DRMPALETTEENTRY* palette;
}D3DRMIMAGE;
typedef D3DRMIMAGE, *LPD3DRMIMAGE;

Members

width and height
Width and height of the image, in pixels.
aspectx and aspecty
Aspect ratio for nonsquare pixels.
depth
Number of bits that specify each pixel.
rgb
A flag that indicates whether pixels are RGB values or palette indices. If this member is FALSE, pixels are indices into a palette. Otherwise, pixels encode RGB values.
bytes_per_line
Number of bytes of memory for a scan line. This value must be a multiple of four.
buffer1
Memory to render into (first buffer).
buffer2
Second rendering buffer for double buffering. Set this member to NULL for single buffering.
red_mask, green_mask, blue_mask, and alpha_mask
A mask for RGB pixels or pixel palette indices. If rgb is TRUE, these members are masks for the red, green, and blue parts of a pixel. Otherwise, they are masks for the significant bits of the red, green, and blue elements in the palette. For example, most Super VGA (SVGA) displays use 64 intensities of red, green, and blue, so the masks should all be set to 0xfc.
palette_size
Number of entries in the palette.
palette
A pointer to a D3DRMPALETTEENTRY structure describing the color palette to be used. This structure is only used if the D3DRMIMAGE rgb member is FALSE.

See Also

IDirect3DRM3::CreateTexture, IDirect3DRMTexture3::GetImage

D3DRMLOADMEMORY

Identifies a resource to be loaded when an application uses the IDirect3DRM3::Load method (or one of the other Load methods) and specifies D3DRMLOAD_FROMMEMORY.

Syntax

typedef struct _D3DRMLOADMEMORY {
    LPVOID lpMemory;
    DWORD  dSize;
} D3DRMLOADMEMORY, *LPD3DRMLOADMEMORY;

Members

lpMemory
Address of a block of memory to be loaded.
dSize
Size, in bytes, of the block of memory to be loaded.

See Also

IDirect3DRM3::Load, IDirect3DRMAnimationSet2::Load, IDirect3DRMFrame3::Load, IDirect3DRMMeshBuilder3::Load, D3DRMLOADOPTIONS, D3DRMLOADRESOURCE

D3DRMLOADRESOURCE

Identifies a resource to be loaded when an application uses the IDirect3DRM3::Load method (or one of the other Load methods) and specifies D3DRMLOAD_FROMRESOURCE.

Syntax

typedef struct _D3DRMLOADRESOURCE {
    HMODULE hModule;
    LPCTSTR lpName;
    LPCTSTR lpType;
} D3DRMLOADRESOURCE, *LPD3DRMLOADRESOURCE;

Members

hModule
Handle of the module containing the resource to be loaded. If this member is NULL, the resource must be attached to the executable file or dynamic-link library (DLL) that uses the resource.

lpName
Name of the resource to be loaded. For example, if the resource is a mesh, this member should specify the name of the mesh file.
lpType
User-defined type identifying the resource.

Remarks

If the high-order word of the lpName or lpType member is zero, the low-order word specifies the integer identifier of the name or type of the given resource. Otherwise, those parameters are long pointers to null-terminated strings. If the first character of the string is a number sign (#), the remaining characters represent a decimal number that specifies the integer identifier of the resource's name or type. For example, the string "#258" represents the integer identifier 258. An application should reduce the amount of memory required for the resources by referring to them by integer identifier instead of by name.

When an application uses a Load method and specifies D3DRMLOAD_FROMRESOURCE, it does not need to find or unlock any resources; the system handles this automatically.

See Also

IDirect3DRM3::Load, IDirect3DRMAnimationSet2::Load, IDirect3DRMFrame3::Load, IDirect3DRMMeshBuilder3::Load, D3DRMLOADMEMORY, D3DRMLOADOPTIONS

D3DRMMATERIALOVERRIDE

Describes the overrides for IDirect3DRMFrame3::SetMaterialOverride and IDirect3DRMFrame3::GetMaterialOverride methods.

Syntax

typedef struct _D3DRMMATERIALOVERRIDE
{
    DWORD         dwSize;
    DWORD         dwFlags;
    D3DCOLORVALUE dcDiffuse;
    D3DCOLORVALUE dcAmbient;
    D3DCOLORVALUE dcEmissive;
    D3DCOLORVALUE dcSpecular;
    D3DVALUE      dvPower;
    LPUNKNOWN     lpD3DRMTex;
} D3DRMMATERIALOVERRIDE, *LPD3DRMMATERIALOVERRIDE;

Members

dwSize
Size of this structure, in bytes.
dwFlags
Logical combination of flags, indicating which fields in this structure are valid. Possible values include the following:
D3DRMMATERIALOVERRIDE_DIFFUSE_ALPHAONLY
D3DRMMATERIALOVERRIDE_DIFFUSE_RGBONLY
D3DRMMATERIALOVERRIDE_DIFFUSE
D3DRMMATERIALOVERRIDE_AMBIENT
D3DRMMATERIALOVERRIDE_EMISSIVE
D3DRMMATERIALOVERRIDE_SPECULAR
D3DRMMATERIALOVERRIDE_POWER
D3DRMMATERIALOVERRIDE_TEXTURE
D3DRMMATERIALOVERRIDE_ALL
dcDiffuse
Diffuse RGBA color setting of type D3DCOLORVALUE.
dcAmbient
Ambient RGB color setting of type D3DCOLORVALUE.
dcEmissive
Emissive RGB color setting of type D3DCOLORVALUE.
dcSpecular
Specular RGB color setting of type D3DCOLORVALUE.
dvPower
Power setting of type D3DVALUE.
lpD3DRMTex
Pointer to the texture interface.

D3DRMPALETTEENTRY

Describes the color palette used in a D3DRMIMAGE structure. This structure is used only if the rgb member of the D3DRMIMAGE structure is FALSE. (If it is TRUE, RGB values are used.)

Syntax

typedef struct _D3DRMPALETTEENTRY {
    unsigned char red;
    unsigned char green;
    unsigned char blue;
    unsigned char flags;
}D3DRMPALETTEENTRY;
typedef D3DRMPALETTEENTRY, *LPD3DRMPALETTEENTRY;

Members

red, green, and blue
Values defining the primary color components that define the palette. These values can range from 0 through 255.
flags
Value defining how the palette is used by the renderer. This value is one of the members of the D3DRMPALETTEFLAGS enumerated type.

See Also

D3DRMIMAGE, D3DRMPALETTEFLAGS

D3DRMPICKDESC

Contains the pick position and face and group identifiers of the objects retrieved by the IDirect3DRMPickedArray::GetPick method.

Syntax

typedef struct _D3DRMPICKDESC {
    ULONG       ulFaceIdx;
    LONG        lGroupIdx;
    D3DVECTOR   vPosition;
} D3DRMPICKDESC, *LPD3DRMPICKDESC;

Members

ulFaceIdx
Face index of the retrieved object.
lGroupIdx
Group index of the retrieved object.
vPosition
Value describing the position of the retrieved object. This value is a D3DVECTOR structure.

See Also

D3DVECTOR, IDirect3DRMPickedArray::GetPick

D3DRMPICKDESC2

Contains the face and group identifiers, pick position, horizontal and vertical texture coordinates for the vertex, vertex normal, and color of the objects retrieved by the IDirect3DRMPicked2Array::GetPick method.

Syntax

typedef struct _D3DRMPICKDESC2
{
    ULONG	ulFaceIdx;
    LONG	lGroupIdx;
    D3DVECTOR	dvPosition;
    D3DVALUE	tu;
    D3DVALUE	tv;
    D3DVECTOR	dvNormal;
    D3DCOLOR	dcColor;

} D3DRMPICKDESC2, *LPD3DRMPICKDESC2;

Members

ulFaceIdx
Face index of the retrieved object.
lGroupIdx
Group index of the retrieved object.
vPosition
Value describing the position of the retrieved object. This value is a D3DVECTOR structure.
tu and tv
Horizontal and vertical texture coordinates, respectively, for the vertex.
dvNormal
Normal vector for the vertex.
dcColor
Vertex color.

D3DRMPMESHLOADSTATUS

Contains the loading status of a progressive mesh loaded with the IDirect3DRMProgressiveMesh::Load method. This structure can be retrieved with the IDirect3DRMProgressiveMesh::GetLoadStatus method.

Syntax

typedef struct _D3DRMPMESHLOADSTATUS {
    DWORD dwSize;
    DWORD dwPMeshSize;
    DWORD dwBaseMeshSize;
    DWORD dwBytesLoaded;
    DWORD dwVerticesLoaded;
    DWORD dwFacesLoaded;
    DWORD dwFlags;
} D3DRMPMESHLOADSTATUS;
typedef D3DRMPMESHLOADSTATUS *LPD3DRMPMESHLOADSTATUS;

Members

dwSize
Size of the structure.
dwPMeshSize
Size of the total progressive mesh in bytes.
dwBaseMeshSize
Size of the base mesh in bytes.
dwBytesLoaded
Number of total bytes loaded.
dwVerticesLoaded
Number of vertices loaded.
dwFacesLoaded
Number of faces loaded.
dwFlags
Flags that indicate the status of the progressive mesh loading. Can be one of the following values:

D3DRMPMESHSTATUS_VALID — The progressive mesh object contains valid data.
D3DRMPMESHSTATUS_INTERRUPTED — The download was interrupted either because the application used IDirect3DRMProgressiveMesh::Abort or because the connection was lost.
D3DRMPMESHSTATUS_BASEMESHCOMPLETE — The base mesh has been downloaded.
D3DRMPMESHSTATUS_COMPLETE — All data has been downloaded.
D3DRMPMESHSTATUS_RENDERABLE — It is now possible to render the mesh.

See Also

IDirect3DRMProgressiveMesh::GetLoadStatus, IDirect3DRMProgressiveMesh::Load

D3DRMQUATERNION

Describes the rotation used by the IDirect3DRMAnimation2::AddRotateKey method, and the quaternion used in IDirect3DRMFrame3::SetQuaternion. It is also used in several of the Direct3D mathematical functions.

Syntax

typedef struct _D3DRMQUATERNION {
    D3DVALUE   s;
    D3DVECTOR  v;
}D3DRMQUATERNION;
typedef D3DRMQUATERNION, *LPD3DRMQUATERNION;

See Also

IDirect3DRMAnimation2::AddRotateKey, IDirect3DRMFrame3::SetQuaternion, D3DRMQuaternionFromRotation, D3DRMQuaternionMultiply, D3DRMQuaternionSlerp, D3DRMMatrixFromQuaternion

D3DRMRAY

Defines the direction and starting position of the ray in IDirect3DRMFrame3::RayPick.

Syntax

typedef struct _D3DRMRAY
{   D3DVECTOR dvDir;
    D3DVECTOR dvPos;
} D3DRMRAY, *LPD3DRMRAY;

Members

dvDir
Direction of the ray used in a ray pick.
dvPos
Starting position of the ray used in a ray pick.

D3DRMVECTOR4D

Describes the screen coordinates used as the destination of a transformation by the IDirect3DRMViewport2::Transform and IDirect3DRMViewport2::TransformVectors methods and as the source of a transformation by the IDirect3DRMViewport2::InverseTransform and IDirect3DRMViewport2::InverseTransformVectors methods.

Syntax

typedef struct _D3DRMVECTOR4D {
    D3DVALUE x;
    D3DVALUE y;
    D3DVALUE z;
    D3DVALUE w;
}D3DRMVECTOR4D;
typedef D3DRMVECTOR4D, *LPD3DRMVECTOR4D;

Members

x, y, z, and w
Values of the D3DVALUE type describing homogeneous values. These values define the result of the transformation.

See Also

IDirect3DRMViewport2::Transform, IDirect3DRMViewport2::TransformVectors, IDirect3DRMViewport2::InverseTransform, IDirect3DRMViewport2::InverseTransformVectors

D3DRMVERTEX

Describes a vertex in a Direct3DRMMesh object.

Syntax

typedef struct _D3DRMVERTEX{
    D3DVECTOR position;
    D3DVECTOR normal;
    D3DVALUE  tu, tv;
    D3DCOLOR  color;
} D3DRMVERTEX;

Members

position
Position of the vertex.
normal
Normal vector for the vertex.
tu and tv
Horizontal and vertical texture coordinates, respectively, for the vertex.
color
Vertex color.

See Also

IDirect3DRMMesh::GetVertices, IDirect3DRMMesh::SetVertices


Return Values

The methods of the Microsoft® Direct3D® Retained Model (COM) interfaces can return the following values.

D3DRM_OK
No error. Equivalent to DD_OK.
D3DRMERR_BADALLOC
Out of memory.
D3DRMERR_BADCACHEFILE
An X file could not be opened because of a bad cache file. A cache file contains data retrieved from the network, cached on the hard disk, and retrieved in subsequent requests.
D3DRMERR_BADDEVICE
Device is not compatible with renderer.
D3DRMERR_BADFILE
Data file is corrupt.
D3DRMERR_BADMAJORVERSION
Bad DLL major version.
D3DRMERR_BADMINORVERSION
Bad DLL minor version.
D3DRMERR_BADOBJECT
Object expected in argument.
D3DRMERR_BADPMDATA
The data in the .x file is corrupted. The conversion to a progressive mesh succeeded but produced an invalid progressive mesh in the .x file.
D3DRMERR_BADTYPE
Bad argument type passed.
D3DRMERR_BADVALUE
Bad argument value passed.
D3DRMERR_BOXNOTSET
An attempt was made to access a bounding box (for example, with IDirect3DRMFrame3::GetBox) when no bounding box was set on the frame.
D3DRMERR_CLIENTNOTREGISTERED
Client has not been registered. Call IDirect3DRM3::RegisterClient.
D3DRMERR_CONNECTIONLOST
Data connection was lost during a load, clone, or duplicate.
D3DRMERR_ELEMENTINUSE
Element can't be modified or deleted while in use. To empty a submesh, call Empty() against its parent.
D3DRMERR_FACEUSED
Face already used in a mesh.
D3DRMERR_FILENOTFOUND
File cannot be opened.
D3DRMERR_INCOMPATIBLEKEY
Specified animation key is incompatible. The key cannot be modified.
D3DRMERR_INVALIDLIBRARY
Specified libary is invalid.
D3DRMERR_LIBRARYNOTFOUND
Specified libary not found.
D3DRMERR_LOADABORTED
Load aborted by user.
D3DRMERR_NOINTERNET
Downloading from a URL failed, or Urlmon.dll could not be found or was corrupt.
D3DRMERR_NOSUCHKEY
Specified animation key does not exist.
D3DRMERR_NOTAGGREGATED
An attempt was made to access IDirect3DRMObject methods through an external visual object, but the external visual was not created with IDirect3DRM::Load or IDirect3DRM::CreateObject, and is not aggregated with IDirect3DRMObject.
D3DRMERR_NOTCREATEDFROMDDS
Specified texture was not created from a DirectDraw Surface.
D3DRMERR_NOTDONEYET
Unimplemented.
D3DRMERR_NOTENOUGHDATA
Not enough data has been loaded to perform the requested operation.
D3DRMERR_NOTFOUND
Object not found in specified place.
D3DRMERR_PENDING
Data required to supply the requested information has not finished loading.
D3DRMERR_REQUESTTOOLARGE
Attempt was made to set a level of detail in a progressive mesh greater than the maximum available.
D3DRMERR_REQUESTTOOSMALL
Attempt was made to set the minimum rendering detail of a progressive mesh smaller than the detail in the base mesh (the minimum for rendering).
D3DRMERR_TEXTUREFORMATNOTFOUND
Texture format could not be found that meets the specified criteria and that the underlying Immediate Mode device supports.
D3DRMERR_UNABLETOEXECUTE
Unable to carry out procedure.
DD_OK
The request completed successfully. Equivalent to D3DRM_OK.
DDERR_INVALIDOBJECT
Received pointer that was an invalid object.
DDERR_INVALIDPARAMS
One or more of the parameters passed to the method are incorrect.
DDERR_NOTFOUND
The requested item was not found.
DDERR_NOTINITIALIZED
An attempt was made to call an interface method of an object created by CoCreateInstance before the object was initialized.
DDERR_OUTOFMEMORY
DirectDraw does not have enough memory to perform the operation.


Further Reading

This section contains information about the following topics.

  • Color Keying
  • D3DCOLOR_MONO
  • D3DCOLOR_RGB
  • D3DCOLORMODEL
  • D3DCOLORVALUE
  • D3DDEVICEDESC
  • D3DENUMDEVICESCALLBACK
  • D3DMATRIX
  • D3DPRIMCAPS
  • D3DRECT
  • D3DTRIANGLE
  • D3DVALUE
  • D3DVECTOR
  • DirectDrawCreate
  • DirectDrawCreateClipper
  • IDirect3D3
  • IDirectDrawClipper
  • IUnknown Interface
  • Mipmaps
  • Texture Map Formats

Color Keying
A color key is typically a single uncommon color that the artist does not use for anything but transparency, but it can also be a specified range of colors. Using the IDirectDrawSurface3::SetColorKey method, you can set the color key for a surface. After the color key is set, subsequent calls to IDirectDrawSurface3::BltFast take advantage of that color key, ignoring the pixels that match it. This type of color key is known as a source color key. Because the source color key prevents "transparent" pixels from being written to the destination, the original background pixels are preserved in these places, making it look like a sprite is a non-rectangular object passing over the background. You can also use a color key that effects the destination surface (a destination color key).

A destination color key is a color on a surface that is used for pixels that can be overwritten by a sprite. Again, the artist chooses an arbitrary color that is not used elsewhere in the image, reserving it as a portion of the image where you are allowed to blit. When you blit a sprite to the destination surface with a destination color key specified, the sprite's pixels will only be blitted to pixels on the destination that are using the destination color key. Because the normal destination pixels are preserved, it looks like the sprite passes behind the image on the destination surface. For more information, see Transparent Blitting and Color Keys in the ""Surfaces" topic in the "DirectDraw Essentials" section of the DirectX Foundation SDK.

D3DCOLOR_MONO
A value of the D3DRMCOLORMODEL constant that tells the system to use a monochromatic model (or ramp model). In this model, the blue component of a vertex color is used to define the brightness of a lit vertex.
D3DCOLOR_RGB
A value of the D3DRMCOLORMODEL constant that tells the system to use a full RGB model.
D3DCOLORMODEL
A constant that defines the color model in which the system will run.
typedef enum _D3DCOLORMODEL {
    D3DCOLOR_MONO = 1,
    D3DCOLOR_RGB  = 2,
} D3DCOLORMODEL;
D3DCOLORVALUE
A structure that describes color values. dvR, dvG, dvB, and dvA are values of the D3DVALUE type specifying the red, green, blue, and alpha components of a color. These values generally range from 0.0 to 1.0, with 0.0 specifying black.
typedef struct _D3DCOLORVALUE {
    union {
        D3DVALUE r;
        D3DVALUE dvR;
    };
    union {
        D3DVALUE g;
        D3DVALUE dvG;
    };
    union {
        D3DVALUE b;
        D3DVALUE dvB;
    };
    union {
        D3DVALUE a;
        D3DVALUE dvA;
    };
} D3DCOLORVALUE;
D3DDEVICEDESC
A structure that contains a description of the current device. For more information, see D3DDEVICEDESC in the "Structures" section of the DirectX Foundation Immediate Mode Reference.
D3DENUMDEVICESCALLBACK
The prototype definition for the callback function to enumerate installed Direct3D devices. For more information, see Callback Functions in the DirectX Foundation Immediate Mode Reference.
typedef HRESULT (FAR PASCAL * LPD3DENUMDEVICESCALLBACK)
  (LPGUID lpGuid,
  LPSTR lpDeviceDescription,
  LPSTR lpDeviceName,
  LPD3DDEVICEDESC lpD3DHWDeviceDesc,
  LPD3DDEVICEDESC lpD3DHELD9eviceDesc,
  LPVOID lpUserArg
);
D3DMATRIX
A structure that describes a matrix.
typedef struct _D3DMATRIX {
    D3DVALUE _11, _12, _13, _14;
    D3DVALUE _21, _22, _23, _24;
    D3DVALUE _31, _32, _33, _34;
    D3DVALUE _41, _42, _43, _44;
} D3DMATRIX, *LPD3DMATRIX;
D3DPRIMCAPS
A structure that defines the capabilities for each primitive type. Used by IDirect3DRM3::CreateDeviceFromClipper to set these default capabilities:

D3DPCMPCAPS_LESSEQUAL — Pass the z-buffer comparison if the new z-value is less than or equal to the current z-value.

D3DPMISCCAPS_CULLCCW — The driver supports counterclockwise culling through the D3DRENDERSTATE_CULLMODE state. (This applies only to triangle primitives.)

D3DPRASTERCAPS_FOGVERTEX — The device calculates the fog value during the lighting operation, places the value into the alpha component of the D3DCOLOR value given for the specular member of the D3DTLVERTEX structure, and interpolates the fog value during rasterization.

D3DPSHADECAPS_ALPHAFLATSTIPPLED — The device can support an alpha component for flat blended and stippled transparency, respectively (the D3DSHADE_FLAT state for the D3DSHADEMODE enumerated type). In these modes, the alpha color component for a primitive is provided as part of the color for the first vertex of the primitive.

D3DPTADDRESSCAPS_WRAP — The device can wrap textures to addresses.

D3DPTBLENDCAPS_COPY | D3DPTBLENDCAPS_MODULATE — The copy texture-blending mode (D3DTBLEND_COPY from the D3DTEXTUREBLEND enumerated type) and the modulate texture-blending mode (D3DTBLEND_MODULATE from the D3DTEXTUREBLEND enumerated type) are supported.

D3DPTEXTURECAPS_PERSPECTIVE | D3DPTEXTURECAPS_TRANSPARENCY — Perspective correction and texture transparency are supported.

D3DPTFILTERCAPS_NEAREST — The texel (a single element of a texture) with coordinates nearest to the desired pixel value is used. This applies to both zooming in and zooming out. If either zooming in or zooming out is supported, then both must be supported.

D3DRECT
A structure that is a rectangle definition.
typedef struct _D3DRECT {
    union {
        LONG x1;
        LONG lX1;  //upper left x
    };
    union {
        LONG y1;
        LONG lY1;  //upper left y
    };
    union {
        LONG x2;
        LONG lX2; //lower right x
    };
    union {
        LONG y2;
        LONG lY2;  //lower right y
    };
} D3DRECT, *LPD3DRECT;
D3DTRIANGLE
The structure that describes the base type for all triangles. The triangle is the main rendering primitive.
D3DVALUE
The fundamental Direct3D fractional data type.
typedef float D3DVALUE, *LPD3DVALUE;
D3DVECTOR
The structure that defines a vector for many Direct3D and Direct3D Retained Mode methods and structures.
typedef struct _D3DVECTOR {
    union {
        D3DVALUE x;
        D3DVALUE dvX;
    };
    union {
        D3DVALUE y;
        D3DVALUE dvY;
    };
    union {
        D3DVALUE z;
        D3DVALUE dvZ;
    };
} D3DVECTOR, *LPD3DVECTOR;
DirectDrawCreate
A function that creates an instance of a DirectDraw object. For more information, see DirectDrawCreate in the "Functions" section of the DirectX Foundation DirectDraw Reference.
DirectDrawCreateClipper
A function that creates an instance of a DirectDrawClipper object not associated with a DirectDraw object. For more information, see DirectDrawCreateClipper in the "Functions" topic of the DirectX Foundation DirectDraw Reference.
IDirect3D3
Applications use the methods of the IDirect3D3 interface to create Direct3D objects and to set up the environment. For more information, see IDirect3D3 in the "Interfaces" topic in the DirectX Foundation Immediate Mode Reference.
IDirect3D3::EnumDevices — This method enumerates all Direct3D device drivers installed on the system.
IDirect3D3::FindDevice — This method finds a device with the specified characteristics and retrieves a description of it.
IDirectDrawClipper
Applications use the methods of the IDirectDrawClipper interface to manage clip lists. For more information, see IDirectDrawClipper in the "Interfaces" topic of the DirectX Foundation DirectDraw Reference.
IDirectDrawClipper::SetHWnd — This method sets the window handle that will obtain the clipping information.
IUnknown Interface
All Component Object Model (COM) interfaces are derived from the IUnknown interface. This interface provides control of the object's lifetime and the ability to navigate multiple interfaces. IUnknown has three methods: AddRef, which increments the object's reference count by 1 when an interface or another application binds itself to the object; QueryInterface, which queries the object about the features it supports by requesting pointers to a specific interface; Release, which decrements the object's reference count by 1. When the count reaches 0, the object is deallocated.

IUnknown::AddRef and IUnknown::Release — These IUnknown methods maintain an object's reference count. For example, if you create a DirectPlay object (with CoCreateInstance, for example), the object's reference count is set to 1. Every time a function returns a pointer to an interface for that object, the function must call AddRef through that pointer to increment the reference count. You must match each AddRef call with a call to Release. Before the pointer can be destroyed, you must call Release through that pointer. After an object's reference count reaches 0, the object is destroyed and all interfaces to it become invalid.
IUnknown::QueryInterface — This IUnknown method determines whether an object supports a specific interface. If an object supports the interface, QueryInterface returns a pointer to that interface. You then can use the methods contained in that interface to communicate with the object. If QueryInterface successfully returns a pointer to an interface, it implicitly calls AddRef to increment the reference count, so your application must call Release to decrement the reference count before destroying the pointer to the interface.
Mipmaps
A mipmap is a sequence of textures, each of which is a progressively lower resolution, prefiltered representation of the same image. Each prefiltered image, or level, in the mipmap is a power of two smaller than the previous level. A high-resolution level is used for objects that are close to the viewer. Lower-resolution levels are used as the object moves farther away. Mipmapping is a computationally low-cost way of improving the quality of rendered textures. For more information, see Mipmaps in the "Textures" topic in the "Direct3D Immediate-Mode Essentials" section of the DirectX Foundation SDK.
Texture Map Formats
A wide range of texture pixel formats are supported by the Microsoft® DirectX® hardware-emulation layer. The table in Texture Map Formats in the "Pixel Format Masks" topic in the DirectX Foundation DirectDraw Reference shows these formats.


Samples Introduction

This section provides information about how to build the Microsoft® Direct3D® Retained Mode samples in Microsoft Developer Studio™, and it provides summaries of the samples to help you determine which sample to look at.

  • Building Samples Using Developer Studio 5.0
  • Samples
© 1998 Microsoft Corporation. All rights reserved. Terms of Use.


Building Samples Using Developer Studio 5.0

Each sample included with the Microsoft® DirectX® Software Development Kit includes a makefile that you can use to build the sample from the command line. You can then run the sample to see what it does. When you find a sample that interests you, you might want to explore further and step through the code yourself. If you want to build and debug samples (or your own code) using Microsoft Developer Studio™, you will want to create a project within Developer Studio. This article discusses how to create a project in Developer Studio version 5.0. The project file must include the necessary source files and libraries, and Developer Studio must be configured with the correct library and include paths so that the compiler can locate the required library and header files.

Note See the readme.txt file in the DirectX SDK Samples directory for information about building samples from the command line.

This article contains the following sections.

  • Tools Options
  • Creating a New Project
  • Project Settings
  • Adding Libraries
  • Setting the Working Directory
  • Adding Files to the Project

Tools Options

You must specify where the header and library files from the DirectX SDK are located when using Developer Studio. These settings are global within Developer Studio and do not need to be repeated for each project.

Perform the following steps to add the DirectX SDK header and library directories to the include and library file search paths.

  1. Within Developer Studio, choose Options from the Tools menu.
  2. Select the Directories tab.
  3. In the Show Directories for dialog box, choose Include files.
  4. Double-click the dotted rectangle below the list of directories and type in the full path for your DirectX SDK include directory. You can also press the "..." (browse) button that appears on the right side of the entry field when you select the rectangle and then navigate to the correct directory. By default, the header (include) files are installed in c:\mssdk\include.
  5. Press the enter key to complete the entry, re-select the new entry if necessary, and then press the Move Item Up button Move Item Up button repeatedly to move the directory up one position at a time, to the top of the directory list. Placing the directory at the top of the list ensures that the DirectX files will come first in the search path and will be used in case of duplicate file names.

    The following screen shot shows the Directories tab of the Tools Options dialog box with the default include directory at the top of the directory list.

    Directories tab of Tools Options dialog box

  6. After you have added the include directory, add the library directory. In the Show directories for dialog box, choose Library files.
  7. Double-click the dotted rectangle below the list of directories and type in the full path (or use the "..." (browse) button to select a path) for your DirectX SDK library directory. By default, the library files are installed in c:\mssdk\lib.
  8. Press the enter key to complete the entry, re-select the new entry if necessary, and then press the Move Item Up button repeatedly to move the directory up one position at a time, to the top of the directory list.

Creating a New Project

Perform the following steps to create a new project.

  1. Choose New from Developer Studio's File menu.
  2. Select the Projects tab.
  3. Select the appropriate project type. "Win32® Application" is appropriate for Windows® applications.
  4. Type in a project name.
  5. Edit the path for project location to point to your desired location, or use the "..." (browse) button to navigate to that directory. Note that the project name is appended to this path.

Project Settings

This section discusses how to add the appropriate libaries to your project and how to set the working directory. Open a project in Developer Studio before proceeding.

Adding Libraries

  1. Choose Settings from Developer Studio's Project menu.
  2. Select the Link tab.
  3. Choose General from the Category dialog box.
  4. Choose All Configurations from the Settings For dialog box.
  5. In the Object/library modules edit control, type the names of the libraries your project requires. You will typically put those libraries at the beginning of the list so definitions will be picked up first from those core libraries.

    The required libraries vary from project to project, depending on the technology the code uses. If in doubt about the libraries required for a particular sample, search the makefile in that sample's directory and include the same library list. The following table lists the most commonly used libraries included with the DirectX SDK. The Winmm.lib library included with the Platform SDK includes additional multimedia functionality as well.
    DirectDraw | ddraw.lib
    Direct3D Retained Mode | d3drm.lib
    DirectSound | dsound.lib
    DirectPlay | dplayx.lib
    DirectInput | dinput.lib

    For example, the Tex1 sample's makefile lists ddraw.lib and d3drm.lib because it uses Microsoft DirectDraw® and Direct3D® Retained Mode.

The following screen shot shows the Link tab of the Project Settings dialog box. It specifies the settings for all configurations and adds multimedia and DirectX libraries to the beginning of Developer Studio's default Object/library modules list.

Link tab of the Project Settings dialog box

Setting the Working Directory

You might need to set the working directory to make sure your program can find certain files. For example, you might need to load an image from the directory in which your program resides. By default, Developer Studio sets the current working directory to the directory in which it resides, rather than to the directory containing your program.

Perform the following steps to set the working directory.

  1. Choose Settings from Developer Studio's Project menu.
  2. Select the Debug tab.
  3. Choose the appropriate configuration ("All Configurations" or "Win32 Debug", for example) from the Settings For dialog box.
  4. Type the full path to your desired working directory in the Working directory edit control.

The following screen shot shows the Debug tab of the Project Settings dialog box. It specifies a working directory for the Win32 Debug configuration.

Debug tab of the Project Settings dialog box

Adding Files to the Project

Perform the following steps to add any required files to your project. Open a project in Developer Studio before proceeding.

  1. Choose Add To Project from Developer Studio's Project menu.
  2. If you are creating a new file, select New, select the type of file, and specify a file name.
  3. If you are opening an existing file, select Files and select the file you want to add to the project.
  4. Repeat the previous steps until you have added all required source files (such as .cpp or .c), resource files (such as .rc), and any other necessary files.
  5. Choose Save All from Developer Studio's File menu to save all files including source code, project files, and the workspace.


Samples

This article summarizes the Microsoft® Direct3D® Retained Mode samples. The summary for each sample lists the default installation directory for that sample in the Microsoft DirectX® Software Development Kit (SDK) and provides a short description of the sample.

All of the Direct3D Retained Mode samples except RMBegin1, RMBegin2, RMEnum and Viewer use the RMMain helper code. All of the samples that use the RMMain helper code depend on the Rmmain.cpp to provide the main application window and Rmmain.rc to provide menus and accelerators. These samples also link to the Ddraw.lib and D3drm.lib libraries. Each sample directory includes a Microsoft Developer Studio project (.dsp) file that you can open in Developer Studio and use to build the sample.

If you are new to Direct3D Retained Mode, you might want to start by looking at the RMBegin1, RMBegin2, RMEnum, Egg, Globe, Hier1, and Tex1 samples.

The following articles provide a detailed walk through of sample code.

  • Rotating an Object: The RMBegin1 Sample
  • Frame Hierarchies: The RMBegin2 Sample
  • Enumerating Devices: The RMEnum Sample

This article contains information on the following samples.

  • Egg
  • Faces
  • Fly
  • Globe
  • Hier1
  • Hier2
  • Morph
  • Quat
  • RMBegin1
  • RMBegin2
  • RMEnum
  • RMMain
  • Shadow
  • Tex1
  • Tex3
  • Tex4
  • Tex5
  • Trans
  • Uvis
  • Viewer

Some of the DirectX Foundation SDK samples demonstrate multiple technologies. You might want to look at those samples to see how the technologies fit together. For example, the DS3dView DirectSound sample is a simple extension of the Direct3D Retained Mode 3-D object Viewer sample. DS3dView enables you to attach sounds to objects and to move the objects in three dimensions. For more information about DS3dView see the DirectX Foundation SDK.

Egg

Path

mssdk\samples\multimedia\d3drm\src\Egg

Description

This sample loads a simple DirectX file of a single mesh object (Egg.x from the Dxsdk\Media directory). The sample initializes the lights in the scene, loads the mesh file, creates the egg frame within the scene, adds the mesh into the frame, and sets up the frame's position, orientation, and rotation. The sample uses methods of IDirect3DRM3 (CreateFrame, CreateLightRGB, CreateMeshBuilder), IDirect3DRMFrame3 (SetPosition, AddLight, SetRotation, AddVisual, SetOrientation), and IDirect3DRMMeshBuilder3 (Load).

Required Libraries

  • Ddraw.lib
  • D3drm.lib

Required RMMain Code

  • Rmmain.cpp
  • Rmmain.rc

Faces

Path

mssdk\samples\multimedia\d3drm\src\Faces

Description

This sample creates mesh objects one face at a time.

Required Libraries

  • Ddraw.lib
  • D3drm.lib.

Required RMMain Code

  • Rmmain.cpp
  • Rmmain.rc

Fly

Path

mssdk\samples\multimedia\d3drm\src\Fly

Description

This sample uses animations to set the position of a spaceship along a curved path.

Required Libraries

  • Ddraw.lib
  • D3drm.lib

Required RMMain Code

  • Rmmain.cpp
  • Rmmain.rc

Globe

Path

mssdk\samples\multimedia\d3drm\src\Globe

Description

This sample loads a simple DirectX file of a single mesh object with textures. It uses methods of:

  • IDirect3DRM3
    • CreateFrame
    • CreateLightRGB
    • CreateMeshBuilder
    • CreateMaterial
    • CreateWrap
    • LoadTexture
    • CreateAnimation
  • IDirect3DRMFrame3
    • GetScene
    • LookAt
    • SetPosition
    • AddLight
    • SetOrientation
    • SetRotation
    • AddVisual
    • AddMoveCallback
    • AddDestroyCallback
  • IDirect3DRMMeshBuilder3
    • Load
    • SetMaterial
    • Scale
    • SetColorRGB
    • GetBox
    • SetTexture
  • IDirect3DRMAnimation
    • SetFrame
    • SetTime
    • SetOptions
    • AddPositionKey
  • IDirect3DRMWrap
    • Apply
  • IDirect3DRMTexture3
    • SetShades

Required Libraries

  • Ddraw.lib
  • D3drm.lib

Required RMMain Code

  • Rmmain.cpp
  • Rmmain.rc

Hier1

Path

mssdk\samples\multimedia\d3drm\src\Hier1

Description

This sample creates a simple hierarchy of two meshes, demonstrating the concept of frames. It initializes the lights in the scene, loads two mesh files, and creates a hierarchy of frames (frames within frames). Hier1 loads a texture and wraps it onto a mesh, adds the mesh into the frame, and sets up the frame's position, orientation, and rotation.

Required Libraries

  • Ddraw.lib
  • D3drm.lib

Required RMMain Code

  • Rmmain.cpp
  • Rmmain.rc

See Also

Hier2

Hier2

Path

mssdk\samples\multimedia\d3drm\src\Hier2

Description

This sample demonstrates a simple hierarchy of four meshes.

Required Libraries

  • Ddraw.lib
  • D3drm.lib

Required RMMain Code

  • Rmmain.cpp
  • Rmmain.rc

See Also

Hier1

Morph

Path

mssdk\samples\multimedia\d3drm\src\Morph

Description

This sample demonstrates how to use interpolators.

Required Libraries

  • Ddraw.lib
  • D3drm.lib

Required RMMain Code

  • Rmmain.cpp
  • Rmmain.rc

See Also

IDirect3DRMInterpolator

Quat

Path

mssdk\samples\multimedia\d3drm\src\Quat

Description

This sample uses quaternions to interpolate between two vectors in space.

Required Libraries

  • Ddraw.lib
  • D3drm.lib

Required RMMain Code

  • Rmmain.cpp
  • Rmmain.rc

RMBegin1

Path

mssdk\samples\multimedia\d3drm\src\RMBegin1

Description

This is a "bare-bones" sample that creates a default Direct3D Retained Mode device, loads a mesh from a DirectX file, adds lights, and rotates the mesh object. Extensive comments throughout the sample code introduce and explain its purpose.

Unlike most of the Direct3D Retained Mode samples, it does not use the RMMain helper file, Rmmain.cpp, or the extensive menus provided by Rmmain.rc.

For a detailed code walkthrough of the RMBegin1 sample, see Rotating an Object: The RMBegin1 Sample.

For a sample that builds upon the RMBegin1 sample code, see RMBegin2.

Required Libraries

  • Ddraw.lib
  • D3drm.lib

RMBegin2

Path

mssdk\samples\multimedia\d3drm\src\RMBegin2

Description

This is a "bare-bones" sample that demonstrates a hierarchy of frames. It loads, scales, lights, and colors three objects from DirectX files. The objects mimic a sun, planet, and moon scenario with the moon revolving around the planet and both the moon and planet revolving around the sun. This sample builds upon the code introduced in the RMBegin1 sample. In addition to building a more complex scene than RMBegin1, this sample handles resizing of the window and handles the WM_ACTIVATE and WM_PAINT messages. Extensive comments throughout the sample code introduce and explain its purpose.

Unlike most of the Direct3D Retained Mode samples, it does not use the RMMain helper file, Rmmain.cpp, or the extensive menus provided by Rmmain.rc.

For a detailed code walkthrough of the RMBegin2 sample, see Frame Hierarchies: The RMBegin2 Sample.

Required Libraries

  • Ddraw.lib
  • D3drm.lib

RMEnum

Path

mssdk\samples\multimedia\d3drm\src\Rmenum

Description

This is a "bare-bones" sample that enumerates devices, intelligently selects one, and creates the Direct3D Retained Mode device. This sample does not perform any rendering. It focuses on device enumeration for clarity and simplicity of code. It enables the user to select the device through a menu choice.

Unlike most of the Direct3D Retained Mode samples, it does not use the RMMain helper file, Rmmain.cpp, or the extensive menus provided by Rmmain.rc. It does use the error reporting functions from its Rmerror.c file.

For a detailed code walkthrough of the RMEnum sample, see Enumerating Devices.

Required Libraries

  • Ddraw.lib
  • D3drm.lib

RMMain

Path

mssdk\samples\multimedia\d3drm\src\Misc

Description

The RMMain helper code handles common tasks, such as creating, enumerating, and managing Microsoft DirectDraw® and Direct3D Retained Mode objects and providing a common resource for menus. It uses Direct3D Retained Mode to set up a window for rendering, calls the BuildScene function the sample provides to have the sample build its scene, and uses Direct3D Retained Mode to render the scene. Most of the Direct3D Retained Mode samples link to this common code, which allows the application-specific code to be much simpler. The samples that use RMMain only work in windowed mode.

RMMain also provides a number of menu items, allowing the user to see the effect of different rendering options. You can single step through the animation, select the device to use for rendering, select shading (flat or Gouraud), turn lighting and dithering on and off, and choose fill options (point, wireframe, or solid).

The RMMain helper code consists of the following files.
Rmmain.cpp | Main source file that includes WinMain and message handler. Creates Direct3D Retained Mode, uses it to set up the window for rendering, and then calls the sample to have it build its scene.
Resource.h | Header file for Rmmain.rc.
Rmmain.rc | Resource file for Rmmain.cpp, providing menus, keyboard accelerators, and the About dialog box.

Shadow

Path

mssdk\samples\multimedia\d3drm\src\Shadow

Description

This sample creates a shadow of a mesh object.

Required Libraries

  • Ddraw.lib
  • D3drm.lib

Required RMMain Code

  • Rmmain.cpp
  • Rmmain.rc

Tex1

Path

mssdk\samples\multimedia\d3drm\src\Tex1

Description

This sample loads a simple, texture-mapped mesh object, using a cylindrical mapping.

Required Libraries

  • Ddraw.lib
  • D3drm.lib

Required RMMain Code

  • Rmmain.cpp
  • Rmmain.rc

See Also

Tex3, Tex4, and Tex5

Tex3

Path

mssdk\samples\multimedia\d3drm\src\Tex3

Description

This sample uses texture wraps for special effects, using a spherical mapping relative to a frame.

Required Libraries

  • Ddraw.lib
  • D3drm.lib

Required RMMain Code

  • Rmmain.cpp
  • Rmmain.rc

See Also

Tex1, Tex4, and Tex5

Tex4

Path

mssdk\samples\multimedia\d3drm\src\Tex4

Description

This sample uses texture wraps for special effects, using a spherical mapping relative to the camera. The texture is also used as a background for the scene.

Required Libraries

  • Ddraw.lib
  • D3drm.lib

Required RMMain Code

  • Rmmain.cpp
  • Rmmain.rc

See Also

Tex1, Tex3, and Tex5

Tex5

Path

mssdk\samples\multimedia\d3drm\src\Tex5

Description

This sample uses a wrap for chrome mapping and a texture map as decal.

Required Libraries

  • Ddraw.lib
  • D3drm.lib

Required RMMain Code

  • Rmmain.cpp
  • Rmmain.rc

See Also

Tex1, Tex3, and Tex4

Trans

Path

mssdk\samples\multimedia\d3drm\src\Trans

Description

This sample demonstrates the use of transparent texture maps. It rotates a solid sphere and independently rotates two partially transparent checkered cubes that intersect with the sphere. The sample creates frames, lights, meshbuilders, meshes, textures, and materials. It calls IDirect3DRMTexture3::SetDecalTransparency to make decals transparent.

Required Libraries

  • Ddraw.lib
  • D3drm.lib

Required RMMain Code

  • Rmmain.cpp
  • Rmmain.rc

Uvis

Path

mssdk\samples\multimedia\d3drm\src\Uvis

Description

This sample demonstrates how Direct3D can be used with Direct3D Retained Mode. It demonstrates how to use a Direct3D Immediate Mode execute buffer as a visual in a Direct3D Retained Mode scene.

Required Libraries

  • Ddraw.lib
  • D3drm.lib

Required RMMain Code

  • Rmmain.cpp
  • Rmmain.rc

Viewer

Path

mssdk\samples\multimedia\d3drm\src\Viewer

Description

Viewer (Direct3D Retained Mode Object Viewer) is a stand-alone Retained Mode application that enables you to load and view 3-D objects.

The initial scene has a light source in the upper-right corner. To see this, the view can be moved backward and forward using the T and R keys. Additional objects can be loaded from the File menu, and new light sources can be added from the Lights menu. Objects can be rotated with the left mouse button and dragged with the right.

The last object that was rotated or dragged remains the current selection.

The device quality can be altered using the Renderer menu. Using this menu, the type of device used can also be switched from ramp to RGB. When using the RGB device, the color of lights in the scene can be changed in the same way as you change the color of objects. In 256-color mode, it is advisable to dither an RGB device for best results.

Additional keyboard controls:
T | Forward
R | Back
Z | Move current selection forwards
X | Move current selection back
Ctrl+G | Gouraud shade
Ctrl+F | Flat Shade
Ctrl+D | Dither toggle
Arrow Keys | Move left/right/up/down
Delete | Delete the current selection

Required Libraries

  • Ddraw.lib
  • D3drm.lib
  • Comdlg32.lib
  • Winmm.lib
  • Msvcrt.lib


DirectX File Format

Microsoft® DirectX® version 6.0 introduces interfaces and methods that enable reading from and writing to DirectX (.x) files. For more information, see the DirectX File Reference.

This section specifies the file format introduced with DirectX 2.0. A binary version of this format was subsequently released with DirectX 3.0, which is also detailed in this reference.

The DirectX file format provides a rich, template-driven format that enables the storage of meshes, textures, animations, and user-definable objects. Support for animation sets enables you to store predefined paths for playback in real time. Instancing and hierarchies are also supported. Instancing enables multiple references to an object, such as a mesh, while storing its data only once per file. Hierarchies are used to express relationships between data records. The DirectX file format is used natively by the Microsoft Direct3D® Retained Mode API, providing support for reading predefined objects into an application or for writing mesh information constructed by the application in real time.

The DirectX file format provides low-level data primitives upon which applications define higher-level primitives through templates. This is the method by which Direct3D Retained Mode defines higher-level primitives such as vectors, meshes, matrices, and colors.

The following sections detail the API-independent features of the file format and also the method by which Direct3D Retained Mode uses the file format.

  • DirectX File Format Architecture
  • DirectX File Templates
  • DirectX File Cube Example
  • DirectX File Binary Format
  • DirectX File Conv3ds.exe Utility
  • DirectX File Samples
  • DirectX File Reference


DirectX File Format Architecture

The Microsoft® DirectX® file format is an architecture- and context-free file format. It is template-driven and is free of any usage knowledge. The file format may be used by any client application and currently is used by Microsoft Direct3D® Retained Mode to describe geometry data, frame hierarchies, and animations.

This following sections deal with the content and syntax of the file format. The file format uses the extension .x when used with the DirectX Software Development Kit (SDK).

  • Reserved Words
  • Header
  • Comments
  • Templates
  • Data
  • Use of Commas and Semicolons

Reserved Words

The following words are reserved and must not be used:

  • ARRAY
  • BINARY
  • BINARY_RESOURCE
  • CHAR
  • CSTRING
  • DOUBLE
  • DWORD
  • FLOAT
  • SDWORD
  • STRING
  • SWORD
  • TEMPLATE
  • UCHAR
  • ULONGLONG
  • UNICODE
  • WORD

Header

The variable length header is compulsory and must be at the beginning of the data stream. The header contains the following:
Type | Sub Type | Size | Contents | Content Meaning
Magic Number (required) | 4 bytes | "xof "
Version Number (required) | Major Number | 2 bytes | 03 | Major version 3
Minor Number | 2 bytes | 02 | Minor version 2
Format Type (required) | 4 bytes | "txt " | Text File
"bin " | Binary File
"tzip" | MSZip Compressed Text File
"bzip" | MSZip Compressed Binary File
Float size (required) | 4 bytes | 0064 | 64-bit floats
0032 | 32-bit floats

Example

xof 0302txt 0064

Comments

Comments are only applicable in text files. Comments can occur anywhere in the data stream. A comment begins with either C++ style double-slashes "//", or a number sign "#". The comment runs to the next new line.

# This is a comment.
// This is another comment.

Templates

Templates define how the data stream is interpreted—the data is modulated by the template definition. This section discusses the following aspects of a template:

  • Template form
  • Template name
  • UUID
  • Members
  • Restrictions

Example templates are presented in Examples.

Template form

A template has the following form.

template <template-name> {
<UUID>
<member 1>;
...
<member n>;
[restrictions]
}

Template name

This is an alphanumeric name that may include the underscore character "_". It must not begin with a digit.

UUID

A universally unique identifier (UUID) formatted to the Open Software Foundation's Distributed Computing Environment standard and surrounded by angle brackets "<" and ">". For example: <3D82AB43-62DA-11cf-AB39-0020AF71E433>.

Members

Template members consist of a named data type followed by an optional name or an array of a named data type. Valid primitive data types are as follows:

Type | Size
WORD | 16 bits
DWORD | 32 bits
FLOAT | IEEE float
DOUBLE | 64 bits
CHAR | 8 bits
UCHAR | 8 bits
BYTE | 8 bits
STRING | NULL-terminated string
CSTRING | Formatted C-string (currently unsupported)
UNICODE | UNICODE string (currently unsupported)

Additional data types defined by templates encountered earlier in the data stream can also be referenced within a template definition. No forward references are allowed.

Any valid data type can be expressed as an array in the template definition. The basic syntax is as follows:

array <data-type> <name>[<dimension-size>];

<dimension-size> can either be an integer or a named reference to another template member whose value is then substituted.

Arrays may be n-dimensional, where n is determined by the number of paired square brackets trailing the statement. For example:

array DWORD FixedHerd[24];
array DWORD Herd[nCows];
array FLOAT Matrix4x4[4][4];

Restrictions

Templates may be open, closed, or restricted. These restrictions determine which data types may appear in the immediate hierarchy of a data object defined by the template. An open template has no restrictions, a closed template rejects all data types, and a restricted template allows a named list of data types.

The syntax for indicating an open template is three periods enclosed by square brackets.

[ ... ]

A comma-separated list of named data types followed optionally by their UUIDs enclosed by square brackets indicates a restricted template.

[ { data-type [ UUID ] , }... ]

The absence of either of the above indicates a closed template.

Examples

template Mesh {
<3D82AB44-62DA-11cf-AB39-0020AF71E433>
DWORD nVertices;
array Vector vertices[nVertices];
DWORD nFaces;
array MeshFace faces[nFaces];
 [ ... ]                // An open template
}
template Vector {
<3D82AB5E-62DA-11cf-AB39-0020AF71E433>
FLOAT x;
FLOAT y;
FLOAT z;
}                        // A closed template
template FileSystem {
<UUID>
STRING name;
[ Directory <UUID>, File <UUID> ]    // A restricted template
}

There is one special template—the Header template. It is recommended that each application define such a template and use it to define application-specific information, such as version information. If present, this header will be read by the DirectX file format API. If a flags member is available, it will be used to determine how the following data is interpreted. The flags member, if defined, should be a DWORD. One bit is currently defined—bit 0. If this bit is clear, the following data in the file is binary. If set, the following data is text. Multiple header data objects can be used to switch between binary and text within the file.

Data

Data objects contain the actual data or a reference to that data. Each has a corresponding template that specifies the data type.

Data objects have the following form.

<Identifier> [name] { [<UUID>]
<member 1>;
...
<member n>;
}

This section discusses the following parts of data objects:

  • Identifier
  • Name
  • Members

Example templates are presented in Examples.

Identifier

This part is compulsory and must match a previously defined data type or primitive.

Name

Name is optional. (See earlier for the syntax definition.)

Members

Data members can be one of the following: data object, data reference, integer list, float list, or string list.

Data object

A nested data object. This allows the hierarchical nature of the file format to be expressed. The types of nested data objects allowed in the hierarchy may be restricted. See Templates for more information.

Data reference

A reference to a previously encountered data object. The syntax is as follows:

{
  name |
  UUID |
  name UUID
}

Integer list

A semicolon-separated list of integers. For example:

1; 2; 3;

Float list

A semicolon-separated list of floats. For example:

1.0; 2.0; 3.0;

String List

A semicolon-separated list of strings. For example:

"Moose"; "Goats"; "Sheep";

Use of Commas and Semicolons

This topic is perhaps the most complex syntax issue in the file format, and it is very strict. Commas are used to separate array members; semicolons terminate each data item.

For example, if a template is defined as:

template mytemp {
DWORD myvar;
}

Then an instance of this template would look like:

mytemp dataTemp {
1;
}

A template containing another template is defined as:

template mytemp {
DWORD myvar;
DWORD myvar2;
}
template container {
FLOAT aFloat;
mytemp aTemp;
}

Then an instance of this template would look like:

container dataContainer {
1.1;
2; 3;;
}

Note that the second line that represents the mytemp inside container has two semicolons at the end of the line. The first semicolon indicates the end of the data item, aTemp (inside container), and the second semicolon indicates the end of the container.

If an array is defined as:

Template mytemp {
array DWORD myvar[3];
}

Then an instance of this would look like:

mytemp aTemp {
1, 2, 3;
}

In the array case, there is no need for the data items to be separated by semicolons because they are delineated by commas. The semicolon at the end marks the end of the array.

Consider a template that contains an array of data items defined by a template.

template mytemp {
DWORD myvar;
DWORD myvar2;
}
template container {
DWORD count;
array mytemp tempArray[count];
}

Then an instance of this would look like:

container aContainer {
3;
1;2;,3;4;,5;6;;
}


DirectX File Templates

This appendix lists the templates used by Microsoft® Direct3D® Retained Mode. A familiarity with Direct3D Retained Mode data types is assumed.

  • Template Name: Header
  • Template Name: Vector
  • Template Name: Coords2d
  • Template Name: Quaternion
  • Template Name: Matrix4x4
  • Template Name: ColorRGBA
  • Template Name: ColorRGB
  • Template Name: Indexed Color
  • Template Name: Boolean
  • Template Name: Boolean2d
  • Template Name: Material
  • Template Name: TextureFilename
  • Template Name: MeshFace
  • Template Name: MeshFaceWraps
  • Template Name: MeshTextureCoords
  • Template Name: MeshNormals
  • Template Name: MeshVertexColors
  • Template Name: MeshMaterialList
  • Template Name: Mesh
  • Template Name: FrameTransformMatrix
  • Template Name: Frame
  • Template Name: FloatKeys
  • Template Name: TimedFloatKeys
  • Template Name: AnimationKey
  • Template Name: AnimationOptions
  • Template Name: Animation
  • Template Name: AnimationSet

Template Name: Header

UUID

<3D82AB43-62DA-11cf-AB39-0020AF71E433>
Member Name | Type | Optional Array Size | Optional Data Objects
major | WORD | None
minor | WORD
flags | DWORD

Description

This template defines the application-specific header for the Direct3D Retained Mode usage of the DirectX file format. The Retained Mode uses the major and minor flags to specify the current major and minor versions for the Retained Mode file format.

Template Name: Vector

UUID

<3D82AB5E-62DA-11cf-AB39-0020AF71E433>
Member Name | Type | Optional Array Size | Optional Data Objects
x | FLOAT | None
y | FLOAT
z | FLOAT

Description

This template defines a vector.

Template Name: Coords2d

UUID

<F6F23F44-7686-11cf-8F52-0040333594A3>
Member Name | Type | Optional Array Size | Optional Data Objects
u | FLOAT | None
v | FLOAT

Description

A two dimensional vector used to define a mesh's texture coordinates.

Template Name: Quaternion

UUID

<10DD46A3-775B-11cf-8F52-0040333594A3>
Member Name | Type | Optional Array Size | Optional Data Objects
s | FLOAT | None
v | Vector

Description

Currently unused.

Template Name: Matrix4x4

UUID

<F6F23F45-7686-11cf-8F52-0040333594A3>
Member Name | Type | Optional Array Size | Optional Data Objects
matrix | array FLOAT | 16 | None

Description

This template defines a 4×4 matrix. This is used as a frame transformation matrix.

Template Name: ColorRGBA

UUID

<35FF44E0-6C7C-11cf-8F52-0040333594A3>
Member Name | Type | Optional Array Size | Optional Data Objects
red | FLOAT | None
green | FLOAT
blue | FLOAT
alpha | FLOAT

Description

This template defines a color object with an alpha component. This is used for the face color in the material template definition.

Template Name: ColorRGB

UUID

<D3E16E81-7835-11cf-8F52-0040333594A3>
Member Name | Type | Optional Array Size | Optional Data Objects
red | FLOAT | None
green | FLOAT
blue | FLOAT

Description

This template defines the basic RGB color object.

Template Name: Indexed Color

UUID

<1630B820-7842-11cf-8F52-0040333594A3>
Member Name | Type | Optional Array Size
index | DWORD
indexColor | ColorRGBA

Description

This template consists of an index parameter and an RGBA color and is used for defining mesh vertex colors. The index defines the vertex to which the color is applied.

Template Name: Boolean

UUID

<4885AE61-78E8-11cf-8F52-0040333594A3>
Member Name | Type | Optional Array Size | Optional Data Objects
DWORD | truefalse | None

Description

Defines a simple Boolean type. This template should be set to 0 or 1.

Template Name: Boolean2d

UUID

<4885AE63-78E8-11cf-8F52-0040333594A3>
Member Name | Type | Optional Array Size | Optional Data Objects
u | Boolean | None
v | Boolean

Description

This template defines a set of two Boolean values used in the MeshFaceWraps template to define the texture topology of an individual face.

Template Name: Material

UUID

<3D82AB4D-62DA-11cf-AB39-0020AF71E433>
Member Name | Type | Optional Array Size | Optional Data Objects
faceColor | ColorRGBA | Any
power | FLOAT
specularColor | ColorRGB
emissiveColor | ColorRGB

Description

This template defines a basic material color that can be applied to either a complete mesh or a mesh's individual faces. The power is the specular exponent of the material. Note that the ambient color requires an alpha component.

TextureFilename is an optional data object used by Direct3D Retained Mode. If this object is not present, the face is untextured.

Template Name: TextureFilename

UUID

<A42790E1-7810-11cf-8F52-0040333594A3>
Member Name | Type | Optional Array Size | Optional Data Objects
filename | STRING | None

Description

This template allows you to specify the file name of a texture to apply to a mesh or a face. This template should appear within a material object.

Template Name: MeshFace

UUID

<3D82AB5F-62DA-11cf-AB39-0020AF71E433>
Member Name | Type | Optional Array Size | Optional Data Objects
nFaceVertexIndices | DWORD | None
faceVertexIndices | array DWORD | nFaceVertexIndicies

Description

This template is used by the Mesh template to define a mesh's faces. Each element of the nFaceVertexIndices array references a mesh vertex used to build the face.

Template Name: MeshFaceWraps

UUID

<4885AE62-78E8-11cf-8F52-0040333594A3>
Member Name | Type | Optional Array Size | Optional Data Objects
nFaceWrapValues | DWORD | None
faceWrapValues | Boolean2d

Description

This template is used to define the texture topology of each face in a wrap. The value of the nFaceWrapValues member should be equal to the number of faces in a mesh.

Template Name: MeshTextureCoords

UUID

<F6F23F40-7686-11cf-8F52-0040333594A3>
Member Name | Type | Optional Array Size | Optional Data Objects
nTextureCoords | DWORD | None
textureCoords | array Coords2d | nTextureCoords

Description

This template defines a mesh's texture coordinates.

Template Name: MeshNormals

UUID

<F6F23F43-7686-11cf-8F52-0040333594A3>
Member Name | Type | Optional Array Size | Optional Data Objects
nNormals | DWORD | None
normals | array Vector | nNormals
nFaceNormals | DWORD
faceNormals | array MeshFace | nFaceNormals

Description

This template defines normals for a mesh. The first array of vectors is the normal vectors themselves, and the second array is an array of indexes specifying which normals should be applied to a given face. The value of the nFaceNormals member should be equal to the number of faces in a mesh.

Template Name: MeshVertexColors

UUID

<1630B821-7842-11cf-8F52-0040333594A3>
Member Name | Type | Optional Array Size | Optional Data Objects
nVertexColors | DWORD | None
vertexColors | array IndexedColor | nVertexColors

Description

This template specifies vertex colors for a mesh, instead of applying a material per face or per mesh.

Template Name: MeshMaterialList

UUID

<F6F23F42-7686-11cf-8F52-0040333594A3>
Member Name | Type | Optional Array Size | Optional Data Objects
nMaterials | DWORD | Material
nFaceIndexes | DWORD
FaceIndexes | array DWORD | nFaceIndexes

Description

This template is used in a mesh object to specify which material applies to which faces. The nMaterials member specifies how many materials are present, and materials specify which material to apply.

Template Name: Mesh

UUID

<3D82AB44-62DA-11cf-AB39-0020AF71E433>
Member Name | Type | Optional Array Size | Optional Data Objects
nVertices | DWORD | Any
vertices | array Vector | nVertices
nFaces | DWORD
faces | array MeshFace | nFaces

Description

This template defines a simple mesh. The first array is a list of vertices, and the second array defines the faces of the mesh by indexing into the vertex array.

Optional Data Elements

The following optional data elements are used by Direct3D Retained Mode.

MeshFaceWraps | If this is not present, wrapping for both u and v defaults to false.
MeshTextureCoords | If this is not present, there are no texture coordinates.
MeshNormals | If this is not present, normals are generated using the GenerateNormals method of the API.
MeshVertexColors | If this is not present, the colors default to white.
MeshMaterialList | If this is not present, the material defaults to white.

Template Name: FrameTransformMatrix

UUID

<F6F23F41-7686-11cf-8F52-0040333594A3>
Member Name | Type | Optional Array Size | Optional Data Objects
frameMatrix | Matrix4x4 | None

Description

This template defines a local transform for a frame (and all its child objects).

Template Name: Frame

UUID

<3D82AB46-62DA-11cf-AB39-0020AF71E433>
Member Name | Type | Optional Array Size | Optional Data Objects
None | Any

Description

This template defines a frame. Currently, the frame can contain objects of the type Mesh and a FrameTransformMatrix.

Optional Data Elements

The following optional data elements are used by Direct3D Retained Mode.

FrameTransformMatrix | If this element is not present, no local transform is applied to the frame.
Mesh | Any number of mesh objects that become children of the frame. These objects can be specified inline or by reference.

Template Name: FloatKeys

UUID

<10DD46A9-775B-11cf-8F52-0040333594A3>
Member Name | Type | Optional Array Size | Optional Data Objects
nValues | DWORD | None
values | array FLOAT | nValues

Description

This template defines an array of floating-point numbers (floats) and the number of floats in that array. This is used for defining sets of animation keys.

Template Name: TimedFloatKeys

UUID

<F406B180-7B3B-11cf-8F52-0040333594A3>
Member Name | Type | Optional Array Size | Optional Data Objects
time | DWORD | None
tfkeys | FloatKeys

Description

This template defines a set of floats and a positive time used in animations.

Template Name: AnimationKey

UUID

<10DD46A8-775B-11cf-8F52-0040333594A3>
Member Name | Type | Optional Array Size | Optional Data Objects
keyType | DWORD | None
nKeys | DWORD
keys | array TimedFloatKeys | nKeys

Description

This template defines a set of animation keys. The keyType member specifies whether the keys are rotation, scale or position keys (using the integers 0, 1, or 2 respectively).

Template Name: AnimationOptions

UUID

<E2BF56C0-840F-11cf-8F52-0040333594A3>
Member Name | Type | Optional Array Size | Optional Data Objects
openclosed | DWORD | None
positionquality | DWORD

Description

This template enables you to set the Direct3D Retained Mode Animation options. The openclosed member can be either 0 for a closed or 1 for an open animation. The positionquality member is used to set the position quality for any position keys specified and can either be 0 for spline positions or 1 for linear positions. By default, an animation is closed.

Template Name: Animation

UUID

<3D82AB4F-62DA-11cf-AB39-0020AF71E433>
Member Name | Type | Optional Array Size | Optional Data Objects
None | Any

Description

This template contains animations referencing a previous frame. It should contain one reference to a frame and at least one set of AnimationKeys. It also can contain an AnimationOptions data object.

Optional Data Elements

The following optional data elements are used by Direct3D Retained Mode.
AnimationKey | An animation is meaningless without AnimationKeys.
AnimationOptions | If this element is not present, an animation is closed.

Template Name: AnimationSet

UUID

<3D82AB50-62DA-11cf-AB39-0020AF71E433>
Member Name | Type | Optional Array Size | Optional Data Objects
none | Animation

Description

An AnimationSet template contains one or more Animation objects and is the equivalent to the Direct3D Retained Mode concept of animation sets. This means each animation within an animation set has the same time at any given point. Increasing the animation set's time will increase the time for all the animations it contains.


DirectX File Cube Example

This section describes a simple cube and then shows how to add textures, frames, and animations to it.

  • A Simple Cube
  • Adding Textures
  • Frames and Animations

A Simple Cube

This file defines a simple cube that has four red sides and two green sides. Notice in this file that optional information is being used to add information to the data object defined by the Mesh template.

Material RedMaterial {
1.000000;0.000000;0.000000;1.000000;;    // R = 1.0, G = 0.0, B = 0.0
0.000000;
0.000000;0.000000;0.000000;;
0.000000;0.000000;0.000000;;
}
Material GreenMaterial {
0.000000;1.000000;0.000000;1.000000;;     // R = 0.0, G = 1.0, B = 0.0
0.000000;
0.000000;0.000000;0.000000;;
0.000000;0.000000;0.000000;;
}
// Define a mesh with 8 vertices and 12 faces (triangles). Use
// optional data objects in the mesh to specify materials, normals,
// and texture coordinates.
Mesh CubeMesh {
8;                                // 8 vertices
1.000000;1.000000;-1.000000;,     // vertex 0
-1.000000;1.000000;-1.000000;,    // vertex 1
-1.000000;1.000000;1.000000;,     // etc...
1.000000;1.000000;1.000000;,
1.000000;-1.000000;-1.000000;,
-1.000000;-1.000000;-1.000000;,
-1.000000;-1.000000;1.000000;,
1.000000;-1.000000;1.000000;;

12;                      // 12 faces
3;0,1,2;,                // face 0 has 3 vertices
3;0,2,3;,                // etc...
3;0,4,5;,
3;0,5,1;,
3;1,5,6;,
3;1,6,2;,
3;2,6,7;,
3;2,7,3;,
3;3,7,4;,
3;3,4,0;,
3;4,7,6;,
3;4,6,5;;

// All required data has been defined. Now define optional data
// using the hierarchical nature of the file format.
MeshMaterialList {
2;                    // Number of materials used
12;                   // A material for each face
0,                    // face 0 uses the first
0,                    // material
0,
0,
0,
0,
0,
0,
1,                    // face 8 uses the second
1,                    // material
1,
1;;
{RedMaterial}         // References to the definitions
{GreenMaterial}       // of material 0 and 1
}
MeshNormals {
8;                    // define 8 normals
0.333333;0.666667;-0.666667;,
-0.816497;0.408248;-0.408248;,
-0.333333;0.666667;0.666667;,
0.816497;0.408248;0.408248;,
0.666667;-0.666667;-0.333333;,
-0.408248;-0.408248;-0.816497;,
-0.666667;-0.666667;0.333333;,
0.408248;-0.408248;0.816497;;
12;                   // For the 12 faces,
3;0,1,2;,             // define the normals
3;0,2,3;,
3;0,4,5;,
3;0,5,1;,
3;1,5,6;,
3;1,6,2;,
3;2,6,7;,
3;2,7,3;,
3;3,7,4;,
3;3,4,0;,
3;4,7,6;,
3;4,6,5;;
}
MeshTextureCoords {
8;                        // Define texture coords
0.000000;1.000000;        // for each of the vertices
1.000000;1.000000;
0.000000;1.000000;
1.000000;1.000000;
0.000000;0.000000;
1.000000;0.000000;
0.000000;0.000000;
1.000000;0.000000;;
}
}

Adding Textures

To add textures, use the hierarchical nature of the file format and add an optional TextureFilename data object to the Material data objects. So, the Material objects now read as follows:

Material RedMaterial {
1.000000;0.000000;0.000000;1.000000;;    // R = 1.0, G = 0.0, B = 0.0
0.000000;
0.000000;0.000000;0.000000;;
0.000000;0.000000;0.000000;;
TextureFilename {
"tex1.ppm";
}
}
Material GreenMaterial {
0.000000;1.000000;0.000000;1.000000;;     // R = 0.0, G = 1.0, B = 0.0
0.000000;
0.000000;0.000000;0.000000;;
0.000000;0.000000;0.000000;;
TextureFilename {
"win95.ppm";
}
}

Frames and Animations

This section shows how to add frames and animations to a simple cube.

  • Frames
  • AnimationSets and Animations

Frames

A frame is expected to take the following structure:

Frame Aframe {        // The frame name is chosen for convenience.
FrameTransformMatrix {
...transform data...
}
[ Meshes ] and/or [ More frames]
}

Place the previously defined cube mesh inside a frame with an identity transform. Then apply an animation to this frame.

Frame CubeFrame {
FrameTransformMatrix {
1.000000, 0.000000, 0.000000, 0.000000,
0.000000, 1.000000, 0.000000, 0.000000,
0.000000, 0.000000, 1.000000, 0.000000,
0.000000, 0.000000, 0.000000, 1.000000;;
}
{CubeMesh}        // You could have the mesh inline, but this                  // uses an object reference instead.
}

AnimationSets and Animations

Animations and AnimationSets in the DirectX file format map directly to the Direct3D Retained Mode animation concepts.

Animation Animation0 {        // The name is chosen for convenience.
{ Frame that it applies to&em;normally a reference }
AnimationKey {
...animation key data...
}
{ ...more animation keys... }
}

Animations are then grouped into AnimationSets:
AnimationSet AnimationSet0 { // The name is chosen for convenience.
{ an animation—could be inline or a reference }
{ ... more animations ... }
}

Now take the cube through an animation.

AnimationSet AnimationSet0 {
Animation Animation0 {
{CubeFrame}    // Use the frame containing the cube
AnimationKey {
2;             // Position keys
9;             // 9 keys
10; 3; -100.000000, 0.000000, 0.000000;;,
20; 3; -75.000000, 0.000000, 0.000000;;,
30; 3; -50.000000, 0.000000, 0.000000;;,
40; 3; -25.500000, 0.000000, 0.000000;;,
50; 3; 0.000000, 0.000000, 0.000000;;,
60; 3; 25.500000, 0.000000, 0.000000;;,
70; 3; 50.000000, 0.000000, 0.000000;;,
80; 3; 75.500000, 0.000000, 0.000000;;,
90; 3; 100.000000, 0.000000, 0.000000;;;
}
}
}


DirectX File Binary Format

This section details the binary version of the Microsoft® DirectX® file format as introduced with the release of DirectX 3.0. This appendix should be read in conjunction with the DirectX File Format Architecture section.

The binary format is a tokenized representation of the text format. Tokens can be stand-alone or accompanied by primitive data records. Stand-alone tokens give grammatical structure and record-bearing tokens supply the necessary data.

Note that all data is stored in little endian format.

A valid binary data stream consists of a header followed by templates and/or data objects.

This section discusses the following components of the binary file format:

  • Header
  • Tokens
  • Token Records
  • Templates
  • Data

In addition, example templates are provided, in Example Templates. A binary data object is shown in Example Data.

Header

The following definitions should be used when directly reading and writing the binary header. Note that compressed data streams are not currently supported and are therefore not detailed here.

#define XOFFILE_FORMAT_MAGIC \
  ((long)'x' + ((long)'o' << 8) + ((long)'f' << 16) + ((long)' ' << 24))

#define XOFFILE_FORMAT_VERSION \
  ((long)'0' + ((long)'3' << 8) + ((long)'0' << 16) + ((long)'2' << 24))

#define XOFFILE_FORMAT_BINARY \
  ((long)'b' + ((long)'i' << 8) + ((long)'n' << 16) + ((long)' ' << 24))

#define XOFFILE_FORMAT_TEXT   \
  ((long)'t' + ((long)'x' << 8) + ((long)'t' << 16) + ((long)' ' << 24))

#define XOFFILE_FORMAT_COMPRESSED \
  ((long)'c' + ((long)'m' << 8) + ((long)'p' << 16) + ((long)' ' << 24))

#define XOFFILE_FORMAT_FLOAT_BITS_32 \
  ((long)'0' + ((long)'0' << 8) + ((long)'3' << 16) + ((long)'2' << 24))

#define XOFFILE_FORMAT_FLOAT_BITS_64 \
  ((long)'0' + ((long)'0' << 8) + ((long)'6' << 16) + ((long)'4' << 24))

Tokens

Tokens are written as little endian WORDs. A list of token values follows. The list is divided into record-bearing and stand-alone tokens.

Record-bearing

#define TOKEN_NAME 1
#define TOKEN_STRING 2
#define TOKEN_INTEGER 3
#define TOKEN_GUID 5
#define TOKEN_INTEGER_LIST 6
#define TOKEN_FLOAT_LIST 7

Stand-alone

#define TOKEN_OBRACE 10
#define TOKEN_CBRACE 11
#define TOKEN_OPAREN 12
#define TOKEN_CPAREN 13
#define TOKEN_OBRACKET 14
#define TOKEN_CBRACKET 15
#define TOKEN_OANGLE 16
#define TOKEN_CANGLE 17
#define TOKEN_DOT 18
#define TOKEN_COMMA 19
#define TOKEN_SEMICOLON 20
#define TOKEN_TEMPLATE 31
#define TOKEN_WORD 40
#define TOKEN_DWORD 41
#define TOKEN_FLOAT 42
#define TOKEN_DOUBLE 43
#define TOKEN_CHAR 44
#define TOKEN_UCHAR 45
#define TOKEN_SWORD 46
#define TOKEN_SDWORD 47
#define TOKEN_VOID 48
#define TOKEN_LPSTR 49
#define TOKEN_UNICODE 50
#define TOKEN_CSTRING 51
#define TOKEN_ARRAY 52

Token Records

This section describes the format of the records for each of the record-bearing tokens.

TOKEN_NAME

TOKEN_NAME is a variable length record. The token is followed by a count value that specifies the number of bytes that follow in the name field. An ASCII name of length count completes the record.
Field | Type | Size (bytes) | Contents
token | WORD | 2 | TOKEN_NAME
count | DWORD | 4 | Length of name field, in bytes
name | BYTE array | Count | ASCII name

TOKEN_STRING

TOKEN_STRING is a variable length record. The token is followed by a count value that specifies the number of bytes that follow in the string field. An ASCII string of length count continues the record, which is completed by a terminating token. The choice of terminator is determined by syntax issues discussed elsewhere.
Field | Type | Size (bytes) | Contents
token | WORD | 2 | TOKEN_STRING
count | DWORD | 4 | Length of string field in bytes
string | BYTE array | Count | ASCII string
terminator | DWORD | 4 | TOKEN_SEMICOLON or TOKEN_COMMA

TOKEN_INTEGER

TOKEN_INTEGER is a fixed length record. The token is followed by the integer value required.
Field | Type | Size (bytes) | Contents
token | WORD | 2 | TOKEN_INTEGER
value | DWORD | 4 | Single integer

TOKEN_GUID

TOKEN_GUID is a fixed-length record. The token is followed by the four data fields as defined by the OSF DCE standard.
Field | Type | Size (bytes) | Contents
token | WORD | 2 | TOKEN_GUID
data1 | DWORD | 4 | UUID data field 1
data2 | WORD | 2 | UUID data field 2
data3 | WORD | 2 | UUID data field 3
data4 | BYTE array | 8 | UUID data field 4

TOKEN_INTEGER_LIST

TOKEN_INTEGER_LIST is a variable length record. The token is followed by a count value that specifies the number of integers that follow in the list field. For efficiency, consecutive integer lists should be compounded into a single list.
Field | Type | Size (bytes) | Contents
token | WORD | 2 | TOKEN_INTEGER_LIST
count | DWORD | 4 | Number of integers in list field
list | DWORD array | 4 x count | Integer list

TOKEN_FLOAT_LIST

TOKEN_FLOAT_LIST is a variable-length record. The token is followed by a count value that specifies the number of floats or doubles that follow in the list field. The size of the floating point value (float or double) is determined by the value of float size specified in the file header. For efficiency, consecutive TOKEN_FLOAT_LISTs should be compounded into a single list.
Field | Type | Size (bytes) | Contents
token | WORD | 2 | TOKEN_FLOAT_LIST
count | DWORD | 4 | Number of floats or doubles in list field
list | float/double array | 4 or 8 x count | Float or double list

Templates

A template has the following syntax definition:

template              : TOKEN_TEMPLATE name TOKEN_OBRACE
                            class_id
                            template_parts
                            TOKEN_CBRACE

template_parts        : template_members_part TOKEN_OBRACKET
                        template_option_info
                        TOKEN_CBRACKET
                      | template_members_list

template_members_part : /* Empty */
                      | template_members_list

template_option_info  : ellipsis
                      | template_option_list

template_members_list :    template_members
                      | template_members_list template_members

template_members      : primitive
                      | array
                      | template_reference

primitive             : primitive_type optional_name TOKEN_SEMICOLON

array                 : TOKEN_ARRAY array_data_type name dimension_list
                        TOKEN_SEMICOLON

template_reference    : name optional_name YT_SEMICOLON

primitive_type        : TOKEN_WORD
                      | TOKEN_DWORD
                      | TOKEN_FLOAT
                      | TOKEN_DOUBLE
                      | TOKEN_CHAR
                      | TOKEN_UCHAR
                      | TOKEN_SWORD
                      | TOKEN_SDWORD
                      | TOKEN_LPSTR
                      | TOKEN_UNICODE
                      | TOKEN_CSTRING

array_data_type       : primitive_type
                      | name

dimension_list        : dimension
                      | dimension_list dimension

dimension             : TOKEN_OBRACKET dimension_size TOKEN_CBRACKET

dimension_size        : TOKEN_INTEGER
                      | name

template_option_list  : template_option_part
                      | template_option_list template_option_part

template_option_part  : name optional_class_id

name                  : TOKEN_NAME

optional_name         : /* Empty */
                      | name

class_id              : TOKEN_GUID

optional_class_id     : /* Empty */
                      | class_id

ellipsis              : TOKEN_DOT TOKEN_DOT TOKEN_DOT

Data

A data object has the following syntax definition.

Note that in number_list and float_list data in binary files, TOKEN_COMMA and TOKEN_SEMICOLON are not used. The comma and semicolon are used in string_list data. Also note that you can only use data_reference for optional data members.

object                : identifier optional_name TOKEN_OBRACE
                            optional_class_id
                            data_parts_list
                            TOKEN_CBRACE
data_parts_list       : data_part
                      | data_parts_list data_part

data_part             : data_reference
                      | object
                      | number_list
                      | float_list
                      | string_list

number_list           : TOKEN_INTEGER_LIST

float_list            : TOKEN_FLOAT_LIST

string_list           : string_list_1 list_separator

string_list_1         : string
                      | string_list_1 list_separator string

list_separator        : comma
                      | semicolon

string                : TOKEN_STRING

identifier            : name
                      | primitive_type

data_reference        : TOKEN_OBRACE name optional_class_id TOKEN_CBRACE

Example Templates

Two example binary template definitions follow. Note that data is stored in little endian format, which is not shown in these examples.

The closed template RGB is identified by the UUID {55b6d780-37ec-11d0-ab39-0020af71e433} and has three members r, g, and b each of type float.

TOKEN_TEMPLATE, TOKEN_NAME, 3, 'R', 'G', 'B', TOKEN_OBRACE,
TOKEN_GUID, 55b6d780, 37ec, 11d0, ab, 39, 00, 20, af, 71, e4, 33,
TOKEN_FLOAT, TOKEN_NAME, 1, 'r', TOKEN_SEMICOLON,
TOKEN_FLOAT, TOKEN_NAME, 1, 'g', TOKEN_SEMICOLON,
TOKEN_FLOAT, TOKEN_NAME, 1, 'b', TOKEN_SEMICOLON,
TOKEN_CBRACE

The closed template Matrix4x4 is identified by the UUID {55b6d781-37ec-11d0-ab39-0020af71e433} and has one member—a two-dimensional array named matrix of type float.

TOKEN_TEMPLATE, TOKEN_NAME, 9, 'M', 'a', 't', 'r', 'i', 'x', '4', 'x', '4', TOKEN_OBRACE,
TOKEN_GUID, 55b6d781, 37ec, 11d0, ab, 39, 00, 20, af, 71, e4, 33,
TOKEN_ARRAY, TOKEN_FLOAT, TOKEN_NAME, 6, 'm', 'a', 't', 'r', 'i', 'x',
TOKEN_OBRACKET, TOKEN_INTEGER, 4, TOKEN_CBRACKET,
TOKEN_OBRACKET, TOKEN_INTEGER, 4, TOKEN_CBRACKET,
TOKEN_CBRACE

Example Data

The binary data object that follows shows an instance of the RGB template defined earlier. The example object is named blue, and its three members r, g, and b have the values 0.0, 0.0 and 1.0, respectively. Note that data is stored in little endian format, which is not shown in this example.

TOKEN_NAME, 3, 'R', 'G', 'B', TOKEN_NAME, 4, 'b', 'l', 'u', 'e', TOKEN_OBRACE,
TOKEN_FLOAT_LIST, 3, 0.0, 0.0, 1.0, TOKEN_CBRACE


DirectX File Conv3ds.exe Utility

The Conv3ds.exe utility converts three-dimensional (3-D) models produced by Autodesk 3-D Studio and other modeling packages into the Microsoft® DirectX® file format. By default, the utility produces binary .x files with no templates.

This article contains the following sections.

  • Using Conv3ds.exe
  • Conv3ds.exe Optional Arguments
  • 3DS Files Produced from Lightwave Objects
  • Hints and Tips

Using Conv3ds.exe

You can run Conv3ds.exe with no options, and it will produce an .x file containing a hierarchy of frames. For example, consider the command:

conv3ds File.3ds

This command will produce an .x file called File.x from the .3ds file. You can use IDirect3DRMFrame3::Load to load the frame.

Conv3ds.exe Optional Arguments

Conv3ds.exe -A

If the .3ds file contains key frame data, you can use the -A option to produce an .x file that contains an animation set. The command for doing this would be:

conv3ds -A File.3ds

The File.3ds parameter is the name of the file to be converted. You can use IDirect3DRMAnimationSet2::Load to load the animation.

Conv3ds.exe -m

Use the -m option to make an .x file that contains a single mesh made from all the objects in the .3ds file.

conv3ds -m File.3ds

Use IDirect3DRMMeshBuilder3::Load to load the mesh.

Conv3ds.exe -T

Use the-T option to wrap all the objects and frame hierarchies in a single top-level frame. Using this option, all the frames and objects in the .3ds file can be loaded with a single call to IDirect3DRMFrame3::Load. The first top-level frame hierarchy in the .x file will be loaded. The frame containing all the other frames and meshes is called "x3ds_filename" (without the .3ds extension). The -T option will have no effect if it is used with the -m option.

Conv3ds.exe -s

The -s option allows you to specify a scale factor for all the objects converted in the .3ds file. For example, the following command makes all objects 10 times bigger:

conv3ds -s10 File.3ds

The following command makes all objects 10 times smaller:

conv3ds -s0.1 File.3ds

Conv3ds.exe -r

The -r option reverses the winding order of the faces when the .3ds file is converted. If, after converting the .3ds file and viewing it in Direct3D, the object appears inside-out, try converting it with the -r option. All Lightwave models exported as .3ds files need this option. See 3DS Files Produced from Lightwave Objects for details.

Conv3ds.exe -v

The -v option turns on verbose output mode. Specify an integer with it. The following table shows the currently supported integers.
Option | Meaning
-v0 | Default. Verbose mode off.
-v1 | Prints warnings about bad objects, and prints general information about what the converter is doing.
-v2 | Prints basic key frame information, the objects being included in the conversion process, and information about the objects being saved.
-v3 | Very verbose. Mostly useful for the debugging information it provides.

Conv3ds.exe -e

The -e option allows you to change the extension for texture map files. For example, consider the command:

conv3ds -e"ppm" File.3ds

If File.3ds contains objects that reference the texture map file Brick.gif, the .x file will reference the texture map file Brick.ppm. The converter does not convert the texture map file. The texture map files must be in the D3DPATH when the resulting .x file is loaded. The D3DPath is an environment variable that sets the default search path.

Conv3ds.exe -x

The -x option forces the Conv3ds.exe utility to produce a text .x file, instead of a binary .x file. Text files are larger but can be hand-edited easily.

Conv3ds.exe -X

The -X option forces the Conv3ds.exe utility to include the Direct3D Retained Mode .x file templates in the file. By default, the templates are not included.

Conv3ds.exe -t

The -t option specifies that the .x file produced will not contain texture information.

Conv3ds.exe -N

The -N option specifies that the .x file produced will not contain normal vector information. All the Direct3D Retained Mode load calls will generate normal vectors for objects with no normal vectors in the .x file.

Conv3ds.exe -c

The -c option specifies that the .x file produced should not contain texture coordinates. By default, if you use the -m option, the mesh that is output will contain (0,0) uv texture coordinates if the .3ds object had no texture coordinates.

Conv3ds.exe -f

The -f option specifies that the .x file produced should not contain a frame transformation matrix.

Conv3ds.exe - z and Conv3ds.exe -Z

The -z and -Z options allow you to adjust the alpha face color value of all the materials referenced by objects in the .x file. For example, the following command causes Conv3ds.exe to add 0.1 to all alpha values under 0.2:

conv3ds -z0.1 -Z0.2 File.3ds

The following command causes Conv3ds.exe to subtract 0.2 from the alpha values for all alphas:

conv3ds-z"-0.2" -z1 File.3ds

Conv3ds.exe -o

The -o option allows you to specify the file name for the .x file produced.

Conv3ds.exe -h

The -h option tells the converter not to try to resolve any hierarchy information in the .3ds file (usually produced by the key framer). Instead, all the objects are output in top-level frames if the -m option is not used.

3DS Files Produced from Lightwave Objects

There are several issues with .3ds files exported by the Trans3d plug-in for Lightwave. These are best handled using the following Conv3ds.exe command:

conv3ds -r -N -f -h -T|m trans3dfile.3ds

All the .3ds objects produced by Trans3d and the Lightwave object editor need their winding order reversed. Otherwise, they appear inside-out when displayed. They contain no surface normal vector information.

Hints and Tips

If you cannot see objects produced by Conv3ds.exe after loading them into the Direct3D Retained Mode viewer, use the scale option -s with a scale factor of approximately 100. This will increase the scale of the objects in the .x file.

If, after loading the object into the viewer and switching from flat shading into Gouraud shading, the object turns dark gray, try converting with the -N option.

If the textures are not loaded after the object is converted, check whether the object is referencing either .ppm or .bmp files by using the -e option. Also check whether the textures' widths and heights are a power of 2. Make sure the textures are stored in one of the directories in your D3DPATH.

Currently, Conv3ds.exe cannot handle dummy frames used in .3ds animations. It ignores them. However, it will convert any child objects.


DirectX File Samples

The following samples demonstrate loading from, converting to, and saving to the Microsoft® DirectX® file format. These samples come with the DirectX Foundation 6.0 Software Development Kit (SDK) and can be found in folders beneath the Mssdk\Samples\Multimedia\D3drm\Src subdirectory.

  • CONVXFMT
  • XOFLOAD
  • XOFSAVE
  • XOFUSER

CONVXFMT

Path

Mssdk\Samples\Multimedia\D3drm\Src\Convxfmt

Description

Converts from one DirectX file format to another.

XOFLOAD

Path

Mssdk\Samples\Multimedia\D3drm\Src\Xofload

Description

Loads a file using the Direct3D Retained Mode templates.

XOFSAVE

Path

Mssdk\Samples\Multimedia\D3drm\Src\Xofsave

Description

Saves a file using the Direct3D Retained Mode templates.

XOFUSER

Path

Mssdk\Samples\Multimedia\D3drm\Src\Xofuser

Description

Saves a file using user-defined templates.


DirectX File Reference

This section discusses the function, interfaces, objects, and data types introduced with DirectX version 6.0 that are used to write to and read from Microsoft® DirectX® (.x) files. This section also briefly introduces the relationship between the interfaces and provides a hierarchy chart that shows interface inheritance. The DirectX file methods allow reading from and writing to both text and binary files.

You should be familiar with the format of DirectX files as outlined in DirectX File Format Architecture before using these interfaces. Understanding the file format will help you better understand the purpose of the interfaces and their methods.

This section contains the following topics.

  • Introduction
  • Hierarchy Chart
  • Function and Interfaces
  • Data Types
  • Return Values

Introduction

The following summary discusses how to load data from a DirectX (.x) file and how to save data to a DirectX file. The DirectX file methods work with both text and binary DirectX files and support loading from various sources, such as files, memory, resources, or URLs.

To use the DirectX file interfaces, you must first use the DirectXFileCreate function to create an IDirectXFile object.

Loading a File

Use the following procedure to load a DirectX file.

  1. Use the DirectXFileCreate function to create an IDirectXFile object.
  2. If templates are not present in the DirectX file that you are going to load, use the IDirectXFile::RegisterTemplates method to register those templates.
  3. Use the IDirectXFile::CreateEnumObject method to create an IDirectXFileEnumObject enumerator object.
  4. Loop through the objects in the file. For each object, perform the following steps.
    1. Use the IDirectXFileEnumObject::GetNextDataObject method to retrieve each IDirectXFileData object.
    2. Use the IDirectXFileData::GetType method to retrieve the data's type.
    3. Load the data using the IDirectXFileData::GetData method.
    4. If the object has optional members, retrieve the optional members by calling the IDirectXFileData::GetNextObject method.
  5. Release the IDirectXFileData object.
  6. Release the IDirectXFileEnumObject object.
  7. Release the IDirectXFile object.

Saving a File

Use the following procedure to save DirectX file templates and data to a DirectX file.

  1. Use the DirectXFileCreate function to create an IDirectXFile object.
  2. Use the IDirectXFile::RegisterTemplates method to inform the DirectX file system about any templates that you are going to use.
  3. Use the IDirectXFile::CreateSaveObject method to create an IDirectXFileSaveObject object.
  4. Use the IDirectXFileSaveObject::SaveTemplates method to save templates, if desired.
  5. Loop through the objects to save. For each top-level object, perform the following steps.
    1. Use the IDirectXFileSaveObject::CreateDataObject method to create an IDirectXFileData object as a top-level object in the file. If the top-level data object has optional child objects, add them to the object by using the appropriate method from the "How to Add" column in the next step.
    2. Each IDirectXFileData object can have optional child objects if its template allows it. The child objects can be any one of the three types of objects: IDirectXFileData, IDirectXFileDataReference, or IDirectXFileBinary. Loop through the objects you need to save, adding each optional child member to the object list in the manner appropriate to its type, as shown in the following table.
      Object Type | How to Add
      Data | Call the IDirectXFileSaveObject::CreateDataObject method to create an IDirectXFileData object, and then call the IDirectXFileData::AddDataObject method to add it as a child of the object.
      Data Reference | Call the IDirectXFileData::AddDataReference method to create and add the data reference object as a child of the object.
      Binary | Call the IDirectXFileData::AddBinaryObject method to create and add the binary object as a child of the object.
    3. Call the IDirectXFileSaveObject::SaveData method to save the data object and all of its children.
    4. Release the IDirectXFileData object.
  6. Release the IDirectXFileSaveObject object.
  7. Release the IDirectXFile object.

Hierarchy Chart

The following diagram shows the relationship between the DirectX file interfaces.

 IUnknown
 |
 +--IDirectXFile
 |
 +--IDirectXFileEnumObject
 |
 +--IDirectXFileObject
 |  |
 |  +--IDirectXFileBinary
 |  |
 |  +--IDirectXFileData
 |  |
 |  +--IDirectXFileDataReference
 |
 +--IDirectXFileSaveObject

Function and Interfaces

DirectX supplies the following DirectX file function and interfaces.

  • DirectXFileCreate function
  • IDirectXFile
  • IDirectXFileBinary
  • IDirectXFileData
  • IDirectXFileDataReference
  • IDirectXFileEnumObject
  • IDirectXFileObject
  • IDirectXFileSaveObject

The following table provides the Globally Unique Identifier (GUID) that corresponds with each DirectX File interface. For information about using a GUID with the QueryInterface method to determine a child object's type, see the introduction to the IDirectXFileData interface.
Interface | GUID
IDirectXFile | IID_IDirectXFile
IDirectXFileBinary | IID_IDirectXFileBinary
IDirectXFileData | IID_IDirectXFileData
IDirectXFileDataReference | IID_IDirectXFileDataReference
IDirectXFileEnumObject | IID_IDirectXFileEnumObject
IDirectXFileObject | IID_IDirectXFileObject
IDirectXFileSaveObject | IID_IDirectXFileSaveObject

DirectXFileCreate Function

The DirectXFileCreate function creates the IDirectXFile interface.

Syntax

STDAPI DirectXFileCreate(LPDIRECTXFILE *ppDirectXFile);

Parameters

ppDirectXFile
Address of a pointer to receive the created IDirectXFile interface.

Return Value

Returns one of the following values:
DXFILE_OK
DXFILEERR_BADALLOC
DXFILEERR_BADVALUE

Remarks

After using this function, use the IDirectXFile methods to: register templates (RegisterTemplates), create an enumerator object (CreateEnumObject), or create a save object (CreateSaveObject).

IDirectXFile

This interface enables you to create the IDirectXFileEnumObject and IDirectXFileSaveObject objects and to register templates.

Use the DirectXFileCreate function to create an instance of this object.

The IDirectXFile interface provides the following methods.

  • CreateEnumObject
  • CreateSaveObject
  • RegisterTemplates

IDirectXFile::CreateEnumObject

IDirectXFile

Creates an enumerator object.

Syntax

HRESULT CreateEnumObject(
  LPVOID pvSource,
  DXFILELOADOPTIONS dwLoadOptions,
  LPDIRECTXFILEENUMOBJECT * ppEnumObj);

Parameters

pvSource
Pointer to data whose contents depend on the value of dwLoadOptions as outlined in the following table.
dwLoadOptions value | Contents of pvSource
DXFILELOAD_FROMFILE | Name of the file
DXFILELOAD_FROMRESOURCE | DXFILELOADRESOURCE structure
DXFILELOAD_FROMMEMORY | DXFILELOADMEMORY structure
DXFILELOAD_FROMURL | Name of the Uniform Resource Locator (URL)
dwLoadOptions
Value that specifies the source of the data. One of the DXFILELOADOPTIONS values.
ppEnumObj
Address of a pointer to receive the created IDirectXFileEnumObject interface.

Return Value

Returns one of the following values:
DXFILE_OK
DXFILEERR_BADALLOC
DXFILEERR_BADFILEFLOATSIZE
DXFILEERR_BADFILETYPE
DXFILEERR_BADFILEVERSION
DXFILEERR_BADRESOURCE
DXFILEERR_BADVALUE
DXFILEERR_FILENOTFOUND
DXFILEERR_RESOURCENOTFOUND
DXFILEERR_URLNOTFOUND

Remarks

After using this method, use one of the IDirectXFileEnumObject methods to retrieve a data object.

IDirectXFile::CreateSaveObject

IDirectXFile

Creates an instance of an IDirectXFileSaveObject object.

Syntax

HRESULT CreateSaveObject(
  LPCSTR szFileName,
  DXFILEFORMAT dwFileFormat,
  LPDIRECTXFILESAVEOBJECT * ppSaveObj);

Parameters

szFileName
Pointer to the name of the file to use for saving data.
dwFileFormat
File format. One of the DXFILEFORMAT constants.
ppSaveObj
Address of a pointer to receive the created IDirectXFileSaveObject object.

Return Value

Returns one of the following values:
DXFILE_OK
DXFILEERR_BADALLOC
DXFILEERR_BADFILE
DXFILEERR_BADVALUE

Remarks

After using this method, use methods of the IDirectXFileSaveObject interface to create data objects and to save templates or data.

IDirectXFile::RegisterTemplates

IDirectXFile

Registers custom templates.

Syntax

HRESULT RegisterTemplates(
  LPVOID pvData,
  DWORD cbSize);

Parameters

pvData
Pointer to a buffer consisting of a DirectX file in text or binary format that contains templates.
cbSize
Size of the buffer pointed to by pvData, in bytes.

Return Value

Returns one of the following values:
DXFILE_OK
DXFILEERR_BADFILEFLOATSIZE
DXFILEERR_BADFILETYPE
DXFILEERR_BADFILEVERSION
DXFILEERR_BADVALUE
DXFILEERR_PARSEERROR

Remarks

The following code fragment provides an example call to RegisterTemplates and example contents for the buffer to which pvData points.

IDirectXFile * pDXFile;

char *szTemplates = "xof 0303txt 0032\
    template SimpleData { \
        <2b934580-9e9a-11cf-ab39-0020af71e433> \
        DWORD item1;DWORD item2;DWORD item3;} \
    template ArrayData { \
        <2b934581-9e9a-11cf-ab39-0020af71e433> \
        DWORD cItems; array DWORD aItem[2][cItems]; [...] } \
    template RestrictedData { \
        <2b934582-9e9a-11cf-ab39-0020af71e433> \
        DWORD item; [SimpleData]}";

hr = pDXFile->RegisterTemplates(szTemplates, strlen(szTemplates));

All templates must specify a name and a UUID (Universally Unique Identifier).

IDirectXFileBinary

This interface enables you to read binary data and to retrieve information about it.

The IDirectXFileBinary interface provides the following methods.

  • GetMimeType
  • GetSize
  • Read

In addition, IDirectXFileBinary inherits the IDirectXFileObject::GetId and IDirectXFileObject::GetName methods.

IDirectXFileBinary::GetMimeType

IDirectXFileBinary

Retrieves the mime type for the binary data.

Syntax

HRESULT GetMimeType(LPCSTR * pszMimeType);

Parameters

pszMimeType
Address of a pointer to receive the mime type string.

Return Value

Returns one of the following values:
DXFILE_OK
DXFILEERR_BADVALUE

When there is no Mime type specified in a specified .X file for a binary object, the function will set *pszMimeType to NULL.

IDirectXFileBinary::GetSize

IDirectXFileBinary

Retrieves the size of the binary data.

Syntax

HRESULT GetSize(DWORD * pcbSize);

Parameters

pcbSize
Pointer to receive the size of the binary data, in bytes.

Return Value

Returns one of the following values:
DXFILE_OK
DXFILEERR_BADVALUE

IDirectXFileBinary::Read

IDirectXFileBinary

Reads binary data.

Syntax

HRESULT Read(
  LPVOID pvData,
  DWORD cbSize,
  LPDWORD pcbRead);

Parameters

pvData
Pointer to the buffer that receives the data that has been read.
cbSize
Size of the buffer pointed to by pvData, in bytes.
pcbRead
Pointer to the number of bytes read.

Return Value

Returns one of the following values:
DXFILE_OK
DXFILEERR_BADVALUE
DXFILEERR_NOMOREDATA

IDirectXFileData

The IDirectXFileData interface provides methods that enable you to build or to access the immediate hierarchy of the data object. Template restrictions determine the hierarchy. Data types allowed by the template are called optional members. The optional members are not required, but an object might miss important information without them. These optional members are saved as children of the data object. The children can be another data object, a reference to an earlier data object, or a binary object.

When saving objects to a DirectX file, use AddBinaryObject, AddDataObject, or AddDataReference to add binary objects, data objects, or data reference objects, respectively, to the file. For more information, see Saving a File.

When enumerating objects in an existing DirectX file, use the GetData, GetNextObject, and GetType methods as follows:

  1. Use GetType to retrieve the object's template's GUID. For example, for a mesh object GetType retrieves the GUID for the mesh template.
  2. Use GetData to retrieve required members of the object in a contiguous chunk of memory.
  3. For each child object, perform the following steps.
    1. Use GetNextObject to retrieve a child object.
    2. Use QueryInterface to determine the child object's type (data, data reference, or binary) by querying for support of the IDirectXFileData, IDirectXFileDataReference, and IDirectXFileBinary interfaces, in turn. The interface supported indicates the object's type. The following code fragment determines whether an object is a binary object by determining if it supports IDirectXFileBinary.
      IDirectXFileObject *DXFileObj;
IDirectXFileBinary *DXFileBinary;

if (FAILED(DXFileObj->QueryInterface(IID_IDirectXFileBinary,
                                     (LPVOID *)&DXFileBinary))
{
    // Object does not support IDirectXFileBinary and therefore
    // is not a binary object.
}
else
{
    // Object is binary.
}
    3. After you have determined the child object's type, use methods of the appropriate interface (IDirectXFileData, IDirectXFileDataReference, or IDirectXFileBinary) to act upon the child object.

The IDirectXFileData interface provides the following methods.

  • AddBinaryObject
  • AddDataObject
  • AddDataReference
  • GetData
  • GetNextObject
  • GetType

In addition, IDirectXFileData inherits the IDirectXFileObject::GetId and IDirectXFileObject::GetName methods.

IDirectXFileData::AddBinaryObject

IDirectXFileData

Creates and adds a binary object as a child object.

Syntax

HRESULT AddBinaryObject(
  LPCSTR szName,
  const GUID * pguid,
  LPCSTR szMimeType,
  LPVOID pvData,
  DWORD cbSize);

Parameters

szName
Pointer to the name of the object. Optional, specify NULL if the object does not need a name.
pguid
Pointer to the GUID representing the object. Optional, specify NULL if the object does not need a GUID.
szMimeType
Pointer to the object's mime type.
pvData
Pointer to the object's data.
cbSize
Size of the buffer pointed to by pvData, in bytes.

Return Value

Returns one of the following values:
DXFILE_OK
DXFILEERR_BADALLOC
DXFILEERR_BADVALUE

Remarks

For more information about saving child objects, see the introduction to this interface, IDirectXFileData.

IDirectXFileData::AddDataObject

IDirectXFileData

Adds a data object as a child object.

Syntax

HRESULT AddDataObject(LPDIRECTXFILEDATA pDataObj);

Parameters

pDataObj
Pointer to the IDirectXFileData object to add as a child object.

Return Value

Returns one of the following values:
DXFILE_OK
DXFILEERR_BADALLOC
DXFILEERR_BADVALUE

Remarks

Use the IDirectXFileSaveObject::CreateDataObject method to create the IDirectXFileData object before calling this method.

For more information about saving objects, see the introduction to this interface, IDirectXFileData.

IDirectXFileData::AddDataReference

IDirectXFileData

Creates and adds a data reference object as a child object.

Syntax

HRESULT AddDataReference(
  LPCSTR szRef,
  const GUID * pguidRef);

Parameters

szRef
Pointer to the name of the referenced data object. Can be NULL if pguidRef provides a reference to the GUID.
pguidRef
Pointer to the GUID representing the data. Can be NULL if szRef provides a reference to the name.

Return Value

Returns one of the following values:
DXFILE_OK
DXFILEERR_BADALLOC
DXFILEERR_BADVALUE

Remarks

At least one of the szRef or pguidRef parameters must be non-NULL.

For more information about saving objects, see the introduction to this interface, IDirectXFileData.

IDirectXFileData::GetData

IDirectXFileData

Retrieves the data for one of the object's members or the data for all members.

Syntax

HRESULT GetData(
  LPCSTR szMember,
  DWORD * pcbSize,
  void ** ppvData);

Parameters

szMember
Name of the member for which to retrieve data. Specify NULL to retrieve all required members' data.
pcbSize
Pointer to receive the ppvData buffer size, in bytes.
ppvData
Address of a pointer to receive the data associated with szMember. If szMember is NULL, *ppvData is set to point to a buffer containing all required members' data in a contiguous block of memory.

Return Value

Returns one of the following values:
DXFILE_OK
DXFILEERR_BADARRAYSIZE
DXFILEERR_BADDATAREFERENCE
DXFILEERR_BADVALUE

Remarks

This method retrieves the data for required members of a data object but no data for optional (child) members. Use GetNextObject to retrieve child objects.

For more information about enumerating objects, see the introduction to this interface, IDirectXFileData.

IDirectXFileData::GetNextObject

IDirectXFileData

Retrieves the next child data object, data reference object, or binary object in the DirectX file.

Syntax

HRESULT GetNextObject(LPDIRECTXFILEOBJECT * ppChildObj);

Parameters

ppChildObj
Address to receive a pointer to the child object's IDirectXFileObject interface.

Return Value

Returns one of the following values:
DXFILE_OK
DXFILEERR_BADVALUE
DXFILEERR_NOMOREOBJECTS

Remarks

To determine the type of object retrieved, use QueryInterface to query the retrieved object for support of IDirectXFileData, IDirectXFileDataReference, or IDirectXFileBinary interfaces. The interface supported indicates the type of object (data, data reference, or binary).

For more information about child objects, enumerating objects and determining the type of object, see the introduction to this interface, IDirectXFileData.

IDirectXFileData::GetType

IDirectXFileData

Retrieves the GUID of the object's template.

Syntax

HRESULT GetType(const GUID ** ppguid);

Parameters

ppguid
Address of a pointer to receive the GUID of the object's template.

Return Value

Returns one of the following values:
DXFILE_OK
DXFILEERR_BADVALUE

IDirectXFileDataReference

The IDirectXFileDataReference interface provides support for data reference objects. A data reference object refers to a data object that is defined earlier in the file. This allows you to use the same object multiple times without repeating it in the file.

After you have determined that an object is a data reference object, use this interface's Resolve method to get the real object that is defined earlier in the file. For information about how to determine that you have a data reference object, see the IDirectXFileData interface.

In addition, IDirectXFileDataReference inherits the IDirectXFileObject::GetId and IDirectXFileObject::GetName methods.

IDirectXFileDataReference::Resolve

IDirectXFileDataReference

Resolves data references.

Syntax

HRESULT Resolve(LPDIRECTXFILEDATA * ppDataObj);

Parameters

ppDataObj
Address of a pointer to receive the IDirectXFileData object.

Return Value

Returns one of the following values:
DXFILE_OK
DXFILEERR_BADVALUE
DXFILEERR_NOTFOUND

IDirectXFileEnumObject

This interface enables you to loop through to retrieve all data objects in the file and to retrieve a data object by GUID or by name.

The IDirectXFileEnumObject interface provides the following methods.

  • GetDataObjectById
  • GetDataObjectByName
  • GetNextDataObject

IDirectXFileEnumObject::GetDataObjectById

IDirectXFileEnumObject

Retrieves the data object that has the specified GUID.

Syntax

HRESULT GetDataObjectById(
  REFGUID rguid,
  LPDIRECTXFILEDATA * ppDataObj);

Parameters

rguid
Reference to the desired GUID.
ppDataObj
Pointer to receive the retrieved IDirectXFileData object.

Return Value

Returns one of the following values:
DXFILE_OK
DXFILEERR_BADVALUE
DXFILEERR_NOTFOUND

IDirectXFileEnumObject::GetDataObjectByName

IDirectXFileEnumObject

Retrieves the data object that has the specified name.

Syntax

HRESULT GetDataObjectByName(
  LPCSTR szName,
  LPDIRECTXFILEDATA * ppDataObj);

Parameters

szName
Pointer to the desired name.
ppDataObj
Pointer to receive the retrieved IDirectXFileData object.

Return Value

Returns one of the following values:
DXFILE_OK
DXFILEERR_BADVALUE
DXFILEERR_NOTFOUND

IDirectXFileEnumObject::GetNextDataObject

IDirectXFileEnumObject

Retrieves the next top-level object in the DirectX file. Top-level objects are always data objects. Data reference objects and binary objects can only be children of data objects.

Syntax

HRESULT GetNextDataObject(
  LPDIRECTXFILEDATA * ppDataObj);

Parameters

ppDataObj
Pointer to receive the retrieved IDirectXFileData object.

Return Value

Returns one of the following values:
DXFILE_OK
DXFILEERR_BADVALUE
DXFILEERR_NOMOREOBJECTS

IDirectXFileObject

IDirectXFileObject is the base interface for DirectX file objects. IDirectXFileData, IDirectXFileDataReference and IDirectXFileBinary interfaces all inherit from this interface.

The IDirectXFileObject interface provides the following methods.

  • GetId
  • GetName

IDirectXFileObject::GetId

IDirectXFileObject

Retrieves a pointer to the GUID that identifies a DirectX file object.

Syntax

HRESULT GetId (LPGUID pGuid)

Parameters

pGuid
Pointer to a GUID to receive the object's ID. The function will set the GUID to a NULL GUID if the object does not have an ID.

Return Value

Returns one of the following values.
DXFILE_OK
DXFILEERR_BADVALUE

IDirectXFileObject::GetName

IDirectXFileObject

Retrieves a pointer to a DirectX file object's name.

Syntax

HRESULT GetName (LPSTR pstrNameBuf, LPDWORD pdwBufLen)

Parameters

pstrNameBuf
Pointer to the buffer in which the DirectX file object's name will be copied. Set to NULL if only the buffer length is needed.
pdwBufLen
Pointer to a DWORD specifying the length of the buffer pointed to by pstrNameBuf. pdwBufLen will be modified to the buffer length needed to hold the object's name even if pstrNameBuf is NULL. In either case, the function will return DXFILEERR_BADVALUE if the original value of pdwBufLen is not as large as or larger than the length needed to hold the object's name.

Return Value

Returns one of the following values.
DXFILE_OK
DXFILEERR_BADALLOC

IDirectXFileSaveObject

This interface enables you to create data objects and to save templates and data objects. Use IDirectXFile::CreateSaveObject to create an instance of this object. Then use SaveTemplates to save the templates. Use CreateDataObject to create a data object, and use SaveData to save the data.

Note that templates are not required in every file. For example, you could put all templates in one DirectX file rather than duplicating them in every DirectX file.

The IDirectXFileSaveObject interface provides the following methods.

  • CreateDataObject
  • SaveData
  • SaveTemplates

IDirectXFileSaveObject::CreateDataObject

IDirectXFileSaveObject

Creates a data object.

Syntax

HRESULT CreateDataObject(
  REFGUID rguidTemplate,
  LPCSTR szName,
  const GUID * pguid,
  DWORD cbSize,
  LPVOID pvData,
  LPDIRECTXFILEDATA * ppDataObj);

Parameters

rguidTemplate
GUID representing the data object's template.
szName
Pointer to the name of the data object. Optional, specify NULL if the object does not have a name. If the object is going to be referenced by a data reference object, at least one of the szName or pguid parameters must be non-NULL.
pguid
Pointer to a GUID representing the data object. Optional, specify NULL if the object does not have a GUID. If the object is going to be referenced by a data reference object, at least one of the szName or pguid parameters must be non-NULL.
cbSize
Size of the data object, in bytes.
pvData
Pointer to a buffer containing all required member's data.
ppDataObj
Address of a pointer to receive the created IDirectXFileData object.

Return Value

Returns one of the following values:
DXFILE_OK
DXFILEERR_BADALLOC
DXFILEERR_BADVALUE

Remarks

Save any templates by using the SaveTemplates method before saving the data created by this method. Save the created data by using the SaveData method. If you need to save optional data, use the IDirectXFileData::AddDataObject method after using this method and before using SaveData. If the object has child objects, add them before calling SaveData.

IDirectXFileSaveObject::SaveData

IDirectXFileSaveObject

Saves a data object and its children to a DirectX file.

Syntax

HRESULT SaveData(
  LPDIRECTXFILEDATA pDataObj);

Parameters

pDataObj
Pointer to the IDirectXFileData object to save.

Return Value

Returns one of the following values:
DXFILE_OK
DXFILEERR_BADARRAYSIZE
DXFILEERR_BADVALUE

IDirectXFileSaveObject::SaveTemplates

IDirectXFileSaveObject

Saves templates to a DirectX file.

Syntax

HRESULT SaveTemplates(
  DWORD cTemplates,
  const GUID ** ppguidTemplates);

Parameters

cTemplates
Total number of templates to save.
ppguidTemplates
Address of a pointer to an array of the GUIDs for all templates to save.

Return Value

Returns one of the following values:
DXFILE_OK
DXFILEERR_BADVALUE

Remarks

The following code fragment provides an example call to SaveTemplates and example contents for the array to which ppuuid points.

IDirectXFileSaveObject * pDXFileSaveObject;

const GUID *aIds[] = {
    &DXFILEOBJ_SimpleData,
    &DXFILEOBJ_ArrayData,
    &DXFILEOBJ_RestrictedData};

hr = pDXFileSaveObject->SaveTemplates(3, aIds);

After using this method to save the templates, use the IDirectXFileSaveObject::CreateDataObject method to create a data object.

Data Types

The DirectX file interfaces use the following constants and structures.

  • DXFILEFORMAT Constants
  • DXFILELOADMEMORY Structure
  • DXFILELOADOPTIONS Constants
  • DXFILELOADRESOURCE Structure

DXFILEFORMAT Constants

Specifies values used by the IDirectXFile::CreateSaveObject method to indicate the format to use when saving the DirectX file.

Syntax

typedef DWORD DXFILEFORMAT;
#define DXFILEFORMAT_BINARY     0
#define DXFILEFORMAT_TEXT       1
#define DXFILEFORMAT_COMPRESSED 2

Values

DXFILEFORMAT_BINARY
Indicates a binary file.
DXFILEFORMAT_TEXT
Indicates a text file.
DXFILEFORMAT_COMPRESSED
Indicates a compressed file.
The default value for the file format is DXFILEFORMAT_BINARY. The file format values can be combined together in a logical OR to create compressed text or compressed binary files. If a file is specified as both binary (0) and text (1), it will be saved as a text file because the value will be indistinguishable from the text file format value (0 + 1 = 1). If you indicate that the file format should be text and compressed, the file will first be written out as text and then compressed. However, compressed text files are not as efficient as binary text files, so in most cases you will want to indicate binary and compressed. Setting a file to be compressed without specifying a format will result in a binary, compressed file.

DXFILELOADMEMORY Structure

Identifies a resource to be loaded when an application uses the IDirectXFile::CreateEnumObject method and specifies DXFILELOAD_FROMMEMORY.

Syntax

typedef struct _DXFILELOADMEMORY {
    LPVOID lpMemory;
    DWORD dSize;
}DXFILELOADMEMORY, *LPDXFILELOADMEMORY;

Members

lpMemory
Pointer to a block of memory to be loaded.
dSize
Size, in bytes, of the block of memory to be loaded.

DXFILELOADOPTIONS Constants

Specifies values used by the IDirectXFile::CreateEnumObject method to indicate the source of the file data.

Syntax

typedef DWORD DXFILELOADOPTIONS;
#define DXFILELOAD_FROMFILE  0x00L
#define DXFILELOAD_FROMRESOURCE 0x01L
#define DXFILELOAD_FROMMEMORY 0x02L
#define DXFILELOAD_FROMSTREAM 0x04L
#define DXFILELOAD_FROMURL 0x08L

Values

DXFILELOAD_FROMFILE
Indicates data read from a file.
DXFILELOAD_FROMRESOURCE
Indicates data read from a resource.
DXFILELOAD_FROMMEMORY
Indicates data read from memory.
DXFILELOAD_FROMSTREAM
Indicates data read from a stream. Not currently supported.
DXFILELOAD_FROMURL
Indicates data read from a URL (Uniform Resource Locator).

DXFILELOADRESOURCE Structure

Identifies a resource to be loaded when an application uses the IDirectXFile::CreateEnumObject method and specifies DXFILELOAD_FROMRESOURCE.

Syntax

typedef struct _DXFILELOADRESOURCE {
    HMODULE hModule;
    LPCTSTR lpName;
    LPCTSTR lpType;
}DXFILELOADRESOURCE, *LPDXFILELOADRESOURCE;

Members

hModule
Handle of the module containing the resource to be loaded. If this member is NULL, the resource must be attached to the executable file that will use it.
lpName
Name of the resource to be loaded. For example, if the resource is a mesh, this member should specify the name of the mesh file.
lpType
User-defined type identifying the resource.

Return Values

The methods of the DirectX file Component Object Model (COM) interfaces can return the following values in addition to standard COM return values.

DXFILE_OK
Command completed successfully. Equivalent to DD_OK.
DXFILEERR_BADALLOC
Memory allocation failed.
DXFILEERR_BADARRAYSIZE
Array size is invalid.
DXFILEERR_BADCACHEFILE
The cache file containing the X file date is invalid. A cache file contains data retrieved from the network, cached on the hard disk, and retrieved in subsequent requests.
DXFILEERR_BADDATAREFERENCE
Data reference is invalid.
DXFILEERR_BADFILE
File is invalid.
DXFILEERR_BADFILEFLOATSIZE
Floating-point size is invalid.
DXFILEERR_BADFILETYPE
File is not a DirectX file.
DXFILEERR_BADFILEVERSION
File version is not valid.
DXFILEERR_BADRESOURCE
Resource is invalid.
DXFILEERR_BADTYPE
Object type is invalid.
DXFILEERR_BADVALUE
Parameter is invalid.
DXFILEERR_FILENOTFOUND
File could not be found.
DXFILEERR_NOMOREDATA
No further data is available.
DXFILEERR_NOMOREOBJECTS
All objects have been enumerated.
DXFILEERR_NOTFOUND
Object could not be found.
DXFILEERR_PARSEERROR
File could not be parsed.
DXFILEERR_RESOURCENOTFOUND
Resource could not be found.
DXFILEERR_URLNOTFOUND
URL could not be found.


Microsoft DirectPlay

Welcome to the Microsoft® DirectPlay® Software Development Kit. DirectPlay is an API that simplifies application access to communication services. It provides a way for applications to communicate with each other independent of the underlying protocol, transport, or online service. This is especially useful for games. Real players, each on her or his own personal computer, can be gathered and launched into a game, without the game developer worrying about the connections.

For the most recent updates, consult the Microsoft DirectX® Web site at http://www.microsoft.com/DirectX/dxm/.

Last Updated: September 28, 1998

About DirectPlay
Provides a brief description of the DirectPlay API.
What's New in DirectPlay 6.0?
Describes the new features in DirectPlay 6.0. These include security, improved connection, initialization, messaging, and asynchronous enumeration of sessions.
Writing a Network Application
Describes general requirements for successful network applications.
DirectPlay Overview
Describes the DirectPlay architecture, session management, player management, message management, and group management with DirectPlay. Also contains an overview of DirectPlay communications.
DirectPlay Lobby Overview
Describes the DirectPlay lobby architecture, lobby sessions, how players navigate in a lobby, and synchronized game launching. A lobby server's main use is to act as a central location where users can go to find and join sessions.
DirectPlay Providers
Describes how DirectPlay interacts with service providers and lobby providers.
Using DirectPlay
Describes how to use different aspects of DirectPlay, including working with globally unique identifiers (GUIDs), the DirectPlay interfaces, how to use callback functions, how to build lobby-aware applications, how to use messages, how to use security and authentication, how to use DirectPlay Addresses as connection shortcuts, and how to migrate from previous versions of DirectPlay. Also discusses the DirectPlay protocol, throttling, and asynchronous messaging.
DirectPlay Tools and Samples
Describes the tools and samples that ship with DirectPlay and how to use them.
DirectPlay Interface Overviews
Provides an overview of the IDirectPlay4 Interface and IDirectPlayLobby3 Interface interfaces, as well as previous versions of these interfaces. Also describes the difference between the Unicode and ANSI interfaces.
DirectPlay Tutorials
Contains four tutorials that provide step-by-step instructions about connecting applications with or without a lobby, overriding service provider dialog boxes, and creating a self-refreshing session list.
DirectPlay Reference
Provides detailed information about functions, callbacks, and the IDirectPlay4 Interface and IDirectPlayLobby3 Interface interface methods. Also describes the DirectPlay structures, system messages, lobby messages, defined properties, and error values.
DirectPlay Glossary
Defines basic DirectPlay terms.

Note The icon external link indicates that the link takes you to a URL that is outside the microsoft.com site; you can return to the DirectPlay site by using the Back button. Note that most of these external links point to servers that are not under Microsoft's control. Please read Microsoft's official statement regarding other servers.


About DirectPlay

The Microsoft® DirectPlay® application programming interface (API) for Microsoft Windows® 95 is a software interface that simplifies application access to communication services. DirectPlay has become a technology family that not only provides a way for applications to communicate with each other, independent of the underlying transport, protocol, or online service, but also provides this independence for matchmaking servers and game servers.

Applications (especially games) can be more compelling if they can be played against real players, and the personal computer has richer connectivity options than any game platform in history. Instead of forcing the developer to deal with the differences that each connectivity solution represents, DirectPlay provides well-defined, generalized communication capabilities. DirectPlay shields developers from the underlying complexities of diverse connectivity implementations, freeing them to concentrate on producing a great application.


What's New in DirectPlay 6.0?

This section discusses new features in Microsoft® DirectPlay® 6.0. For the most recent updates, including new features, additional samples, and further technical information, consult the Microsoft DirectX® Web site at http://www.microsoft.com/DirectX/.

DirectPlay 6.0 has a few new interfaces, IDirectPlay4, IDirectPlay4A, IDirectPlayLobby3, and IDirectPlayLobby3A. IDirectPlay4 inherits directly from IDirectPlay3, and IDirectPlayLobby3 inherits directly from IDirectPlayLobby2. The IDirectPlay4A and IDirectPlayLobby3A are the ANSI versions of the interfaces, while IDirectPlay4 and IDirectPlayLobby3 are the Unicode versions of the interfaces. and by default behaves as IDirectPlay3. All new functionality is enabled through new methods or flags.

DirectPlay 6.0 supports the following new features and methods:

  • Guaranteed Messaging: DirectPlay 5.0 only supported guaranteed messaging when the service provider implemented it. In a practical sense, this meant that guaranteed messaging was available only on TCP/IP. In DirectPlay 6.0, the DirectPlay Protocol enables guaranteed messaging on all service providers regardless of whether the provider inherently support guaranteed messaging. This makes true guaranteed messaging available on IPX, modem, and serial service providers. The DirectPlay Protocol is built upon the nonguaranteed messaging of the service provider.

    The DirectPlay Protocol can also be used as a substitute for the guaranteed protocol implemented by the service provider. This improves the efficiency of service providers, such as TCP/IP, because the DirectPlay Protocol is designed for real-time gaming while TCP is not. For example:

    • Guaranteed messages are not serialized; they do not wait for each to be acknowledged before sending the next one. Several messages can be outstanding while waiting for acknowledgement. This improves the overall throughput of messages.
    • Message prioritization is provided. Higher priority messages are sent before lower priority messages. Lower priority messages only use idle bandwidth. A large, lower priority message that spans many packets will not block a higher priority message.
    • Fully dynamic reporting of latency is supported.

    See IDirectPlay4::SendEx, IDirectPlay4::Send, and DirectPlay Protocol for more information.

  • Asynchronous Messaging: New methods have been added to DirectPlay 6.0 to support asynchronous messaging. DirectPlay 5.0 supported only synchronous messaging. This meant that an application was blocked in the IDirectPlay4::Send method until the send was complete. For a guaranteed send on TCP/IP, this could take some time on a slow connection, and would take even more time for guaranteed sends to a group of players.

    In DirectPlay 6.0, the SendEx function call returns immediately, and the application is notified of the success or failure by means of a message posted to the receive queue. The application also has the ability to cancel messages. In addition, the service provider interface has been updated to allow service providers to implement optimized asynchronous messaging, as well.

    See Asynchronous Messaging, SendEx, CancelMessage, and GetMessageQueue for more information.

  • Message Throttling: DirectPlay 5.0 sent messages as fast as the outbound bandwidth of the computer allowed. DirectPlay 6.0 throttles the rate at which messages are sent to make sure that it does not overload the target computer or exceed the outbound bandwidth of the sending computer, thus introducing latency. A send queue keeps a list of pending messages. The application can use the status of the send queue to regulate how much data it sends.

    For example, a computer attached to the Internet through an ISDN line can send data much faster than a computer connected by means of a 28.8 modem can receive data. As a result, messages are queued on the receiving computer's Internet service provider (ISP) with no indication to the sending computer that this is a problem. With throttling, the ISDN computer only puts data onto the network as fast as the 28.8-modem computer can receive it. This gives the sending application the chance to see that messages in the send queue are backing up and to cancel some of them or decrease the rate of sending data.

    See SendEx, CancelMessage, and GetMessageQueue for more information.

  • Firewall Support for TCP/IP: DirectPlay 6.0 uses a range of port numbers to make it easier to configure firewalls. This works with all clients behind firewalls.

    The firewall support is completely transparent to the developer and to the end user. The firewall administrator needs to configure the firewall to allow DirectPlay packets to pass through.

    See Firewall Support in DirectPlay 6 for more information.

  • Lobby Improvements: DirectPlay 6.0 notifies the lobby when the host of a session has migrated. This makes it easier for lobby systems to track the host of a game and thus allow players to join games in progress.

    The DirectPlay lobby messages are seamlessly integrated with the lobby provider interface so that external lobby clients do not have to re-route messages to the server. Connect and ConnectEx have a maximum limit on the timeout (1 minute). You no longer have to wait 2.5 minutes on the Internet to realize your game did not connect. Connect and ConnectEx are asynchronous, so you can cancel at anytime.

    See DPLMSG_NEWSESSIONHOST, Connect and ConnectEx for more information.

  • Security: DirectPlay 6.0 provides security for peer-to-peer sessions (as long as the host is on a secure server). Previously only client-server sessions could be secure. DirectPlay 6.0 also supports sending secure messages to a group.

    See DPSESSIONDESC2 for more information.

  • Application Registration: Methods to register and unregister lobby-aware applications are now part of the DirectPlay dynamic-link libraries (DLLs), rather than part of the DirectX foundation setup routines.

    See IDirectPlayLobby3::RegisterApplication and IDirectPlayLobby3::UnregisterApplication for more information.

  • Improved Localization Support: Registry entries for DirectPlay service providers, lobby providers, and lobby-aware applications are now better able to support localization through the use of separate ANSI descriptions and Unicode descriptions. This allows applications that only support single-byte characters to display properly localized ANSI descriptions, while applications that support Unicode or multi-byte character sets can obtain a better description.

    The biggest improvement can be seen in English language applications being run on Far East versions of Windows—rather than receiving a multi-byte description displayed as garbage, users now receive a single-byte description that is correct.

    See Service Providers, IDirectPlayLobby3::RegisterApplication, IDirectPlay4::EnumConnections, IDirectPlayLobby3::EnumLocalApplications, and DirectPlayEnumerate for more information.

  • Improved Keep-alive Support: Applications can implement their own keep-alives so that the server player can remove dead clients. The host or server can destroy remote players.

    See Service Providers and IDirectPlay4::DestroyPlayer for more information.

  • Private Service Providers: Some service providers do not want to be presented to the user by the application. These are cases where the service provider only works when launched by a lobby client. DirectPlay 6.0 supplies a flag for these service providers to be private. These service providers can only be referenced when launched by a lobby, or if the application knows the globally unique identifier (GUID). Private service providers will not be listed by IDirectPlay4::EnumConnections.

    See Service Providers and IDirectPlay4::EnumConnections for more information.

  • Lobby Can Connect to an Application That Is Already Running - A new method on the IDirectPlayLobby3 interface enables an application to go into a wait mode. When in wait mode, a lobby client that uses RunApplication will not launch a new instance of the application, but will send the connection settings directly to the application already running in wait mode.

    See WaitForConnectionSettings for more information.

DirectPlay 6.0 supports the following new methods, structures, system messages, and lobby messages:

  • IDirectPlay4::SendEx
  • IDirectPlay4::CancelMessage
  • IDirectPlay4::CancelPriority
  • IDirectPlay4::GetMessageQueue
  • IDirectPlay4::GetGroupOwner
  • IDirectPlay4::SetGroupOwner
  • IDirectPlayLobby3::ConnectEx
  • IDirectPlayLobby3::RegisterApplication
  • IDirectPlayLobby3::UnregisterApplication
  • IDirectPlayLobby3::WaitForConnectionSettings
  • DPAPPLICATIONDESC
  • DPMSG_SENDCOMPLETE
  • DPMSG_SETGROUPOWNER
  • DPLMSG_NEWSESSIONHOST

DirectPlay 6.0 also supports new functionality for existing DirectPlay 5.0 methods, structures, system messages, and callback functions:

  • IDirectPlay4::CreateGroup
  • IDirectPlay4::CreateGroupInGroup
  • IDirectPlay4::DestroyPlayer
  • IDirectPlay4::EnumConnections
  • IDirectPlay4::EnumGroupPlayers
  • IDirectPlay4::EnumGroups
  • IDirectPlay4::EnumGroupsInGroup
  • IDirectPlay4::GetPlayerAddress
  • IDirectPlay4::Send
  • IDirectPlayLobby3::Connect
  • IDirectPlayLobby3::EnumLocalApplications
  • DPSESSIONDESC2
  • DPMSG_CREATEPLAYERORGROUP
  • DPMSG_DESTROYPLAYERORGROUP
  • EnumPlayersCallback2


Writing a Network Application

The fundamental concern when writing a networked, multiplayer application is how to propagate state information to all the computers in the session. The state of the session defines what users see on their computers and what actions they can perform. Generally, two things make up the session state: the environment and the individual users or players.

The environment consists of the objects that the players can manipulate or interact with. This can include a map of a dungeon, a racecourse, or even a document. The environment can also include computer-controlled players.

Within the environment, each player also has a state indicating the player's current properties. These can include position, velocity, energy, armor, and so on.

When a player first joins the session, the session's current state must be downloaded, including the environment and the state of the other players.

Actions performed by users or the natural progression of a game change the state of the session. When this happens, the change must be propagated to the other computers in the session through messages. There are many techniques for updating the session state, but they all depend on sending messages between computers.

When two players perform an action on the same object (like opening a door) or on each other (like swinging a sword) a conflict can arise. That is, two players are trying to do something where only one of them can succeed. In these cases, arbitration or conflict resolution is needed. There are several ways to resolve conflicts like this: The two players can communicate with each other and decide which one wins, or a special player can arbitrate all conflicts.

The actions of players change the state of a game, and conflicting actions must be resolved before the game's state can be updated. There are two fundamental ways of maintaining state in a session. The first way is called peer-to-peer. In peer-to-peer sessions, all the computers in the session have the complete state of the environment and all the players. Any change in state that happens on one computer must be propagated to all the other computers in the session. No one computer is really in charge.

The second way to maintain the session state is called client/server. In client/server sessions, one computer is designated the server, and it maintains the complete state of the game and performs conflict resolution. All the other computers in the session are clients, and they download some portion of the state from the server. When they need to change the state, they tell the server, and the server propagates the change to other clients as needed.

With DirectPlay, you can create and manage both peer-to-peer and client/server applications. DirectPlay provides all the tools needed to write a networked, multiplayer application by providing the services to manage players, send messages between players, and automatically propagate the state among all the computers.


DirectPlay Overview

This section contains general information about the DirectPlay® component. The following topics are discussed:

  • Architecture
  • Session Management
  • Player Management
  • Message Management
  • Group Management
  • Overview of DirectPlay Communications

Architecture

The DirectPlay API is a network abstraction and distributed object system that applications can be written to. The API defines the functionality of the abstract DirectPlay network, and all the functionality is available to your application regardless of whether the actual underlying network supports it. In cases where the underlying network does not support a method, DirectPlay contains all the code necessary to emulate it. Examples include group messaging and guaranteed messaging.

DirectPlay's service-provider architecture insulates the application from the underlying network it is running on. The application can query DirectPlay for specific capabilities of the underlying network, such as latency and bandwidth, and adjust its communications accordingly.

The following diagram illustrates the DirectPlay service-provider architecture.

DirectPlay service provider architecture

The first step in using DirectPlay is to select which service provider to use. The service provider determines what type of network or protocol will be used for communications. The protocol can range from TCP/IP over the Internet, to an IPX local area network, to a serial cable connection between two computers.

Use the service provider to make a connection to a point on the network. The user may need to provide additional information to make a connection, or the application can specify the connection parameters.

Connection Management Methods

DirectPlay provides two useful connection management methods:

  • IDirectPlay4::EnumConnections enumerates all the connections that are available to the application.
  • IDirectPlay4::InitializeConnection initializes a specific connection.

Session Management

A DirectPlay session is a communications channel between several computers. Before an application can start communicating with other computers, it must be part of a session. An application can do this in one of two ways: It can enumerate all the existing sessions on a network and join one of them, or it can create a new session and wait for other computers to join it. Once the application is part of a session, it can create a player and exchange messages with all the other players in the session.

Each session has one computer that is designated as the host. The host is the owner of the session and is the only computer that can change the session's properties.

The following diagram illustrates the DirectPlay session model:

DirectPlay session model

Session Management Methods

DirectPlay provides several session management methods:

  • IDirectPlay4::EnumSessions enumerates all the available sessions.
  • IDirectPlay4::Open joins one of the enumerated sessions or creates a new session.
  • IDirectPlay4::SecureOpen performs the same function as IDirectPlay4::Open, but enables the application to alter the default opening behavior.
  • IDirectPlay4::Close leaves the currently open session.
  • IDirectPlay4::GetSessionDesc gets the properties of the current session.
  • IDirectPlay4::SetSessionDesc changes the properties of the current session.
  • IDirectPlay4::GetCaps gets the communications capabilities of the underlying network.

Player Management

The most basic entity within a DirectPlay session is a player. A player represents a logical object within the session that can send and receive messages. DirectPlay does not have any representation of a physical computer in the session. Each player is identified as being either a local player (one that exists on your computer) or a remote player (one that exists on another computer). Each computer must have at least one local player before it can start sending and receiving messages. Individual computers can have more than one local player.

When an application sends a message, it is always directed to another player - not another computer. The destination player can be another local player (in which case the message will not go out over the network) or a remote player. Similarly, when an application receives messages, they are always addressed to a specific (local) player and marked as being from some other player (except system messages, which are always marked as being from DPID_SYSMSG).

DirectPlay provides some additional player management methods that an application can use. These methods can save the application from having to implement a list of players and data associated with each one. You do not need these methods to use DirectPlay successfully. They enable an application to associate a name with a player and automatically propagate that name to all the computers in the session. Similarly, the application can associate some arbitrary data with a player that will be propagated to all the other computers in the session. The application can also associate private local data with a player that is available only to the local computer.

Basic Player Management Methods

DirectPlay provides several basic player management methods:

  • IDirectPlay4::EnumPlayers enumerates all the players in the sessions.
  • IDirectPlay4::CreatePlayer creates a local player.
  • IDirectPlay4::DestroyPlayer destroys a local player.

Additional Player Management Methods

DirectPlay provides these additional methods to manage player information:

  • IDirectPlay4::GetPlayerCaps gets a player's communications capabilities.
  • IDirectPlay4::GetPlayerName gets a player's name.
  • IDirectPlay4::SetPlayerName changes a player's name.
  • IDirectPlay4::GetPlayerData gets the application-specific data associated with a player.
  • IDirectPlay4::SetPlayerData changes the application-specific data associated with a player.
  • IDirectPlay4::GetPlayerAddress gets a player's network-specific address.
  • IDirectPlay4::GetPlayerAccount gets a player's account information.
  • IDirectPlay4::GetPlayerFlags gets a player's flag settings.

Message Management

Once an application has created a player within a session, it can start exchanging messages with other players in the session. DirectPlay imposes no message format or extra bytes on the message. A message can be sent to an individual player, to all the players in the sessions, or to a subset of players that have been defined as a group (see Group Management). When sending a message, it must also be marked as being from a specific local player.

All the messages received by an application are put into a receive queue. The application must retrieve individual messages from the queue and act on them as appropriate. The application can either poll the receive queue for messages or use a separate thread that waits on a synchronization event for notification that a new message has arrived.

There are two types of messages. Player messages are messages that another player in the session sent. This type of message is directed to a specific player and is marked as being from the sending player. System messages are sent to all the players in a session, and are all marked as being from the system (DPID_SYSMSG). DirectPlay generates system messages to notify the application of some change in state of the session; for example, when a new player has been created. See Using system messages for more information.

Basic Message Management Methods

DirectPlay provides several message management methods:

  • IDirectPlay4::SendEx sends a message from a local player to another player in the session. This is an enhanced version of Send that supports guaranteed and nonguaranteed messages, asychronous messages, and setting the timeout and priority of a message.
  • IDirectPlay4::Send sends a message from a local player to another player in the session.
  • IDirectPlay4::SendChatMessage enables players to chat with other players using standardized messages.
  • IDirectPlay4::Receive retrieves a message from the incoming message queue.
  • IDirectPlay4::CancelMessage cancels a specific message (or all messages) that is still in the send queue.
  • IDirectPlay4::CancelPriority cancels all messages of a particular priority or range of priorities that are still in the send queue.
  • IDirectPlay4::GetMessageCount gets the number of messages currently in the incoming message queue.
  • IDirectPlay4::GetMessageQueue determines how many messages are in the send or receive queue.

Group Management

DirectPlay supports groups within a session. A group is a logical collection of players. By creating a group of players, an application can send a single message to the group, and all the players in the group will receive the message. A group is the means by which a network's multicast capabilities are exposed to the application.

Groups can also be used as a general means to organize players in a session. A player can belong to more than one group. DirectPlay provides methods for administering groups and their membership. Additional methods associate names and data with individual groups as a convenience, but you don't need them to use groups.

The following diagram shows a logical representation of the contents of a DirectPlay session:

A logical representation of the contents of a DirectPlay session

Basic Group Management Methods

DirectPlay provides several group management methods:

  • IDirectPlay4::EnumGroups enumerates all the groups in the session.
  • IDirectPlay4::CreateGroup creates a new group.
  • IDirectPlay4::DestroyGroup destroys a group.
  • IDirectPlay4::EnumGroupPlayers enumerates the players that are in a group.
  • IDirectPlay4::AddPlayerToGroup adds a player to a group.
  • IDirectPlay4::DeletePlayerFromGroup removes a player from a group.

Additional Group Management Methods

DirectPlay provides these additional methods to manage groups and group information:

  • IDirectPlay4::GetGroupName gets the group's name.
  • IDirectPlay4::SetGroupName changes the name of a group created by this computer.
  • IDirectPlay4::GetGroupData gets the application-specific data associated with a group.
  • IDirectPlay4::SetGroupData changes the application-specific data associated with a group created by this computer.
  • IDirectPlay4::GetGroupFlags gets the flags describing a group.
  • IDirectPlay4::GetGroupParent gets the DPID of the parent of the group.
  • IDirectPlay4::CreateGroupInGroup creates a group within an existing group.
  • IDirectPlay4::EnumGroupsInGroup enumerates all the groups within another group.
  • IDirectPlay4::AddGroupToGroup adds a shortcut from a group to an already existing group.
  • IDirectPlay4::DeleteGroupFromGroup removes a group previously added to another group with AddGroupToGroup, but doesn't destroy the deleted group.
  • IDirectPlay4::GetGroupConnectionSettings retrieves a group's connection settings.
  • IDirectPlay4::SetGroupConnectionSettings sets a group's connection settings.
  • IDirectPlay4::SetGroupOwner changes the owner of a group.
  • IDirectPlay4::GetGroupOwner gets the owner of a group.

Overview of DirectPlay Communications

DirectPlay's default mode of communications is peer-to-peer. In this model, the session's complete state is replicated on all the computers in the session. This means that the session description data, the list of players and groups, and the names and remote data associated with each session are duplicated on every computer. When one computer changes something, it is immediately propagated to all the other computers.

DirectPlay's alternative mode of communications is client/server. In this model, only the server stores the session's complete state, and each client has only a subset of the session's state. Each client has only the information that is relevant to that computer and receives that information from the server. When one computer changes something, it propagates the change to the server. The server then determines which clients it must inform of the change.

An application can manage its own data using either a client/server model or peer-to-peer model, but this will not change how the underlying DirectPlay session state is managed.

The following sections discuss the two modes of communications within DirectPlay sessions:

  • Peer-to-Peer Session
  • Client/Server Session

Peer-to-Peer Session

In a peer-to-peer DirectPlay session, one computer is designated the name server. This computer responds to enumeration requests, regulates computers trying to join the session, downloads the session's state to new computers that have joined, and generates ID numbers as players and groups are created. Beyond that, the name server is just another peer in the session and runs the same application as all the other peers. Messages are not routed through the name server, and the name server does not generate all the system messages.

DirectPlay automatically performs the name server functions, which are not exposed to the application in any way. The DirectPlay application running on the name server is also the session's host. Only the host application can change the session description data. Each peer application in the session has access to the complete list of players and groups in the session (see Session Management) and can send and receive messages from any other player in the session or send a message to any group in the session. See Session Management for more details.

The session's network address corresponds to the name server's network address. When a computer needs to join the session, it sends the join request to the name server. In response, the name server downloads the session's state to the new computer. If the name server leaves the session, a new computer is elected name server. When the name server migrates, the session's network address also changes.

The following diagram illustrates joining a session. To join a session, a machine sends the join request to the name server of the session.

Joining a session

Peer-to-peer sessions generally have a limitation on the number of computers that can participate. Every change in state on every computer (such as player movements) must be broadcast to all the other computers in the session. Because of the limit on the amount of data a computer can receive (especially if connected through a phone line), there is a limit on how many computers can generate data. Minimizing the quantity and frequency of data exchanged can help increase the number of computers that can be in a session before performance degrades.

Computers in a peer-to-peer DirectPlay session communicate directly with each other. That is, messages are not sent through an intermediate computer to reach their destination (although they can go through a router). When DirectPlay needs to send the same message to a set of computers, it attempts to use any multicast capabilities in the service provider. If multicast is not supported, then individual unicast messages are sent to each destination computer.

The following diagram illustrates group messaging without multicast. To broadcast a message, individual messages are sent to each machine.

Group Messaging without Multicast

This can be a source of inefficiency in sessions with a large number of players (more than four). Adding a multicast server to the session can alleviate this. A multicast server is a computer that will forward a single message to multiple destinations. A computer needing to broadcast a message to all the other computers in the session can send one message to the multicast server, which in turn sends individual messages to all the other computers. This is more efficient because the multicast server is connected to the network through a high-speed link and can therefore pump out unicast messages faster than any individual computer. The assumption is that the server has a high-speed link to the network (such as a T1 line), while the other computers have slow-speed links (such as phone lines).

The following diagram illustrates group messaging using a multicast server. Player-to-player messages are sent directly to the destination machine. Group messages are sent to the multicast server, which forwards them to all the destination machines.

Group Messaging Using a Multicast Server

DirectPlay supports the creation of a multicast server in a session. If the name server is on a sufficiently high-speed link, it can choose to be a multicast server for the session as well. Adding a multicast server to a session only changes how group messages (including broadcast) are routed - the application's behavior does not change. Unicast player-to-player messages are still sent directly to the destination computers.

Client/Server Session

In a DirectPlay client/server session, one computer is designated the server. Like the peer-to-peer name server, this computer responds to enumeration requests, regulates computers trying to join the session, downloads the session's state to new computers that have joined, and generates ID numbers as players and groups are created. Unlike the peer-to-peer name server, all messages in the session are routed through the server.

The server computer runs a special version of the application (the application server) that can maintain the master state of the game, updating that state according to actions that the client computers take, and notifying individual clients of relevant events. The application server creates a special player called the server player. Any client computer can send a message directly to the server player or receive a message from the server player. When the server player receives a message, it can send messages to other client players to inform them of a change in state.

The following diagram illustrates client\server communications. Each machine communicates directly with the server only. The server can forward messages to other clients.

The client computers run client versions of the application that can maintain the local state, updating the state in response to messages from the server, and sending messages to the server when local action occurs.

You can implement a client/server application in two ways. One mode is a hybrid peer-to-peer and client/server session, where every client application has the complete player and group list available to it (including the server player). Any client player can send a message directly to any player in the session, and each player or group can have data associated with it (such as name or remote data) that will be updated on all the computers whenever it changes. All the benefits of peer-to-peer state propagation are available, and, in addition, a server player is available. However, you cannot control the propagation of the player-to-player data. Depending on the frequency with which players and groups are created and destroyed or their data changes, client computers could be overloaded with in-coming messages. This type of a session is not scalable beyond about 16 players. It is not very different from a peer-to-peer session, except: it has a server player; all messages are routed through the server; and the server player will receive a copy of all the messages that pass through the server.

The second mode is pure client/server. Each client application sees only the server player and its own local players in the session. A client player can send messages only to the server player and receive messages from only the server player. The application server can see all the players on all clients. When the server receives a message from a client, it can intelligently decide how to update the master application state and inform the clients that need to be notified of this update. In this mode, the client application must manage the player list and the data associated with each player.

The following diagram shows a logical representation of the contents of a DirectPlay client/server session.

A logical representation of the contents of a DirectPlay client/server session

Like a peer-to-peer session, the session's network address corresponds to the server's network address. When a computer needs to join the session, it sends the join request to the server. In response, the server downloads the session's state to the new computers. If the server leaves the session, the session is terminated.

Because all messages are routed through the server, it automatically behaves as a multicast server.

Security

Using DirectPlay security features, an application running on a server can create secure sessions. DirectPlay implements security through the Security Support Provider Interface (SSPI) on Windows. Key features supported by DirectPlay in a secure session are:

  • Authentication to verify the identity of the user. Once a user has been authenticated, communications between the client and server can be done securely either by digitally signing or encrypting the messages.
  • Digitally signed system messages to verify the identity of the sender.
  • Encryption of sensitive system messages.

For more information, including how to set up a secure server, start a secure session, and specify security packages, see Security and Authentication.


DirectPlay Lobby Overview

A DirectPlay lobby server is a common place on a network that (at a minimum) tracks DirectPlay application sessions in progress, and users that are connected to the server. Users can navigate around the lobby server to find areas of interest. At any location on the lobby server, the user can chat with other users, join sessions that are in progress, or gather a group of players to start a new session.

This section discusses the following topics.

  • DirectPlay Lobby Architecture
  • Lobby Sessions
  • Lobby Navigation
  • Synchronized Launching

A lobby server's main advantage is that it acts as a central, well-known location where users can go to find sessions and other people to interact with. The lobby server manages all the network addresses of the various players and sessions and can automatically manage launching applications and connecting them to the correct address without user intervention. The management of sessions, players, and their network addresses is especially useful on the Internet, where users generally can't find opponents or get applications connected in a session easily. It also has the advantage of launching application sessions for the user without the user having to enter any network configuration information.

Lobby servers can be greatly enhanced to provide more services to the user, such as tournaments, individual score tracking and high scores, personal profiles, avatars, message boards, news, a broader user interface, authenticated membership, software updates, and so on.

A lobby-aware application is one that has been specifically developed to operate with lobby servers. There are two types of lobbies that a user can experience. An external lobby is a client application whose sole purpose is to interact with a lobby server and the other users connected to it. When the time comes to start or join an application session, the lobby client launches the application in a separate process and gives it all the information necessary to establish a connection to the session. Adding support for external lobby launching to a DirectPlay application is quite straightforward and explained further in Supporting External Lobby Launching.

An internal lobby is a lobby user interface that is integrated into the application itself. This is more difficult to implement because the application must implement the user interface for the lobby as well as that for the game. However, it has the advantage that you can customize the lobby experience to match the application's theme.

DirectPlay Lobby Architecture

The DirectPlay lobby architecture consists of a client API that all applications, whether they are external lobby clients or applications that have a lobby client built in, use to connect to any DirectPlay-compliant lobby server. This is done through a lobby provider interface that, like a service provider, abstracts the interaction with the lobby server. The author of the lobby server application must write the lobby provider that resides on the client computer. The application calls the standard DirectPlay APIs, and the lobby provider's dynamic-link library (DLL) services these methods by communicating with the lobby server software.

The following diagram illustrates the DirectPlay lobby architecture. Different lobby client applications can connect to the same lobby server through the DirectPlay API.

DirectPlay lobby architecture

At the very least, the lobby server must be able to track all the users currently connected to it, organize those players by grouping them, and synchronize the launch of an application session.

The DirectPlay API defines a common level of functionality for all lobby servers. Any generic lobby client application can connect to any generic lobby server and, through the DirectPlay API and the lobby provider architecture, they can interoperate successfully. An application can extend the basic functionality with the Send and Receive methods. A lobby client designed to work with a specific lobby server can implement extended functionality that is not defined by the DirectPlay API.

There is no separate API to communicate with a DirectPlay lobby server. Interaction with a lobby server has been abstracted so that the same IDirectPlay4 interface used to communicate in an application session can be used to communicate with the lobby server. Additional methods and messages have been added to the interface to support the additional functionality that a lobby server requires.

By using the same DirectPlay methods to interact with the lobby server, it is simple to add a lobby client interface to an application, because the same APIs and concepts are being leveraged.

Lobby Sessions

A lobby session closely resembles a DirectPlay client/server session (see the illustration in Client/Server Session). The term lobby session refers to a connection to a lobby server where clients and the server have not been specifically written to interoperate. The term application session refers to a traditional DirectPlay session in which all the clients and the server (if any) have been specifically written to interoperate.

A DirectPlay lobby session is used to represent a connection to a lobby server. Like a DirectPlay application, the first step in using DirectPlay to communicate with a lobby server is to select which lobby provider to use and which lobby server to connect to. Like a DirectPlay application, the IDirectPlay4::EnumConnections and IDirectPlay4::InitializeConnection methods are used to do this.

The lobby client uses the same session management methods as an application client to locate and to join a lobby session; for example, EnumSessions, Open, SecureOpen, and Close. Joining a lobby session gives the client application access to all the information on the lobby server and enables the user to interact with other users on the lobby server.

Like a DirectPlay application session, the player is the basic entity in a lobby session. Each player represents a user on a client computer connected to the lobby server. There is also the server player representing the lobby server. After a lobby client connects to a lobby server (by joining the lobby session), it must establish the user's presence by creating a player and adding the player to an initial group before the player can start communicating with the server and other players. In fact, other users connected to the session won't even be aware of the new user's presence until this happens.

The same player management methods used by application sessions are used to manage players in a lobby session; for example, EnumPlayers, CreatePlayer, DestroyPlayer, GetPlayerName, SetPlayerName, and GetPlayerCaps.

Unlike a DirectPlay application session, Send and Receive generally cannot be used to exchange messages with other players. In the DirectPlay lobby architecture, any application that uses the DirectPlay API can connect to any lobby server. This means that many different lobby client applications might be present in the same lobby session, all of which were written by different developers. Simply sending a message to another client player or the server player does not guarantee that it will be interpreted correctly by the recipient application.

Common functions that require communications between clients and the server have new methods created for them. DirectPlay determines the message's format. The recipient receives a system message containing the content of the message in a well-defined data structure. For example, the IDirectPlay4::SendChatMessage method sends a text chat message to another player.

Groups take on more significance in a lobby session, because they are used to define the organization of the entire lobby server and for launching application sessions. You can create a complete hierarchy of groups to manage and organize all the players and sessions that the lobby server tracks.

For the purposes of the lobby server, groups are classified as one of two types. A standard group can contain players and other groups and is called a room. A room is primarily used as a meeting place for players to interact with other players in the context of the lobby. The room contains links to other rooms and links to the second type of group—a staging area.

A staging area group typically contains only players. A staging area is used to marshal players together in order to launch a new session. After the session has been launched, the staging area can remain in existence so that new players can join the session in progress.

Room groups are organized primarily in a hierarchical structure. A few top-level groups are created and other groups are created within existing groups. The lobby client can enumerate all the top-level groups as well as the groups contained within a group. The lobby server can also organize the groups in a web structure. Once a group is created, you can add it to another group, which creates a link between the two groups. When a lobby client enumerates groups within a group, all subgroups and linked groups are returned.

The following diagram illustrates the organization of a lobby session.

Organization of a lobby session

Players can be seen only in groups. They cannot be seen until they are part of a group. Players can belong to more than one group at once.

Lobby Navigation

Players can navigate through the lobby server space simply by deleting themselves from their current group and adding themselves to a new group. At any time, the IDirectPlay4::EnumGroupsInGroup method can be called to determine what groups are linked to the current group.

In general, the scope of the lobby session visible to a player is limited by the groups the player is part of. This is done to limit the amount of information that the server must download to the client.

Synchronized Launching

Application sessions are marshaled and launched from a staging area. One player creates a staging area and waits for other players to join it. A player can set the properties of the application session to be created through the IDirectPlay4::SetGroupConnectionSettings method. Other players who are considering joining the group can find out what the application session properties are by calling the IDirectPlay4::GetGroupConnectionSettings method. After enough players have joined the staging area, any player can call the IDirectPlay4::StartSession method to initiate the synchronized launch sequence. Every player in the staging area groups receives a DPMSG_STARTSESSION system message with a DPLCONNECTION structure. If the player is using an external lobby client, it can launch the application by using the IDirectPlayLobby3::RunApplication method. If the player is using an internal lobby, the application can use the information to establish a connection to the appropriate session by calling IDirectPlayLobby3::Connect.


DirectPlay Providers

This section describes the DirectPlay interface and the DirectPlay service providers and how they interact with each other. For more information, see:

  • Service Providers
  • Lobby Providers
  • Firewall Support in DirectPlay 6.0

The DirectPlay interface is a common interface to the application for simple send and receive type messaging, as well as higher-level services like player management, groups for multicast, data management and propagation, and lobby services for locating other players on a network.

The service providers furnish network-specific communications services as requested by DirectPlay. Online services and network operators can supply service providers to use specialized hardware, protocols, communications media, and network resources. A service provider can simply be a layer between DirectPlay and an existing transport like Winsock, or it can use specialized resources on an online service such as multicast servers, enhanced quality of service, or billing services. Microsoft includes four generic service providers with DirectPlay: head-to-head modem (TAPI), serial connection, Internet TCP/IP (using Winsock), and IPX (also using Winsock).

The DirectPlay interface hides the complexities and unique tasks required to establish an arbitrary communications link inside the DirectPlay provider implementation. An application using DirectPlay need only concern itself with the performance and capabilities of the virtual network presented by DirectPlay. It need not know whether a modem, network card, or online service is providing the medium.

DirectPlay will dynamically bind to any DirectPlay provider installed on the user's system. The application interacts with the DirectPlay object. The DirectPlay object interacts with one of the available DirectPlay service providers, and the selected service provider interacts with the transport, protocol, and other network resources.

The DirectPlay API is exposed to the application through several Component Object Model (COM) interfaces. (See DirectPlay Interfaces for a discussion of COM and DirectPlay.) Application sessions can talk to someone else on the network through the IDirectPlay4 and IDirectPlay4A interfaces. The first uses Unicode strings in all the DirectPlay structures, while the second uses ANSI strings. IDirectPlay, IDirectPlay2, IDirectPlay2A, IDirectPlay3, and IDirectPlay3A still exist for backward compatibility with applications written to a previous version of the DirectPlay Software Development Kit (SDK).

Lobby clients can talk to another application on the same computer through the IDirectPlayLobby3 and IDirectPlayLobby3A interfaces. The first interface uses Unicode strings while the second uses ANSI strings. The IDirectPlayLobby, IDirectPlayLobby2, and IDirectPlayLobby2A interfaces still exists for backward compatibility.

Service Providers

The service provider furnishes network-specific communication services as requested by DirectPlay. Online services and network operators can supply service providers for specialized hardware and communications media. Microsoft includes the following service providers with DirectPlay:

  • TCP/IP
  • IPX
  • Modem-to-Modem
  • Serial Link

Individual service providers are identified using a globally unique identifier (GUID). GUIDs for the standard service providers are listed in the header file Dplay.h. Third-party service providers will have their own GUIDs.

This section outlines what to expect from the default service providers that Microsoft provides. To obtain information about the behavior of third-party service providers, contact the network operator.

You can ask the service provider to optimize for bandwidth or for latency. The DPSESSION_OPTIMIZELATENCY flag asks the service provider to optimize for latency (which turns off nagling in TCP/IP). The default is to optimize for bandwidth.

TCP/IP

The Transmission Control Protocol/Internet Protocol (TCP/IP) service provider uses Winsock to communicate over the Internet or local area network (LAN) using the TCP/IP protocol. It uses User Datagram Protocol (UDP) packets for nonguaranteed messaging and TCP for guaranteed messaging. A single computer can host multiple DirectPlay sessions using TCP/IP.

When the IDirectPlay4::EnumSessions method is used, TCP/IP displays a dialog box asking the user for the session's IP address. The user must enter the IP address of the computer hosting the session to be joined. If the computer has a name (such as microsoft.com), the name can be used instead of the IP address, and DirectPlay will use Domain Name System (DNS) lookup to find it. The IDirectPlay4::EnumSessions method will return the sessions that the computer is hosting. The user can also leave the address blank and select OK. In this case, DirectPlay will broadcast a message looking for sessions. This will generally only work on a LAN and only on the same subnet.

If you're hosting a session, the application can use IDirectPlay4::GetPlayerAddress to obtain the local IP address.

An application can use the IDirectPlay4::InitializeConnection method, or the IDirectPlayLobby3::SetConnectionSettings method followed by a call to IDirectPlayLobby3::Connect, to supply an IP address to the service provider in a DirectPlay Address. The IP address must be a null-terminated ANSI or Unicode string (each has a different data type GUID). If a broadcast enumeration of sessions is desired, the address must be a zero-length string; that is, a string only consisting of the null terminator.

Note: A Windows® 9x user can determine his or her IP address by choosing Run from the Start menu and typing WINIPCFG as the program to run. A Windows® NT® user can determine his or her IP address by running IPConfig from the command line. If the user is connected to both a LAN and a dial-up Internet service provider (ISP), the computer can have two IP addresses, and the correct one must be selected for that connection. Most dial-up ISPs assign a dynamic IP address that changes each time the user logs on.

The TCP/IP service provider uses port 47624 to send and receive enumeration requests. Communications are sent on the port range 2300-2400. To work through a firewall, all computers must be using DirectPlay 6.0 and the ports 47624, and the range 2300-2400 must be open for both inbound and outbound TCP and UDP traffic. Note: DirectPlay starts assigning ports at 2300 and works its way up, sequentially. It is possible to open a smaller range starting at 2300.

An application can select a specific port to use. To do so, it must initialize the TCP/IP service provider with a DirectPlay Address that includes the data chunk DPAID_INetPort. See DirectPlay Address and DirectPlay Address Data Types for more information. If an application selects a specific port to use, all communication is sent through that port, and it is only necessary to open that one port (for both inbound and outbound using TCP and UDP).

Adding DirectPlay lobby support can eliminate the need for users to enter an IP address if they start the game from a lobby server.

The TCP/IP service provider can be identified using the symbol definition DPSPGUID_TCPIP.

Note: A Windows 9x user can configure his or her computer connections to display or not display a dialog box requesting connection information when DirectPlay tries to initiate a TCP/IP connection. To suppress the display of this dialog box, follow these steps:

  1. Open Control Panel.
  2. Double-click the Internet icon.
  3. Choose the Connection tab.
  4. Clear the check box next to Connect to the Internet as needed.

IPX

The IPX service provider uses Winsock to communicate over a local area network (LAN) using the Internet Packet Exchange (IPX) protocol. The service provider only supports nonguaranteed messaging. You can use the DirectPlay Protocol for guaranteed messaging on IPX. A single computer can host only one DirectPlay session using IPX.

IPX always uses a broadcast to find sessions on the network, so the IDirectPlay4::EnumSessions method will not display a dialog box requesting IP addresses.

IPX will not enumerate sessions on another subnet.

Once a session is established, packets are sent directly between computers (they are not broadcast).

This service provider can be identified using the symbol definition DPSPGUID_IPX.

Modem-to-Modem

A modem-to-modem service provider uses Telephony API (TAPI) to communicate with another modem. The service provider only supports nonguaranteed messaging. You can use the DirectPlay Protocol for guaranteed messaging for modem sessions.

Creating a session (by using the IDirectPlay4::Open method) causes a dialog box to appear, asking the user which modem to wait for a call on. The IDirectPlay4::EnumSessions method will also display a dialog box asking the user what phone number to call and which modem to use. After the information is entered, DirectPlay will dial the modem and try to find sessions hosted by the computer on the other end. In both cases, dialog boxes are displayed to show the progress.

To enumerate the modem sessions, use EnumSessions in a loop with the DPENUMSESSIONS_RETURNSTATUS flag set on the modem service provider, and wait for DP_OK to be returned. The application should then use EnumSessions one more time to obtain the sessions.

To enumerate the modem sessions without any dialog boxes, use IDirectPlay4::EnumSessions in a loop with the DPENUMSESSIONS_RETURNSTATUS flag (see EnumSessions for more details). When DP_OK is returned, the application should then use EnumSessions one more time to obtain the actual list of sessions.

When using EnumSessions in a loop like this, the application must implement a windows message loop as follows:

while (lpDPLAY->EnumSessions(lpsd, 0, lpEnumSessionsCallback, lpContext, DPENUMSESSIONS_RETURNSTATUS) == DPERR_CONNECTING)
{
    MSG	msg;

    if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    Sleep(500);
}

The current list of available modems can be obtained from the service provider by initializing it and calling the IDirectPlay4::GetPlayerAddress method with a player ID of zero. The DirectPlay Address returned will contain a data chunk with the ANSI modem names (DPAID_Modem) and the Unicode modem names (DPAID_ModemW). The list of modems is a series of NULL-terminated strings with a zero-length string at the end of the list.

If you insert too many delays into the message processing, you can lose packets; for example, if you print a lot of debug information.

The modem-to-modem service provider can be identified by using the symbol definition DPSPGUID_MODEM.

Serial Link

A serial link is used to communicate with another computer through the serial ports. The service provider only supports nonguaranteed messaging. You can use the DirectPlay Protocol for guaranteed messaging on serial links.

Creating a session (using the IDirectPlay4::Open method) causes a dialog box to appear asking the user to configure the serial port. The IDirectPlay4::EnumSessions method will also display a dialog box asking the user to configure the serial port. You must configure the serial port the same way on both computers.

If you insert too many delays into the message processing, you may lose packets; for example, if you print a lot of debug information.

This service provider can be identified using the symbol definition DPSPGUID_SERIAL.

Lobby Providers

The lobby provider is a client component dynamic-link library (DLL) supplied by the developer of a lobby server. It implements communications functions with the lobby server as requested by DirectPlay. A lobby client written using the DirectPlay API can interoperate with any lobby server for which a lobby provider DLL is present on the system.

The DirectX® SDK installs a lobby provider for use with the test lobby server (LSERVER.EXE) included with the SDK. This lobby provider is used by the BELLHOP sample lobby client, and together they can be used to test the lobby-aware functions of your applications.

Firewall Support in DirectPlay 6.0

Applications do not need to be rewritten to take advantage of DirectPlay's new firewall support. The default behavior is to use a dynamically allocated port from DirectPlay's range. This provides backward compatibility with existing applications, as well as the ability to use multiple DirectPlay applications on a single computer.

Additionally, applications can be written to take advantage of DirectPlay's new fixed-port feature. You can choose a port number specifically for the application, and a firewall administrator need only open that particular port. See the section on selecting a specific port in the TCP/IP topic.

Compatibility

DirectX 6.0 users can still communicate with DirectX 5.0 users as long as no firewall is involved. This means that if even one computer is behind a firewall, peer-to-peer games with DirectX 5.0 computers will not work. Client/server games are allowed, as long as the host is DirectX 6.0, and in each case where the line of communication between the host and a client will pass through a firewall, that client is DirectX 6.0, as well.

Proxy Setup

Because of proxy architecture, you are limited to using a single computer. However, multiple applications (each using the dynamic DirectPlay range or unique application-defined ports) on the computer are still allowed.

For more information about using DirectPlay's firewall support, please see the following topics.

  • Setup for Client Firewall Support Using the DirectPlay Dynamic Range
  • Setup for Host Firewall Support Using the DirectPlay Dynamic Range
  • Using an Application-Specified Fixed Port
  • Setup for Client Firewall Support Using an Application-Specified Fixed Port
  • Setup for Host Firewall Support Using an Application-Specified Fixed Port
  • Dynamic Range Port Reference Chart
  • DirectX 5.0-DirectX 6.0 Cross-Compatibility Reference Chart

Setup for Client Firewall Support Using the DirectPlay Dynamic Range

To join a game through a firewall, the client must be using DirectX 6.0 and communicating with a DirectX 6.0 host. To support applications using the DirectPlay dynamic range, a firewall administrator needs to allow an initial outbound TCP connection on port 47624, with subsequent connections of inbound TCP ports 2300-2400, outbound TCP ports 2300-2400, inbound UDP ports 2300-2400, and outbound UDP ports 2300-2400. For a chart highlighting these requirements, see the Dynamic Range Port Reference Chart.

Note: It is sufficient to open only a subset of these ports starting at 2300, for example, 2300-2310. The first DirectPlay application on a particular computer will use port 2300, the next will use 2301, and so on.

Example of a Microsoft Proxy Server 2.0 Configuration:

  • Internet Service Manager, WinSock Proxy service: Service Properties
    • Add protocol "DirectPlay (client)" under Protocols tab.
      • Initial connection
        • 47624 TCP Outbound
      • Subsequent connections
        • 2300-2400 TCP Inbound
        • 2300-2400 TCP Outbound
        • 2300-2400 UDP Inbound
        • 2300-2400 UDP Outbound
    • Give appropriate permissions to "DirectPlay (client)" under Permissions tab.
  • Add to file "mspclnt.ini", which is in the C:\Msp\Clients folder by default.
    • [Common Configuration]
    • RemoteBindUdpPorts=2300-2400
    • ServerBindTcpPorts=2300-2400
    • KillOldSession=1

Setup for Host Firewall Support Using the DirectPlay Dynamic Range

To host a game through a firewall, the host must be using DirectX 6.0, and the clients beyond the firewall must be using DirectX 6.0, as well. To support applications using the DirectPlay dynamic range, a firewall administrator needs to allow an initial inbound TCP connection on port 47624, with subsequent connections of inbound TCP ports 2300-2400, outbound TCP ports 2300-2400, inbound UDP ports 2300-2400, and outbound UDP ports 2300-2400. For a chart highlighting these requirements, see the Dynamic Range Port Reference Chart.

Note: It is sufficient to open only a subset of these ports starting at 2300. For example 2300-2310. The first DirectPlay application on a particular computer will use port 2300, the next will use 2301, and so on.

Theoretical Microsoft Proxy Server 2.0 configuration:

  • Internet Service Manager, WinSock Proxy service: Service Properties
    • Add protocol "DirectPlay (host)" under Protocols tab.
      • Initial connection
        • 47624 TCP Inbound
      • Subsequent connections
        • 2300-2400 TCP Inbound
        • 2300-2400 TCP Outbound
        • 2300-2400 UDP Inbound
        • 2300-2400 UDP Outbound
    • Give appropriate permissions to "DirectPlay (host)" under Permissions tab.
  • Add to file "mspclnt.ini", which is in the C:\Msp\Clients folder by default.
    • [Common Configuration]
    • RemoteBindUdpPorts=2300-2400
    • ServerBindTcpPorts=2300-2400
    • KillOldSession=1

Unfortunately, some firewall solutions, including Microsoft Proxy Server 2.0, won't recognize additional inbound connections as subsequent connections. The workaround for this is that each port in the range (2300, 2301, 2302, and so on) must get its own protocol definition, as if it were an application-specified fixed port. For more information, see Setup for Host Firewall Support Using an Application-Specified Fixed Port. Practically, only as many ports as active DirectPlay applications need to be opened, that is, to run both the applications "SuperDuperGame" and "WackyFunGame" at the same time, only ports 2300 and 2301 will be used.

Using an Application-Specified Fixed Port

An application can choose to use a fixed port rather than the DirectPlay default ports. If this is done, only the one port needs to be opened to allow that application (and only that application) to operate through a firewall.

To specify a fixed port, the application must create a DirectPlay Address that contains the data chunk for DPAID_InetPort (defined in dplobby.h). The application can append the chunk to the lpAddress returned by EnumConnections before passing it to InitializeConnection. Alternatively, the application can create the DirectPlay Address completely (specifying the service provider, IP address and port number) and pass that to InitializeConnection.

Setup for Client Firewall Support Using an Application-Specified Fixed Port

To join a game through a firewall, the client must be using DirectX 6.0 and communicating with a DirectX 6.0 host. To support applications using an application-specified fixed port n, a firewall administrator needs to allow an initial outbound TCP connection on port n, with subsequent connections of inbound TCP port n, inbound UDP port n, and outbound UDP port n.

Example of a Microsoft Proxy Server 2.0 configuration, where the application "SuperDuperGame" (superdg.exe) specifies the port as 12345:

  • Internet Service Manager, WinSock Proxy service: Service Properties
    • Add protocol "SuperDuperGame (client)" under Protocols tab.
      • Initial connection
        • 12345 TCP Outbound
      • Subsequent connections
        • 12345 TCP Inbound
        • 12345 UDP Inbound
        • 12345 UDP Outbound
    • Give appropriate permissions to "SuperDuperGame" under Permissions tab.
  • Add to file "mspclnt.ini", which is in the C:\msp\Clients folder by default.
    • [superdg]
    • RemoteBindUdpPorts=12345
    • ServerBindTcpPorts=12345
    • KillOldSession=1

Setup for Host Firewall Support Using an Application-Specified Fixed Port

To host a game through a firewall, the host must be using DirectX 6.0, and the clients beyond the firewall must be DirectX 6.0, as well. To support applications using an application-specified fixed port n, a firewall administrator needs to allow an initial inbound TCP connection on port n, with subsequent connections of outbound TCP port n, inbound UDP port n, and outbound UDP port n.

Example of a Microsoft Proxy Server 2.0 configuration, where the application "SuperDuperGame" (superdg.exe) specifies the port as 12345.

  • Internet Service Manager, WinSock Proxy service: Service Properties
    • Add protocol "SuperDuperGame (host)" under Protocols tab.
      • Initial connection
        • 12345 TCP Inbound
      • Subsequent connections
        • 12345 TCP Outbound
        • 12345 UDP Inbound
        • 12345 UDP Outbound
    • Give appropriate permissions to "SuperDuperGame" under Permissions tab.
  • Add to file "mspclnt.ini", which is in the C:\msp\Clients folder by default.
    • [superdg]
    • RemoteBindUdpPorts=12345
    • ServerBindTcpPorts=12345
    • KillOldSession=1

Dynamic Range Port Reference Chart

The following chart shows which ports an administrator needs to open for a given desired style of play for applications using DirectPlay's dynamic range.

Connection | Client configuration | Host configuration
Initial TCP Connection | 47624 Outbound | 47624 Inbound
Subsequent Inbound TCP Connections | 2300-2400 | 2300-2400
Subsequent Outbound TCP Connections | 2300-2400 | 2300-2400
Subsequent Inbound UDP Connections | 2300-2400 | 2300-2400
Subsequent Outbound UDP Connections | 2300-2400 | 2300-2400

DirectX 5.0-DirectX 6.0 Cross-Compatibility Reference Chart

The following chart shows which versions work with each other, assuming there are only two computers, and the firewall referred to is physically the same firewall for both (that is, both the client and host are behind the same firewall):

Internet DirectX 5.0 Host | DirectX 5.0 Host Behind Firewall | Internet DirectX 6.0 Host | DirectX 6.0 Host Behind Firewall
Internet DirectX 5.0 Client | yes | no | yes | no
DirectX 5.0 Client behind firewall | no | yes | no | yes
Internet DirectX 6.0 Client | yes | no | yes | yes
DirectX 6.0 Client behind firewall | no | yes | yes | yes

The chart still holds true for more than two computers if the session is client/server. If there are more than two computers, the session is peer-to-peer, and there is a firewall involved anywhere, then all computers must be using DirectX 6.0.


Using DirectPlay

This section contains the following topics that explain how to use different aspects of DirectPlay:

  • Debug vs. Retail DLLs
  • Working with GUIDs
  • DirectPlay Interfaces
  • Using Callback Functions
  • Building Lobby-Aware Applications
  • DirectPlay Messages
  • DirectPlay Address (Optional)
  • DirectPlay Protocol
  • Asynchronous Messaging
  • Understanding DirectPlay Asynchronous Networking with the DirectPlay Protocol
  • Migrating from Previous Versions of DirectPlay
  • Debugging DirectPlay Applications
  • Security and Authentication

Debug vs. Retail DLLs

The Software Development Kit (SDK) has the option to install debug or retail builds of the DirectPlay dynamic-link libraries (DLLs). When developing software, it is best to install the debug versions of the DLLs. The debug DLLs have additional code that will validate internal data structures and output debug error messages (using the Win32® OutputDebugString API) while your program is executing. When an error occurs, the debug output will give you a more detailed description of what the problem is. The debug DLLs will execute more slowly than the retail DLLs but are much more useful for debugging an application. Be sure to ship the retail version with your application.

In order to see the debug messages, it is necessary to configure your computer so that debug output will be displayed in a window or on a remote computer. An interactive development environment like Microsoft® Visual C++™ allows you to do this. Consult the environment's documentation for set-up instructions.

See Debugging DirectPlay Applications for more information.

Working with GUIDs

Globally unique identifiers (GUIDs) are 16-byte data structures that you can use to identify objects in a globally unique way. Whenever a GUID is required in an API, a symbol representing that GUID should be used. The symbols are either defined in one of the DirectPlay header files, or the application developer must generate them. You can generate GUIDs by using the Guidgen.exe utility that comes with Microsoft Visual C++. For example, every application must define an application GUID that identifies the application that is running in a session.

Note If there are different versions of an application that cannot interoperate in the same session, they should have different application GUIDs to distinguish them.

To use DirectPlay-defined GUIDs successfully in your application, you must either define the INITGUID symbol prior to all other include and define statements, or you must link to the Dxguid.lib library. If you define INITGUID, you should define it in only one of your source modules.

DirectPlay Interfaces

All the functionality in DirectPlay is accessed through member functions on Component Object Model (COM) interfaces. To use them, an application must obtain the appropriate COM interface.

The standard method of obtaining COM interfaces is to use the Win32 CoCreateInstance API. To use it successfully, the application must first call the Win32 CoInitialize API to initialize COM, and then call CoCreateInstance, specifying the GUID of the desired interface. For example, use the following code to obtain an IDirectPlay4A interface:

  // C++ example
  hr = CoCreateInstance( CLSID_DirectPlay, NULL, CLSCTX_INPROC_SERVER,
                         IID_IDirectPlay4A, (LPVOID*)&lpDirectPlay4A);
  // C example
  hr = CoCreateInstance( &CLSID_DirectPlay, NULL, CLSCTX_INPROC_SERVER,
                         &IID_IDirectPlay4A, (LPVOID*)&lpDirectPlay4A);

When the program is finished, all the COM interfaces must be freed by calling the Release method on each interface. Finally, the Win32 CoUninitialize method should be called to uninitialize COM.

If you call CoCreateInstance without first calling CoInitialize, you will get a CO_E_NOTINITIALIZED error, with the error text "CoInitialize has not been called."

DirectPlay has several COM interfaces. Each interface represents a revision of an earlier version of DirectPlay in which new methods are added. COM interfaces are numbered sequentially with each revision. The latest COM interface will have all the latest functionality of DirectPlay. To access the new functionality (for example, IDirectPlay4::SendChatMessage), you must use the latest COM interface. Source code written for an earlier COM interface will work.

Once a COM interface is obtained, an alternate interface can be used on the same object by calling the QueryInterface method on the interface. For example, DirectPlayCreate will create a DirectPlay object and return an IDirectPlay interface. If your application requires an IDirectPlay4 interface, it can call QueryInterface on the IDirectPlay interface. Be sure to release the original IDirectPlay interface if it is no longer needed.

Using Callback Functions

The enumeration methods in DirectPlay are used to return a list of items to the application. The application calls an enumeration method (such as IDirectPlay4::EnumPlayers) and supplies a pointer to a callback function that it has implemented. DirectPlay will call the callback function once for each item in the list. The enumeration method will not return until all the items in the list have been returned to the application through the callback function.

It is extremely important that all callbacks be declared correctly. For example:

BOOL FAR PASCAL EnumConnectionsCallback(LPCGUID lpguidSP, LPVOID lpConnection, DWORD dwConnectionSize,
LPCDPNAME lpName, DWORD dwFlags, LPVOID pContext);

The FAR PASCAL symbol will define the function as _stdcall. That means it will clean up the stack before returning to DirectPlay. Do not cast function pointers when passing them to a DirectPlay enumeration method. If there is a compiler warning about the function pointer, fix the function declaration.

Building Lobby-Aware Applications

A lobby-aware application is one that, at a minimum, supports being launched from a lobby. A matchmaking lobby is a site on the Internet where end users can find other people to play games with. Once a group of people has decided to start an application session, the lobby software can launch the application on each person's computer and have them all connect to a session. The main benefit for end users is the ease with which they can establish a session with other players. Not only does it allow a user to easily find opponents, but there is also no need for the user to:

  • Select a service provider. The lobby will specify which service provider to use.
  • Decide whether to host or join a session. The lobby will specify whether to create or join a session.
  • Enter a network address or configure the network. The lobby will supply this information if it is needed.
  • Enter the name of the player. The lobby will pass in the same name that the user connected to the lobby with.

Other benefits of the lobby are:

  • It can keep track of sessions in progress and enable users to join them.
  • It can receive status messages from the session and display the progress to other users on a scoreboard.
  • It can obtain final scores and maintain player rankings for tournament play.

For a DirectPlay application to be lobby-aware, at a minimum, it must support being launched from a lobby. You can add other features to make it integrate better with the lobby. For additional information see the following topics within this section.

  • Registering Lobby-Aware Applications
  • Supporting External Lobby Launching
  • Supporting Dynamic Lobby Connection
  • LobbyMessaging (Optional)

Registering Lobby-Aware Applications

To enable a lobby to launch a DirectPlay application, the application must add entries to the system registry. Once an application has been registered, it will be recognized as a lobby-aware application and lobbies can launch it. These registry entries must be deleted when the application is removed.

You can register your application by filling in the DPAPPLICATIONDESC structure with the necessary information, then calling IDirectPlayLobby3::RegisterApplication. You can unregister your application by calling IDirectPlayLobby3::UnRegisterApplication.

Supporting External Lobby Launching

Once the application has been registered, the DirectPlay application must be able to recognize whether a lobby launched it. If a lobby launched the application, it must follow a slightly different code path to set up the network connection. Consult the DUEL (Lobby.c) and DPCHAT (Lobby.cpp) samples in the SDK for the code necessary to support external lobby launching. See Tutorial 1: Connecting by Using the Lobby for a demonstration on how to connect an application by using a DirectPlay lobby.

The necessary basic steps are:

  1. At startup, create an IDirectPlayLobby3 interface using the CoCreateInstance API.
  2. The application can examine the connection information that was passed in by the lobby and modify some of the connection settings if necessary. The IDirectPlayLobby3::GetConnectionSettings method returns a DPLCONNECTION structure with the connection settings. This method returns DPERR_NOTLOBBIED if a lobby did not launch the application. New settings can be set with IDirectPlayLobby3::SetConnectionSettings.
  3. IDirectPlayLobby3::ConnectEx creates or joins the specified application session using the specified service provider and returns an IDirectPlay interface of your choosing. ConnectEx returns an error if the session could not be created or joined, or if a lobby did not launch the application.
  4. Create a player using the name information supplied in the DPLCONNECTION structure obtained in step two.

At this point, the application can continue on the same code path as if the user had manually selected a connection, joined or created a session, and entered the name of the player to create.

The IDirectPlayLobby3 interface can be saved if the game will pass information back to the lobby (see Lobby Messaging), or it can be discarded by using the Release method if no messages will be sent.

Many lobbies will launch the application and then go into a suspend mode, waiting for the application to terminate. DirectPlay will notify the lobby when the application that it launched has terminated. For this reason it is important that the application launched by the lobby not launch another application.

Supporting Dynamic Lobby Connection

One drawback of the external lobby launching described in the preceding topic is that the lobby server always launches a new instance of your game, even if one is already running. You can avoid this by supporting dynamic lobby connection.

The instructions in this section assume you already have a game running and a connection to a lobby server which will return you connection settings. The disadvantage of this approach is that the lobby server always launches a new instance of your game even when one is already running. This method of supporting dynamic lobby connection is implemented in the Duel sample.

  1. At startup, create an IDirectPlayLobby3 interface using the CoCreateInstance API.
  2. Ask the user to choose dynamic lobby connection. The user must choose dynamic lobby connection instead of manual network configuration.
  3. Call IDirectPlayLobby3::WaitForConnectionSettings to put your application in wait mode.
  4. Wait for a lobby message to come in using IDirectPlayLobby3::ReceiveLobbyMessage. The message type to expect is the DPLSYS_NEWCONNECTIONSETTINGS system message. Note that you can call WaitForConnectionSettings again to cancel wait mode.
  5. After you receive the system message, examine the connection information that was passed in by the lobby and modify some of the connection settings if necessary. The IDirectPlayLobby3::GetConnectionSettings method returns a DPLCONNECTION structure with the connection settings. This method returns DPERR_NOTLOBBIED if a lobby did not launch the application. New settings can be set with IDirectPlayLobby3::SetConnectionSettings.
  6. IDirectPlayLobby3::ConnectEx creates or joins the specified application session using the specified service provider and returns an IDirectPlay interface of your choosing. ConnectEx returns an error if the session could not be created or joined, or if a lobby did not launch the application.
  7. Create a player using the name information supplied in the DPLCONNECTION structure obtained in step five.

Lobby Messaging (Optional)

After registering a lobby-aware application and adding the code to support external lobby launching, the next step in integrating the application with the lobby is to send information back to the lobby or to request information from the lobby. You can do this by exchanging messages with the lobby through the IDirectPlayLobby3::SendLobbyMessage and IDirectPlayLobby3::ReceiveLobbyMessage methods on the IDirectPlayLobby3 interface. Standard message structures have been defined by DirectPlay to facilitate this functionality.

Sending information to the lobby is done through setting properties. The application must create and fill in a DPLMSG_SETPROPERTY structure and send it to the lobby by using the SendLobbyMessage method. Each property identifies a distinct type of data. The application developer should generate GUIDs (using Guidgen.exe) for every property that will be set. The lobby operator needs to obtain this list of GUIDs from the application developer along with the description and data structure of each property.

Properties can take the form of:

  • Current individual player scores.
  • Final individual player scores.
  • Player configuration for later retrieval.
  • Current game status (level or mission).

The lobby can store this information or display it to other users in the lobby so they can monitor the game's progress. An application can request confirmation that the property was set correctly by supplying a nonzero request ID with the set property message.

Requesting information from the lobby is done through requesting properties. The application must create and fill in a DPLMSG_GETPROPERTY structure and send it to the lobby by using the SendLobbyMessage method. At some later time, the lobby will send a message back to the application—a DPLMSG_GETPROPERTYRESPONSE structure that contains the property data that was requested. The application can retrieve the message from the lobby message queue using the ReceiveLobbyMessage method. As before, the application developer generates the GUIDs for each property and the lobby operator must obtain them from the developer.

The following list shows examples of some properties that can be requested from the lobby:

  • Game configuration settings — enables players to configure the game in the lobby before launching the game.
  • Player configuration settings — enables players to configure their players in the lobby or to use a stored configuration from a previous session.
  • Other information stored from a previous session.

Not all lobbies will be able to support these standard lobby messages. The application can determine whether the lobby that it was launched from supports standard lobby messages by sending a DPLMSG_GETPROPERTY message requesting the DPLPROPERTY_MessagesSupported property.

DirectPlay Messages

The following sections describe how to use messages in DirectPlay.

  • Synchronization
  • Using System Messages
  • Using Lobby Messages

Synchronization

An application can use two methods to process DirectPlay messages. The first is to check the receive queue during the main loop of the application. Typically, this means the application is single threaded.

Alternatively, an application can have a separate thread to wait for messages and process them. In this case the application should supply a non-NULL, auto-reset synchronization event handle (see the Win32 CreateEvent API) when it creates players. DirectPlay will set this event when a message arrives for that player. All the local players in an application can share the same event or each can have his or her own event.

The message processing thread should then use the Win32 WaitForSingleObject API to wait until the event is set. Continue calling Receive until there are no more messages in the message queue.

Using System Messages

Messages returned by the IDirectPlay4::Receive method from player ID DPID_SYSMSG are system messages. All system messages begin with a double-word value specified by the dwType DWORD value. You can cast the buffer returned by the IDirectPlay4::Receive method to a generic message (DPMSG_GENERIC) and switch on the dwType element, which will have a value equal to one of the messages with the DPSYS_ prefix. After the application has determined which system message it is, the buffer should be cast to the appropriate structure (beginning with the DPMSG_ prefix) to read the data.

Your application should be prepared to handle the following system messages.

Value of dwType | Message structure | Cause
DPSYS_ADDGROUPTOGROUP | DPMSG_ADDGROUPTOGROUP | An existing group has been added to an existing group.
DPSYS_ADDPLAYERTOGROUP | DPMSG_ADDPLAYERTOGROUP | An existing player has been added to an existing group.
DPSYS_CHAT | DPMSG_CHAT | A chat message has been received.
DPSYS_CREATEPLAYERORGROUP | DPMSG_CREATEPLAYERORGROUP | A new player or group has been created.
DPSYS_DELETEGROUPFROMGROUP | DPMSG_DELETEGROUPFROMGROUP | A group has been removed from a group.
DPSYS_DELETEPLAYERFROMGROUP | DPMSG_DELETEPLAYERFROMGROUP | A player has been removed from a group.
DPSYS_DESTROYPLAYERORGROUP | DPMSG_DESTROYPLAYERORGROUP | An existing player or group has been destroyed.
DPSYS_HOST | DPMSG_HOST | The current host has left the session and this application is the new host.
DPSYS_SECUREMESSAGE | DPMSG_SECUREMESSAGE | A digitally signed or encrypted message has been received.
DPSYS_SENDCOMPLETE | DPMSG_SENDCOMPLETE NEW NEW! | An asynchronous send is complete.
DPSYS_SESSIONLOST | DPMSG_SESSIONLOST | The connection with the session has been lost.
DPSYS_SETGROUPOWNER | DPMSG_SETGROUPOWNER NEW NEW! | The owner of the group has changed.
DPSYS_SETPLAYERORGROUPDATA | DPMSG_SETPLAYERORGROUPDATA | Player or group data has changed.
DPSYS_SETPLAYERORGROUPNAME | DPMSG_SETPLAYERORGROUPNAME | Player or group name has changed.
DPSYS_SETSESSIONDESC | DPMSG_SETSESSIONDESC | Session description has changed.
DPSYS_STARTSESSION | DPMSG_STARTSESSION | Lobby server is requesting that a session be started.

Using Lobby Messages

Messages returned by the IDirectPlayLobby3::ReceiveLobbyMessage method fall into two categories: DirectPlay-defined messages and custom-defined messages. The message category can be identified by the lpdwMessageFlags parameter of ReceiveLobbyMessage. The flags indicate that the message is either a system message (the DPLMSG_SYSTEM flag) or a standard message (the DPLMSG_STANDARD flag). If neither of these flags is set, the message is custom-defined. System messages are generated automatically by DirectPlay and are sent to the lobby only to inform it of changes in the status of the application. Standard messages can be generated by either the lobby or the application and sent to each other.

The advantage of standard messages over custom-defined messages is that the receiver can positively interpret the message. All applications and lobbies are not required to act on standard messages.

DirectPlay-defined messages all start with a DWORD value that identifies the message type. After retrieving a message using ReceiveLobbyMessage, the lpData pointer to the message data should be cast to the DPLMSG_GENERIC structure and the structure's dwType member examined. Based on the value of dwType, the lpData pointer should then be cast to the appropriate message structure for further processing.

Lobbies should be prepared to handle all the message types in the following table. Applications need to handle the DPLMSG_GETPROPERTYRESPONSE message if they generate DPLMSG_GETPROPERTY messages.

Messages returned by the IDirectPlayLobby3::ReceiveLobbyMessage method that have a dwFlags parameter set to DPLMSG_SYSTEM are system messages. All system messages begin with a double-word value specified by dwType. You can cast the buffer returned by the IDirectPlayLobby3::ReceiveLobbyMessage method to a generic message (DPLMSG_GENERIC) and switch on the dwType element, which will have a value equal to one of the messages with the DPLSYS_ prefix.

The following list shows the possible values of the dwType data member, and the message structure and message cause associated with each value.

Value of dwType | Message structure | Cause
DPLSYS_APPTERMINATED | DPLMSG_SYSTEMMESSAGE | The application has terminated.
DPLSYS_CONNECTIONSETTINGSREAD | DPLMSG_SYSTEMMESSAGE | The application has read the connection settings.
DPLSYS_DPLAYCONNECTFAILED | DPLMSG_SYSTEMMESSAGE | The application failed to connect to the DirectPlay session.
DPLSYS_DPLAYCONNECTSUCCEEDED | DPLMSG_SYSTEMMESSAGE | The application successfully connected to the DirectPlay session.
DPLSYS_GETPROPERTY | DPLMSG_GETPROPERTY | The application is requesting a property from the lobby.
DPLSYS_GETPROPERTYRESPONSE | DPLMSG_GETPROPERTYRESPONSE | The lobby is responding to a prior DPLMSG_GETPROPERTY message.
DPLSYS_NEWCONNECTIONSETTINGS | DPLMSG_SYSTEMMESSAGE | A waiting application was found when a lobby client called RunApplication. The waiting application can now read the connection settings with GetConnectionSettings and join a session using ConnectEx.
DPLSYS_NEWSESSIONHOST | DPLMSG_NEWSESSIONHOST NEW NEW! | The application session has a new host.
DPLSYS_SETPROPERTY | DPLMSG_SETPROPERTY | The application is setting a property on the lobby.
DPLSYS_SETPROPERTYRESPONSE | DPLMSG_SETPROPERTYRESPONSE | The lobby is responding to a prior DPLMSG_SETPROPERTY message.

DirectPlay Address (Optional)

A DirectPlay Address is a data format that DirectPlay uses to pass addressing information between lobby servers, applications, DirectPlay, and service providers. The format is flexible enough to hold any number of variable-length data fields that make up a network address. You do not need to understand DirectPlay Addresses in order to use DirectPlay. In fact, you can successfully write a DirectPlay application without understanding DirectPlay Addresses.

This section contains the following topics:

  • DirectPlay Address Data Types
  • Using DirectPlay Addresses
  • Examples of Using DirectPlay Addresses

You only need to learn about DirectPlay Addresses if you want to do one of the following:

  • Override the standard service provider dialog boxes. You need to create a DirectPlay Address that specifies which service provider to use and contains all the information the service provider needs to establish a connection. You then pass the DirectPlay Address to the IDirectPlay4::InitializeConnection method.
  • Write a lobby client that will launch an external DirectPlay application. The lobby client needs to create a DirectPlay Address that specifies which service provider to use and contains all the information the service provider needs to establish a connection and automatically connect the client to a session. You need to create a DirectPlay Address of the session to be joined and put it in the DPLCONNECTION structure before calling the IDirectPlayLobby3::RunApplication method.

A DirectPlay Address is a sequence of variable-length data chunks tagged with a GUID that supplies all the address information needed by DirectPlay. Examples are the network address of a server, the network address of a player, the e-mail name of a player, or the network address of a session.

DirectPlay Address Data Types

Microsoft has predefined the following general data types for each data chunk. Based on the data type, the data must be cast to the appropriate type or structure to interpret the data.

GUID | Type of Data
DPAID_ComPort | A DPCOMPORTADDRESS structure that contains all the settings for the COM port. The serial connection service provider will use this information to configure the serial port.
DPAID_INet A null-terminated ANSI string (LPSTR) containing an IP address ("137.55.100.173") or a domain net ("gameworld.com"). The length, in bytes, must include the terminator.

A blank address is a string that contains only the ANSI terminator (0x00) and has a length of 1 byte. If a blank address is supplied, the Internet TCP/IP connection service provider will use this information to enumerate sessions on the specified network address or to broadcast on the subnet.

DPAID_INetW A null-terminated Unicode string (LPWSTR) containing an IP address ("137.55.100.173") or a domain net ("gameworld.com"). The length in bytes must include the terminator.

A blank address is a string that contains only the Unicode terminator (0x0000) and has a length of 2 bytes. If a blank address is supplied, the Internet TCP/IP connection service provider will use this information to enumerate sessions on the specified network address or broadcast on the subnet.

DPAID_INetPort | A WORD (2 bytes) containing the specific port number to use. See the section on selecting a specific port in the TCP/IP topic or see Firewall Support in DirectPlay 6.0 for information about using this DirectPlay Address.
DPAID_LobbyProvider | The 16-byte GUID that specifies the lobby provider this DirectPlay Address applies to.
DPAID_Modem | A variable-length null-terminated ANSI string (LPSTR) specifying which installed modem to use. The length, in bytes, must include the terminator. The modem service provider will use this modem without displaying a dialog box asking the user which modem to use. Use the IDirectPlay4::GetPlayerAddress method to determine which modems are available.
DPAID_ModemW | A variable-length, null-terminated Unicode string (LPWSTR) specifying which installed modem to use. The length, in bytes, must include the terminator. The modem service provider will use this modem without displaying a dialog box asking the user which modem to use. Use the IDirectPlay4::GetPlayerAddress method to determine which modems are available.
DPAID_Phone | A variable-length, null-terminated ANSI string (LPSTR) containing a phone number. The length, in bytes, must include the terminator. The modem service provider will call this phone number on the IDirectPlay4::EnumSessions method. If no modem is specified, the first modem will be used.
DPAID_PhoneW | A variable-length null-terminated Unicode string (LPWSTR) containing a phone number. The length in bytes must include the terminator. The modem service provider will call this phone number on the IDirectPlay4::EnumSessions method. If no modem is specified, the first modem will be used.
DPAID_ServiceProvider | The 16-byte GUID that specifies the service provider this DirectPlay Address applies to.
DPAID_TotalSize | A DWORD containing the size of entire DPADDRESS structure.

Using DirectPlay Addresses

You can use a DirectPlay Address to encapsulate all the information necessary to initialize a DirectPlay object. At a minimum, this is the GUID of a DirectPlay provider, but can also include the network address of an application or lobby server and even a specific session instance GUID.

A DirectPlay Address can be used to supply enough information to DirectPlay (and the DirectPlay provider) when it is initialized so that no dialog boxes appear later during the process of establishing a session or connecting to a session.

The DirectPlay Addresses returned by EnumConnections are simply registered DirectPlay providers that the user can choose from. When one of these is initialized, dialog boxes can appear, which ask the user for more information.

The application can create a DirectPlay Address directly using the IDirectPlayLobby3::CreateAddress and IDirectPlayLobby3::CreateCompoundAddress methods on the IDirectPlayLobby3 interface and pass the connection to the IDirectPlay4::InitializeConnection method to initialize the DirectPlay object. If enough valid information is supplied, then no DirectPlay dialog boxes will appear.

Examples of Using DirectPlay Addresses

This topic contains examples of DirectPlay Addresses and the data they contain for different connection types.

A DirectPlay Address describing an IPX connection

Initializing this connection will bind the DirectPlay object to the IPX service provider.

guidDataType | dwDataSize | Data
DPAID_ServiceProvider | 16 | {685BC400-9D2C-11cf-A9CD-00AA006886E3}

A DirectPlay Address describing a modem connection

Initializing this connection binds DirectPlay to the modem service provider and stores the phone number. A subsequent call to the IDirectPlay4::EnumSessions will dial the number without asking the user for a phone number.

guidDataType | dwDataSize | Data
DPAID_ServiceProvider | 16 | {44EAA760-CB68-11cf-9C4E-00A0C905425E}
DPAID_Phone | 9 (including NULL terminator) | "555-8237"

A DirectPlay Address describing a TCP/IP connection

Initializing this connection binds DirectPlay to the TCP/IP service provider and stores the IP address. A subsequent call to IDirectPlay4::EnumSessions will enumerate sessions on this server without asking the user for an IP address.

guidDataType | dwDataSize | Data
DPAID_ServiceProvider | 16 | {36E95EE0-8577-11cf-960C-0080C7534E82}
DPAID_INet | 10 (including NULL terminator) | "127.0.0.1"

DirectPlay Protocol

The DirectPlay protocol is an implementation of guaranteed messaging on nonguaranteed service providers. For example, the Internetwork Packet Exchange (IPX) service provider does not inherently support guaranteed messaging. When an application tries to send a guaranteed message on IPX, the DirectPlay protocol will take care of doing all the handshaking necessary to guarantee delivery of the message.

The DirectPlay protocol also implements asynchronous messaging and message throttling, although the service provider may optimize this functionality.

An application invokes the DirectPlay protocol by setting the DPSESSION_DIRECTPLAYPROTOCOL flag when creating a session.

System messages are always sent guaranteed, whether or not the service provider natively supports guaranteed messages, and whether or not you set the DirectPlay protocol flag. The DirectPlay protocol will be used automatically to send system messages guaranteed.

For non-system messages, if an application sets the DirectPlay protocol flag and sends a message guaranteed (by setting the DPSEND_GUARANTEED flag in SendEx), the message will be sent guaranteed whether the service provider supports guaranteed messages or not.

For non-system messages, if an application does not set the DirectPlay protocol flag and sends a message guaranteed, the message will be sent guaranteed only if the service provider supports it. If the service provider does not support guaranteed messages, the message will not be sent guaranteed, regardless of the DPSEND_GUARANTEED flag.

An application also can also specify that the DirectPlay protocol be used instead of the default guaranteed messaging implemented by the service provider. This is also done by specifying the DPSESSION_DIRECTPLAYPROTOCOL flag when creating a session.

The following table summarizes how non-system messages are sent.

If the DirectPlay Protocol flag is not set:

Service Provider Messages Sent Guaranteed Use: Messages Sent Nonguaranteed Use:
IPX | IPX, won't be sent guaranteed | IPX
TCP/IP | TCP | UDP
Modem | Modem, won't be sent guaranteed | Modem

If the DirectPlay Protocol flag is set:

Service Provider Messages Sent Guaranteed Use: Messages Sent Nonguaranteed Use:
IPX | DirectPlayProtocol/IPX | DirectPlayProtocol/IPX
TCP/IP | DirectPlayProtocol/UDP | DirectPlayProtocol/UDP
Modem | DirectPlayProtocol/Modem | DirectPlayProtocol/Modem

When the DirectPlay protocol flag is not set, the application must examine the capabilities of the service provider (after the session has been opened) to determine what functionality is available in terms of asynchronous messaging, canceling messages, timeouts on messages, and prioritization of messages. If the DirectPlay protocol flag is set, all this functionality is available.

Unless the service provider is TCP/IP, when the DirectPlay Protocol flag is not explicitly set, messages will not be sent guaranteed.

Asynchronous Messaging

The ability to send messages asynchronously frees the application's communication code from blocking while each message is transmitted. It offloads management of outgoing messages to DirectPlay while still giving the application programmer the ability to monitor the message queue and to cancel messages.

The asynchronous messaging feature is only available if the session is using the DirectPlay Protocol or if it is supported by the service provider. For example, the TCP/IP service provider only supports asynchronous messages when the computer is using WinSock 2.0 or greater. If the DirectPlay Protocol is not being used, it is important to use IDirectPlay4::GetCaps method to check the DPCAPS_ASYNCSUPPORTED flag after the session has been established, to determine whether asynchronous messages are supported.

To send an asynchronous message, you must use the IDirectPlay4::SendEx method with the DPSEND_ASYNC flag set in the dwFlags parameter. SendEx will return immediately. Later, the application will receive a DPMSG_SENDCOMPLETE system message with the status result for the sent message. You can disable the notification by setting the DPSEND_NOSENDCOMPLETEMSG flag when the message is sent. The application can track individual messages using the dwMsgID parameter returned by SendEx. This ID can be used to cancel individual messages or to match completion notification messages.

SendEx can be used to assign a timeout value and a priority to a message in sessions that support these properties. You can also cancel messages in the send queue using the IDirectPlay4::CancelMessage or IDirectPlay4::CancelPriority method. Timeout, priority, and cancellation functionality require the DirectPlay Protocol or service provider support, as determined by the GetCaps method.

You should exercise great care when mixing asynchronous and synchronous messages. A synchronous message will be sent after any asynchronous messages ahead of it in the queue and will then block until completed. If supported, timeouts and priorities can be used with synchronous messages. Message tracking by ID and cancellation do not apply to synchronous messages.

Asynchronous messaging does not increase bandwidth or decrease latency.

Understanding DirectPlay Asynchronous Networking with the DirectPlay Protocol

When you are designing a network gaming application, the object of the networking code is to provide the basis for a synchronized game environment to many players. The networking code must handle many different network environments which may provide low or high latency, low or high bandwidth, and varying reliability.

Until now, it has been left to the game developers to determine the characteristics of the network link and adapt the game appropriately. Typically, the solution that most developers have applied is to minimize the amount and frequency of the data sent to the lowest common denominator. Although this approach provides a solution that works well in the harshest environments, it does not provide the best gaming experience to the end user. In many cases, the game could send many more updates or more information per update to enhance the user experience and keep tighter synchronization of the gaming environment. The goal of the network code should be to use all available bandwidth for updating the game state. At the same time, the code must avoid backlogging the connection by sending faster than the link can handle, which leads to higher latencies and worse game synchronization.

The DirectPlay protocol and the new asynchronous DirectPlay capability, supported by SendEx, CancelMessage, and GetMessageQueue, provide an environment where the network code in an application can recognize link capabilities and adapt its behavior to make maximum use of available bandwidth. The DirectPlay protocol uses feedback from the receiver, letting the protocol know how much data is arriving at the receiver. Unlike existing network protocols, the feedback allows the DirectPlay protocol to precisely control its sending rate so as not to build up a backlog of message packets between the sender and the receiver. The DirectPlay protocol also applies this feedback to unreliable messages. This "throttling" of sent messages not only guarantees that the client application does not introduce excessive latencies into the game by creating a backlog, it also allows the client to adapt itself. By viewing the send queue, the client can recognize when it is sending data faster than the link can deliver the data or when the client is not using nearly the available bandwidth. This gives the client the opportunity to adjust its sending strategy to the capabilities of the existing link.

In order to take maximum advantage of the DirectPlay protocol, you should send messages asychronously, using SendEx with the DPSEND_ASYNC flag set. Messages sent asynchronously do not block. When you send a message asynchronously, the send is not completed when the call to SendEx returns. Instead, the send will complete at a later time and inform you by posting a completion message to the receive queue. Asynchronous sends allow the application to have multiple outstanding reliable sends or non-reliable sends. If you use asynchronous sends, the DirectPlay protocol can be sending many messages, both reliable and non-reliable, simultaneously on a link. That is, the protocol does not wait for the completion of one message before sending another. This prevents single packet losses from hurting link use. It also prevents the loss of one reliable packet from slowing the delivery of other reliable messages.

Typically, network games have used non-reliable messages only for transferring a real-time game state. The primary reasons for this strategy are that sending a non-reliable message generally does not block and that many non-reliable messages can be sent without waiting. The DirectPlay protocol enables you to send reliable messages that do not block and to have many outstanding reliable sends on each connection. This means your game can use reliable sends and be just as responsive as a game that uses non-reliable sends. This can greatly simplify the design of your game state updates and allows you to use incremental updates, which are almost impossible with non-reliable sends.

There are a few things you must watch out for when using the DirectPlay protocol:

  • When the DirectPlay protocol is active, synchronous non-reliable sends may block because of throttling. By setting the asychronous flag on your sends, you can get the non-reliable sends to return immediately and prevent your game thread from blocking.
  • Even though the DirectPlay protocol makes better use of the network link, you still have to think carefully and minimize the amount of data you send. Always, less data per state update is better, and the goal is to get more updates per second to improve the user experience.
  • When you are making asynchronous sends, the protocol makes a copy of the send data so you can reuse your buffer (or allocate your messages on the stack), so remember that every sent message that is still in the pending queue represents a memory allocation as big as that send, and don't let the send queue grow without limits. There is generally no advantage to letting the send queue to a particular player grow beyond 16 sends. The number of messages in the send queue is absolutely limited by the DirectPlay protocol to 29 in the current implementation. Any additional sends will not be sent concurrently; that is, they will wait for other sends to finish before they put any packets on the network link. You can check the send or receive queue for an individual player with GetMessageQueue.
  • Do not get confused by the difference between the send queue to a particular player and all the send queues. When you are throttling sends, you generally want to get the queue for the player you are sending to and not for all the players. This also means you will probably want to use directed sends rather than group sends.
  • If you always find the send queue is empty, you should send at a higher data rate in order to improve game synchronization. Since the protocol feeds back from the receiver, there is no danger of swamping the receiver. An empty queue is wasted bandwidth.
  • Don't loop tightly checking the queue. Sleep in between. A constantly spinning thread can use all the CPU cycles. You can adapt the sleep period based on how long it takes the queue to get down to a level where you usually issue another send.
  • The send queue represents a backlog. The longer the send queue is the longer the latency of additional sends. If the queue is growing too large or too long, cancel messages with CancelMessage.

Migrating from Previous Versions of DirectPlay

The DirectPlay version 6.0 API is fully compatible with applications written for any previous version of DirectPlay. That is, you can recompile your application by using DirectPlay on the DirectX 6.0 SDK without making any changes to the code. DirectPlay supplied with the DirectX 6.0 SDK supports all the APIs and behavior of earlier DirectPlay versions.

For specific information, see:

  • Migrating from DirectPlay 3.0 or DirectPlay 5.0
  • Migrating from DirectPlay 2.0 or Earlier

Migrating from DirectPlay 3.0 or DirectPlay 5.0

If you are migrating to DirectPlay version 6.0 from DirectPlay version 3.0 or version 5.0, you do not have to make any changes. However, you should upgrade your application to use the new IDirectPlay4 or IDirectPlay4A interfaces.

For a list of new features in version 6.0 of DirectPlay, see What's New in DirectPlay 6.0.

Some system messages were changed in DirectPlay 5.0, with new data members added to the end. These new members are continued in DirectPlay 6.0. Applications that need to be backward-compatible with older runtimes should either:

  • Compile with the DirectX 3.0 header files and libraries.
  • Not reference new data members.
  • Test with both the DirectX 3.0 and the DirectX 6.0 run time.

The system message structures that had new members added for DirectPlay 5.0 were:

Structure | New members
DPMSG_CREATEPLAYERORGROUP | DPID dpIdParent
DWORD dwFlags
DPMSG_DESTROYPLAYERORGROUP | DPNAME dpnName
DPID dpIdParent
DWORD dwFlags

Migrating from DirectPlay 2.0 or Earlier

The names of the DirectPlay DLLs in version 3.0 and later are different from those in previous DirectPlay versions. Applications compiled with DirectX 2.0 or earlier do not use the new DirectPlay DLLs. To use the new DLLs, the application must be recompiled and linked to the Dplayx.lib import library.

It is also recommended that you add the code necessary to make the application lobby-aware. This means that an external lobby or matchmaking program can start the application and supply it with all the information necessary to connect to a session. The application need not ask the user to decide on a service provider, select a session, or supply any other information (such as a telephone number or network address).

In addition, several other new features were added in the DirectPlay version 6.0 API. (For a description of the new features, see What's New in DirectPlay 6.0.) The new features include:

  • Guaranteed messaging.
  • Asynchronous messaging.
  • Message throttling.
  • Firewall support.
  • Lobby improvements.
  • Security improvements.
  • Improved localization support.
  • APIs to register and unregister applications.
  • Better management of group ownership.
  • Improved keepalive support.
  • Private service providers.

Migrating to the IDirectPlay4 Interface

To migrate an application created with DirectPlay version 2.0 or earlier, carry out the following steps:

  1. Find out if your application was launched from a lobby client. For more information, see Step 2: Retrieving the Connection Settings.
  2. If your application is enumerating service providers, use the EnumConnections method to determine if a service provider is available. If so, call the InitializeConnection method on the service provider. If InitializeConnection returns an error, the service provider cannot run on the system, and you should not add that service provider to the list to show to the user. If the call succeeds, use the Release method to release the DirectPlay object and add the service provider to the list.
  3. Call the QueryInterface method on the IDirectPlay interface to obtain an IDirectPlay4 (Unicode) or IDirectPlay4A (ANSI) interface. The only difference between the two interfaces is how strings in the structures are read and written. For the Unicode interface, Unicode strings are read and written to the member of the structure that is of the LPWSTR type. For the ANSI interface, ANSI strings are read and written to the member of the structure that is of the LPSTR type.
  4. Make all the changes necessary to use the new structures in existing APIs. For example, instead of the following:
    lpDP->SetPlayerName(pidPlayer, lpszFriendlyName, lpszFormalName)

    where lpDP is an IDirectPlay interface, use the following:

    DPNAME PlayerName, *lpPlayerName;
PlayerName.dwSize = sizeof(DPNAME);
lpPlayerName = &PlayerName;

lpPayerName->lpszShortNameA = lpszFriendlyName;
lpPlayerName->lpszLongNameA = lpszFormalName;
lpDP4A->SetPlayerName(pidPlayer, lpPlayerName, 0)

    where lpDP4A is an IDirectPlay4A interface. If the application is using Unicode strings (and therefore instantiates an IDirectPlay4 interface), use the following:

    lpPayerName->lpszShortName = lpwszFriendlyName;
lpPlayerName->lpszLongName = lpwszFormalName;
lpDP4->SetPlayerName(pidPlayer, lpPlayerName, 0)

    where lpDP4 is an IDirectPlay4 interface.

  5. Update the following system messages:
    • DPSYS_ADDPLAYER has been replaced by DPSYS_CREATEPLAYERORGROUP.
    • DPSYS_DELETEPLAYER and DPSYS_DELETEGROUP have been combined in a single DPSYS_DESTROYPLAYERORGROUP message.
    • DPSYS_DELETEPLAYERFROMGRP has been changed to DPSYS_DELETEPLAYERFROMGROUP.
  6. Update your application to generate a DPSYS_SETPLAYERORGROUPNAME message when a player or group name changes, and a DPSYS_SETPLAYERORGROUPDATA message when the player or group data changes.
  7. Update the DPSESSIONDESC structure to DPSESSIONDESC2, and add the new members to the DPCAPS structure.
  8. Update the callback functions for IDirectPlay4::EnumSessions, IDirectPlay4::EnumGroups, IDirectPlay4::EnumGroupPlayers, and IDirectPlay4::EnumPlayers.
  9. Update the manner in which the hEvent parameter is supplied to the IDirectPlay4::CreatePlayer method. In previous versions of DirectPlay, this parameter was lpEvent. DirectPlay does not return an event; instead, the application must create it. This allows the application the flexibility of creating one event for all the players.
  10. Set the DPSESSION_KEEPALIVE flag in the DPSESSIONDESC2 structure if the application needs DirectPlay to detect when players drop out of the game abnormally.
  11. Update your application to create sessions with the DPSESSION_MIGRATEHOST flag. This enables another computer to become the host if the current host drops out of the session. If your application has any special code that only the host runs, then your application should set this flag when it creates a session. It should also add support for the DPSYS_HOST system message. For a list of system messages, see Using system messages.
  12. Become familiar with the new methods of the IDirectPlay4 interface and use them in your application. You might be able to substitute the code where you broadcast player state information to all the other players by using the IDirectPlay4::SendEx and IDirectPlay4::Receive methods.

Debugging DirectPlay Applications

The Debug versions of the DirectPlay DLLs provide debugging output that can be very useful in tracking down the cause of errors DirectPlay might return to your application. Because the debug DLLs perform extra debugging checks at run time, they should always be used during product development. However, in addition to installing the debug DLLs, you need to take additional steps to see DirectPlay's debugging output.

  1. Install the DLLs from the Debug directory of the DirectX SDK.
  2. Run SYSEDIT.EXE.
  3. Select the WIN.INI window.
  4. Insert the following text at the beginning of the WIN.INI file:
    [DirectPlay]
Debug=8
BreakOnAssert=0
  5. Close the SYSEDIT window, and select Yes when it asks you if you want to save your changes.

Now, run your game as you normally would from within your debugger (usually Microsoft Visual C++). If you have performed these steps correctly, you will see various messages printed in the Debug pane of the Output window, as DirectPlay logs what is happening internally.

Here is an example of the output DPLAY provides.

DIRECTPLAY :: DPLAYX.DLL - version = 4.05.02.0001

DIRECTPLAY ::====> ENTER: DLLMAIN(7006a430): Process Attach: fff96a6b, tid=fff965bf
DIRECTPLAY ::Platform detected as non-NT -- setting flag to ANSI
DIRECTPLAY ::got path = C:\WINDOWS\SYSTEM\dpmodemx.dll

DIRECTPLAY ::got guid = {0F1D6860-88D9-11cf-9C4E-00A0C905425E}

DIRECTPLAY ::Could not read description err = 2

DIRECTPLAY ::got dwReserved1 = 0

DIRECTPLAY ::got dwReserved2 = 0

DIRECTPLAY ::got path = C:\WINDOWS\SYSTEM\dpmodemx.dll

DIRECTPLAY ::got guid = {44EAA760-CB68-11cf-9C4E-00A0C905425E}

DIRECTPLAY ::Could not read description err = 2

DIRECTPLAY ::got dwReserved1 = 0

DIRECTPLAY ::got dwReserved2 = 0

DIRECTPLAY ::got path = C:\WINDOWS\SYSTEM\dpwsockx.dll

DIRECTPLAY ::got guid = {36E95EE0-8577-11cf-960C-0080C7534E82}

DIRECTPLAY ::Could not read description err = 2

DIRECTPLAY ::got dwReserved1 = 500

DIRECTPLAY ::got dwReserved2 = 0

DIRECTPLAY ::got path = C:\WINDOWS\SYSTEM\dpwsockx.dll

DIRECTPLAY ::got guid = {685BC400-9D2C-11cf-A9CD-00AA006886E3}

DIRECTPLAY ::Could not read description err = 2

DIRECTPLAY ::got dwReserved1 = 50

DIRECTPLAY ::got dwReserved2 = 0

By changing the value of Debug in WIN.INI, you can vary the amount of information DirectPlay gives you. The value can be any number from 0 to 9. A value of 0 will tell DirectPlay to log very little; only information about severe errors will be reported. A value of 9 will log every detail of what's happening inside the DirectPlay DLL. As the value is increased, more and more information is logged. In the example above, Debug was set to 8. For normal operation, when you are not specifically debugging a DirectPlay-related issue, it should be set to 0.

Increasing the value of Debug from 0 to 9 can introduce subtle timing changes in your games, so, for example, bugs that appear at level 0 may not be available at level 7.

The BreakOnAssert field can be set to 0 or 1. A value of 0 means you do not want DirectPlay to throw an exception if an internal assertion fails. A value of 1 means you want DirectPlay to throw an exception (and thereby break into the debugger).

Security and Authentication

DirectPlay security allows an application running on a server to authenticate users against a database of known users before allowing them to join a session. Once a user has been authenticated, all communications between the client and server can be done securely either by digitally signing messages (to verify the identity of the sender) or by encrypting the messages.

The following diagram shows DirectPlay security architecture. (SSPI = Security Support Provider Interface, CAPI = CryptoAPI, MS RSA Base CP = Microsoft RSA Base Cryptographic Provider, NTLM = NT LAN Manager.)

DirectPlay security architecture

User and Message Authentication

DirectPlay provides user and message authentication (digital signing) support through the Windows® Security Support Provider Interface (SSPI). This is a standard interface that gives software access to various security packages under the Windows operating system. A security package is an implementation of a protocol between a client and server that establishes the identity of the client and provides other security services, such as digital signing. The default security package that DirectPlay uses is called NTLM (Windows® NT® LAN Manager) Security Support Provider.

This security package is based on the NTLM authentication protocol. NTLM is a shared-secret, user challenge-response authentication protocol that supports pass-through authentication to a domain controller in the server's domain or in a domain trusted by the current domain's domain controller. This protocol provides a high level of security because passwords are never sent out on the network. NTLMSSP ships with the Windows 95 and Windows NT operating systems.

A DirectPlay application can choose to use a different SSPI security package when it creates a session by calling the SecureOpen method. For example, DPA (Distributed Password Authentication) Security Support Provider is another security package that organizations can use to provide membership services to a large customer base (hundreds of thousands). This security package is available through the Microsoft Commercial Internet Services (MCIS) Membership Server.

Message Privacy (encryption/decryption)

DirectPlay provides message encryption support through the Windows Cryptography Application Programming Interface (CAPI). This is a standard interface similar to SSPI that gives software access to various cryptographic packages under the Windows operating system. This architecture allows DirectPlay applications to plug in cryptographic packages that provide the desired level of encryption (40 bit, 128 bit, and so on) legally allowed in the locale of use.

The default CryptoAPI (CAPI) provider for DirectPlay cryptography services is the Microsoft RSA Base Cryptographic Provider version 1.0. The default CAPI provider type is PROV_RSA_FULL. The default encryption algorithm is the CALG_RC4 stream cipher. This provider is supplied by Microsoft and is included with Microsoft Internet Explorer for Windows 95, Windows 95 OSR-2 Update, and Windows NT 4.0 operating system.

A DirectPlay application can choose to use a different cryptographic provider when it creates a session by using the SecureOpen method. Please note that DirectPlay only supports stream ciphers.

For more information about SSPI, NTLM, DPA, MCIS, CAPI, and the RSA Base Cryptographic Provider, see http://www.microsoft.com.

Secure Sessions

User authentication should not be confused with password protection of a session. Authentication is used to verify that the user is allowed access to the server by virtue of having been added to the membership database by the administrator of the server. Only users that are part of the membership database are permitted to join the session. A password can be added to a session, so that only those members who know the password can join a particular session. Additionally, authentication requires a server that supports authentication, while any computer can put a password on a session.

For example, a server on the Internet might have a membership of a thousand users. Anybody can enumerate the sessions that are available on the server, but only members will be able to join sessions on the server. Users who want only their friends (who are members) to be able to join can put a password on their session.

Once a secure server has been set up and an initial membership list has been established, a secure DirectPlay session can be started. Creating a secure DirectPlay session simply requires the server to create a session using IDirectPlay4::Open or IDirectPlay4::SecureOpen and to specify the DPSESSION_SECURESERVER flag in the DPSESSIONDESC2 structure.

A DirectPlay application can choose to use alternate providers when it creates a session by calling the SecureOpen method and specifying the providers to use in the DPSECURITYDESC structure. For a different SSPI provider (for user and message authentication), an application needs to specify the provider name in the lpszSSPIProvider member of the DPSECURITYDESC structure. For a different CryptoAPI provider (for message privacy), an application needs to specify the provider name, provider type, and encryption algorithm in the lpszCAPIProvider, dwCAPIProviderType, and dwEncryptionAlgorithm members, respectively.

When a client enumerates this session, the DPSESSIONDESC2 structure returned by IDirectPlay4::EnumSessions will have the DPSESSION_SECURESERVER flag set. This tells the client that authentication credentials will be required to join the session. If the client attempts to join the session using IDirectPlay4::Open, the security package may allow the user in if the user's credentials were already established through a system log on (for example, through NT LAN Manager). Otherwise, a DPERR_LOGONDENIED error is returned. The application must then collect credentials from the user, put them in a DPCREDENTIALS structure, and try to join the session again by calling SecureOpen, passing in the DPCREDENTIALS structure. SecureOpen is recommended for security.

Within a secure session, all DirectPlay system messages are digitally signed to verify the identity of the sender. Certain system messages that carry sensitive information are encrypted. System messages that originate from one player and need to be broadcast to all the other players in the session are first sent to the server. The server then puts its signature on the message and forwards the message to all the other computers in the session. Player to player messages are not signed by default and are not routed through the server.

An application can choose to sign or encrypt specific player-to-player messages using the DPSEND_SIGNED and DPSEND_ENCRYPTED flags in the IDirectPlay4::Send method. Signed and encrypted player messages are routed through the server and delivered as secure system messages. When a secure message is received by a player, the message will contain flags indicating whether the message came in signed or encrypted. Messages that do not pass the verification are dropped.


DirectPlay Tools and Samples

The following samples show how to use DirectPlay. These DirectPlay samples are included on the DirectX 6.0 CD-ROM. The Control Panel tool can be used to find out about DirectPlay applications. The DPSim tool can be used to test your DirectPlay applications.

  • DirectX Control Panel Tool
  • DPSim Simulation Service Provider Tool
  • Lobby Server Application
  • Bellhop Sample
  • DPChat Sample
  • DPLaunch Sample
  • DPSlots Sample
  • Duel Sample
  • Override Sample

DirectX Control Panel Tool

  • Found in Control Panel. Double-click to open the DirectX Properties dialog box.
  • The DirectPlay tab displays all the registered DirectPlay service providers and applications.
  • Open the DirectX Properties dialog box before starting a DirectPlay application to see on-the-fly statistics about DirectPlay communications such as bytes per second and messages per second.

DPSim Simulation Service Provider Tool

  • Found in Mssdk\Samples\Multimedia\DPlay\bin\DPSim.dll. The tool to configure DPSim is found in Mssdk\Samples\Multimedia\DPlay\bin\DPSimCfg.exe. The DPSim.dll needs to be copied to Windows' system directory (system32 on Windows NT).

DPSim provides a test and simulation environment for testing DirectPlay applications. It has two areas of functionality. It can simulate low bandwidth or high latency connections over a high-speed local area network and can generate random or programmed message transmission failures.

You can enter and edit the parameters that control DPSim, which are stored in the registry, by using the Configuration Manager, DPSimCfg.exe.

Using DPSim

DPSimCfg.exe is used to configure the registry parameters used by DPSim and to activate or deactivate it by adding or removing the Simulator Service Provider registry entry. When active, the Simulator Service Provider can be selected from the list of Service Providers. DPSim is implemented over the TCP/IP Service Provider.

There are four ways to drop message packets being sent to simulate communication failures.

  1. A certain percentage of the packets can be randomly dropped.
  2. Every Nth packet can be dropped.
  3. You can use a defined pattern, for example, number packets passed, number packets dropped, number passed, number dropped, and so on. The pattern is series of numeric values separated by a comma or a space. The pattern will repeat itself when the end of the sequence is reached.
  4. No packets are dropped.

Packet dropping can be specified not to occur until a certain period (in milliseconds) after communication starts, and it can be specified to last for a certain period ( in milliseconds). These periods are defined with the Start After and Stop After parameters. If Stop After is zero, packet dropping will continue indefinitely.

A check box exists for dropping guaranteed messages.

A latency (in milliseconds) can be added to both sent messages and received messages. Each latency can also have a +/- variance range, evenly distributed.

Instead of a latency, a simulated bandwidth can also be specified for both sending and receiving.

Note that for fine adjustment of the slider controls, you can click on the slider controls and use the arrow keys to increase or decrease the value.

Lobby Server Application

  • Found in Mssdk\Samples\Multimedia\DPlay\bin\LServer.exe.
  • Provides the functionality to establish a multiplayer DirectPlay session.

Using the Lobby Server Application

To initialize the lobby server in its default mode, select the Server menu, and choose Start. The lobby server will create several default top-level groups. Users will only be allowed to create sub-groups within the top-level groups, staging areas, or shortcuts to staging areas.

For your convenience, the lobby server application also provides a test mode in which no top level groups are automatically created. Users are free to create any group hierarchy they want, to any depth. If you want to set the lobby server into test mode, you must do so before you select Start from the Server menu. To set the lobby server into test mode, select Server from the lobby application's main menu. Choose Test Mode from the Server menu. You can now start the lobby server in test mode by choosing Start from the Server menu.

If you choose Secure Mode in the Server menu before selecting Start and the lobby server running on Windows NT 4.0 or later, the lobby server will require clients to login.

The lobby server will ask which service provider to use. All clients connecting to the server will need to select this same service provider. You will then be asked to provide a name for the lobby server session.

Bellhop Sample

  • Sources found in Mssdk\Samples\Multimedia\DPlay\Bellhop. Executable found in Mssdk\Samples\Multimedia\DPlay\bin\Bellhop.exe.
  • A lobby client program that uses the IDirectPlay4 interface to communicate with a lobby server.
  • Uses the LServer test lobby server so that a real lobby client/server environment can be set up. The lobby server application must be running for Bellhop to work. When users run Bellhop, you are presented with virtual environment in which you can meet others, begin games with them, and join in games that are already running.
  • Bellhop can be used to test external lobby support in your application.
  • LServer can be used as a test server to write your own lobby client or integrate a lobby client into your application.

Using Bellhop

After launching bellhop, you will be asked to select a lobby provider. This is the lobby server application installed as part of the SDK. It must be running before Bellhop is started. If the lobby provider is running, choose Lobby Connection for DirectPlay.

You will then be presented with a dialog asking you to select a service provider. The sample lobby server and lobby provider are capable of operating over any network supported by DirectPlay. Select an appropriate service provider (such as TCP/IP), and choose OK.

With a TCP/IP connection, you will be prompted for the address of the lobby server. You can leave this blank to try to find the address on your local network. Alternatively, you can enter the computer name or IP address. When the lobby server name is displayed, join it.

You will be presented with a player character that represents you in the virtual gaming environment. To move your player from doorway to doorway, double-click the doorway you wish to enter. You can also drag and drop the icon representing your player to the doorway.

You will only see the contents of rooms that you have joined. Once you leave a room, all the doorways and players in that room will disappear.

Bellhop provides context-sensitive menus. If you right click on a player or group, the Bellhop program will display the options available for that specific item. If you right click on the background, you can choose to refresh its display. Bellhop will re-enumerate all the groups and players that are available to you.

When you want to create a sub-folder or staging area in an existing folder, right-click the folder. In the menu that appears, select Create Group In Group. If you choose to create a staging area, you will need to select which game to play from the listbox. Bellhop will only list applications that are registered with DirectPlay. Any other applications that may be running on the network are ignored. In addition to selecting a game, you must choose which connection will be used to launch the game. You can optionally specify a password for the session and the maximum number of players.

If you want to join a staging area, you can right click on its icon and select Get Group Connection Settings in the menu that appears. Bellhop will show you properties of the staging area. You can modify these settings using Set Group Connection Settings.

To start a game from a staging area, right click on the staging area icon and select Start Session. This will launch the application on the machines of all the people in the staging area and connect them together in a session. If you move into the staging area after the session has started, select Start Session to join the session in progress. If the session is in progress, the icon will change from a green triangle to a red and black triangle.

You can create a shortcut to a room by dragging and dropping one doorway on top of another. The icon will appear as a doorway surrounded by a magic portal.

To change the name of local groups or players, right-click the group or player and select Set Group Name in the menu that is displayed. When you do, another menu appears. Choose Set Player Name. Alternately you can single click on the text of the group or player name.

Spectators within the lobby are treated the same as players.

There is optional support for allowing players in multiple rooms simultaneously. To enable it, uncomment the code in the CreatePlayer section of CGroupTree and rebuild. For every player created, a player is added to the root of the tree control. You can enter simultaneous rooms by dragging the player icon from the top level onto a doorway.

DPChat Sample

  • Sources found in Mssdk\Samples\Multimedia\DPlay\DPChat. Executable found in Mssdk\Samples\Multimedia\DPlay\bin\DPChat.exe.
  • A simple Windows-based chat program that uses IDirectPlay4 to establish a chat session over the network.
  • Uses IDirectPlayLobby3 to make it lobby-able.

Using DPChat

Use either the DPLaunch or Bellhop application to run DPChat. You can start a new chat session or connect to one already in progress.

DPLaunch Sample

  • Sources found in Mssdk\Samples\Multimedia\DPlay\DPLaunch. Executable found in Mssdk\Samples\Multimedia\DPlay\bin\DPLaunch.exe.
  • A stand-alone application that demonstrates how a DirectPlay 6.0 application can be launched from an external source using the IDirectPlayLobby3 interface.
  • Can also be used to test the lobby support in your application.

Using DPLaunch

When you run it, DPLaunch presents you with a pull-down list of all registered DirectPlay applications on your computer. Once you choose which application to start, you must also select the connection method, and specify your player name. In addition, you need to pick a session name, and specify whether you are joining an existing session or creating a new one. If you know the IP address of a computer hosing a DirectPlay session, you can specify that as well.

DPSlots Sample

  • Sources found in Mssdk\Samples\Multimedia\DPlay\DPSlots. Executable found in Mssdk\Samples\Multimedia\DPlay\bin\DPSlots.exe.
  • A DirectPlay client/server application that simulates a slot machine and uses security.
  • The server controls all the slot machines and tracks how much money each player has.
  • The client securely logs in to the server.

Using DPSlots

DPSlots is really two applications in one. When you host a session, it acts as a server. When you join a session, it acts as a client.

The server maintains a simple database of account balances for every user that is allowed to log in. Clients can request their current balance from the server. They can also request that the server spin the wheels and calculate the amount won or lost. The server maintains a simple text file "database" called Slotsdb.txt. The DPSlots program uses this file to record the balance for each user. Each line of the text file contains the user account ID and a 8-character balance figure separated by a comma, as shown in the following example.

Account1,    1000
Account2,     500

You need to add lines manually to this file for each user.

When you join a session, DPSlots acts as a client and sends messages to the server for all operations. After requesting a spin from the server, it animates the tumblers and displays the results. The client can be required to log the user into the server using a name and password.

DPSlots can be hosted using security by clicking the Require Secure Login checkbox after choosing to host. By leaving the Security Provider editbox blank the default NTLM security package will be used. If you have an alternate SSPI security package installed, it can be specified here.

Once you have a security provider, the server will host a secure session. Clients will have to securely log in with a user name and a password before being allowed access the session on the server. All messages between the client and server will be digitally signed and encrypted.

When hosting a secure server, the account ID for each user will be defined by the security package being used. This account ID must be stored in the database file along with the appropriate balance. The default security package is NTLM, which uses a domain and a user name for the account ID. If, for example, you use NTLM, your domain is "GAMES", and you have two users "Bob" and "Jane", your database file would be as shown in the following example.

GAMES/Bob,    1000
GAMES/Jane,     500

Currently you can only host a secure session using NTLM on a Windows NT workstation or server. However, you can log into the server from Windows 95 or Windows NT.

Duel Sample

  • Sources found in Mssdk\Samples\Multimedia\DPlay\Duel. Executable found in Mssdk\Samples\Multimedia\DPlay\bin\Duel.exe.
  • A multiplayer game that uses the IDirectPlay interface.
  • Uses IDirectPlayLobby to make it lobby-able.
  • Demonstrates the use of DirectDraw for animation, the use of DirectInput for obtaining keyboard input, and the use of DirectSound for generating sound effects in games.

Using Duel

Your computer must be connected to the network for Duel to work. When you launch the application, you can chose to host a new game or join an existing game. When the program displays its splash screen, press the Enter key to begin playing.

All players in the game are represented by a small space ship in an asteroid field. Use the left and right arrows to turn the ship left and right. The up arrow accelerates your ship forward. The down arrow accelerates it backward. Press the space bar to fire. To exit the game, press Esc or F12.

To play using TCP/IP over the Internet, the people who are joining the game must enter the IP address of the machine that hosted the game. You can find out the IP address of your machine by running the Winipcfg utility that comes with Windows 9x and Windows NT. If you have a network card and a modem installed, you will need to make sure you read the IP address of the modem connection to the Internet. The modem will show up as a PPP Adapter. This game will not work through proxies or firewalls.

Override Sample

  • Sources found in Mssdk\Samples\Multimedia\DPlay\Override. Executable found in Mssdk\Samples\Multimedia\DPlay\bin\Override.exe.
  • A simple demonstration of how to override the DirectPlay service provider dialogs.

Using Override

When the program begins, select a service provider. Once you make your selection, the application displays a custom dialog box that it creates to collect the information needed for that service provider. If you select an unknown service provider, then the service provider's dialog cannot be overridden and the Override application simply displays the default dialog box.

Once the service provider information has been collected from the user, it must be formatted into a DirectPlay Address. This can be used to initialize the service provider.

The IDirectPlay4::EnumSessions and IDirectPlay4::Open methods must be called with the dwFlags parameter set to the value DPENUMSESSIONS_RETURNSTATUS. This will suppress any status dialogs that may pop up to show to progress of the connection.


DirectPlay Interface Overviews

DirectPlay is composed of objects and interfaces based on the component object model (COM). COM is a foundation for an object-based system that focuses on the reuse of interfaces, and it is the model at the heart of OLE programming. It is also an interface specification from which any number of interfaces can be built.

New methods and functionality are exposed in COM through the use of new interfaces that are sequentially numbered. The current DirectPlay interface is called IDirectPlay4. The old interfaces, IDirectPlay and IDirectPlay2, still exist for backward compatibility with applications written to those interfaces.

This section contains general information about the following DirectPlay COM interfaces:

  • Unicode vs. ANSI Interfaces
  • IDirectPlay and IDirectPlay2 Interfaces
  • IDirectPlay3 Interface
  • IDirectPlay4 Interface
  • IDirectPlayLobby and IDirectPlayLobby2 Interfaces
  • IDirectPlayLobby3 Interface

Unicode vs. ANSI Interfaces

DirectPlay supports both Unicode and ANSI strings by defining string pointers in a structure as the union of a Unicode string pointer (LPWSTR) and an ANSI string pointer (LPSTR). The two string pointers have different names. Typically, the ANSI member ends with the letter "A". Depending on which IDirectPlay interface is chosen (IDirectPlay4 Interface for Unicode or IDirectPlay4A for ANSI), or which IDirectPlayLobby3 interface is chosen (IDirectPlayLobby3 Interface for Unicode or IDirectPlayLobby3A for ANSI), the application should read and write the appropriate strings from the structure and ignore the other one.

IDirectPlay and IDirectPlay2 Interfaces

The IDirectPlay and IDirectPlay2 COM interfaces remain part of DirectPlay version 6. IDirectPlay contains the methods required to run applications that were written for the DirectX SDK versions 1 and 2. IDirectPlay2 contains the methods required to run applications that were written for the DirectX SDK version 3. Although you could use this interface to create new applications, it is recommended that you use the newer DirectPlay interfaces, IDirectPlay4 Interface and IDirectPlay4A, to take advantage of their increased functionality.

IDirectPlay3 Interface

The IDirectPlay3 COM interface remains part of DirectPlay version 6. It contains the methods required to run applications that were written for the DirectX SDK version 5. Although you could use this interface to create new applications, it is recommended that you use the newer DirectPlay interfaces, IDirectPlay4 Interface and IDirectPlay4A, to take advantage of their increased functionality.

IDirectPlay4 Interface

IDirectPlay4 is the latest interface. It directly inherits from IDirectPlay3, so any code written for IDirectPlay3 will work with IDirectPlay4 with no modification.

The new methods in IDirectPlay4 are:

  • CancelMessage
  • CancelPriority
  • GetGroupOwner
  • GetMessageQueue
  • SendEx
  • SetGroupOwner

IDirectPlayLobby and IDirectPlayLobby2 Interfaces

The IDirectPlayLobby and IDirectPlayLobby2 COM interfaces remain part of DirectPlay version 6. IDirectPlayLobby contains the methods required to run applications that were written for the DirectX SDK versions 1, 2, and 3. IDirectPlayLobby2 contains the methods required to run applications that were written for the DirectX SDK version 5. Although you could use these interfaces to create new applications, it is recommended that you use the newer DirectPlay interface, IDirectPlayLobby3 Interface, to take advantage of its increased functionality.

IDirectPlayLobby3 Interface

The IDirectPlayLobby3 Interface interface lets game developers launch external applications, enable communication between an application and a lobby client, and manipulate DirectPlay Addresses.

IDirectPlayLobby3 supports all the methods of IDirectPlayLobby and IDirectPlayLobby2. See Building Lobby-Aware Applications for information about detecting a launch by an external lobby and registering lobby-aware applications. See DirectPlay Lobby Overview for general information about lobby sessions.

The new methods in IDirectPlayLobby3 are:

  • ConnectEx
  • RegisterApplication
  • UnregisterApplication
  • WaitForConnectionSettings


DirectPlay Tutorials

This section contains four tutorials that provide step-by-step instructions about how to connect an application with or without a lobby, how to override service provider dialog boxes, and how to create a self-refreshing session list.

The first tutorial demonstrates how to connect an application by using a DirectPlay lobby.

The second tutorial demonstrates how to connect an application by using a dialog box that queries the user for connection information. You should write your application so that it can start by using either method. The code is available in the DPCHAT sample in the LOBBY.CPP and DIALOG.CPP files.

The third tutorial demonstrates the calls you need to supply the service provider with all the information it needs so that it doesn't display dialog boxes to the user requesting information.

The fourth tutorial demonstrates how to create a self-refreshing session list.

  • Tutorial 1: Connecting by Using the Lobby (DPCHAT)
  • Tutorial 2: Connecting by Using a Dialog Box (DPCHAT)
  • Tutorial 3: Overriding the Service Provider Dialogs
  • Tutorial 4: Creating Self-Refreshing Session Lists

Note The sample files in these tutorials are written in C++. If you are using a C compiler, you must make the appropriate changes to the files for them to successfully compile. At the very least, you must add the vtables and this pointers to the interface methods. For more information, see Accessing COM in the DirectX Foundation Software Development Kit.

Tutorial 1: Connecting by Using the Lobby

An application written to use the IDirectPlayLobby3 interface can be connected to a session without requiring the user to manually enter connection information in a dialog box. To demonstrate how to create a lobbied application, the DPCHAT sample performs the following steps:

  • Step 1: Creating a DirectPlayLobby Object
  • Step 2: Retrieving the Connection Settings
  • Step 3: Configuring the session Description
  • Step 4: Connecting to a Session
  • Step 5: Creating a Player

Step 1: Creating a DirectPlayLobby Object

To use a DirectPlay lobby, you first create an instance of a DirectPlayLobby object by calling CoCreateInstance. The following example shows one way to create a DirectPlayLobby object:

// Create an IDirectPlayLobby3A interface
hr = CoCreateInstance( CLSID_DirectPlayLobby, NULL, CLSCTX_INPROC_SERVER,
                       IID_IDirectPlayLobby3A, (LPVOID*)&lpDirectPlayLobby3A);
if ( FAILED(hr) )
  goto FAILURE;

Step 2: Retrieving the Connection Settings

After the DirectPlayLobby object has been created, use the IDirectPlayLobby3::GetConnectionSettings method to retrieve the connection settings returned from the lobby. If this method returns DPERR_NOTLOBBIED, the lobby did not start this application, and the user will have to configure the connection manually. If any other error occurs, your application should report an error that indicates that lobbying the application failed.

The following example shows how to retrieve the connection settings:

// Retrieve the connection settings from the lobby.
// If this routine returns DPERR_NOTLOBBIED, then a lobby did not
// start this application and the user needs to configure the
// connection.

// Pass a NULL pointer to retrieve only the size of the
// connection settings
hr = lpDirectPlayLobbyA->GetConnectionSettings(0, NULL, &dwSize);
if (DPERR_BUFFERTOOSMALL != hr)
    goto FAILURE;

// Allocate memory for the connection settings.
lpConnectionSettings = (LPDPLCONNECTION) GlobalAllocPtr(GHND, dwSize);
    if (NULL == lpConnectionSettings)
    {
        hr = DPERR_OUTOFMEMORY;
        goto FAILURE;
    }

    // Retrieve the connection settings.
    hr = lpDirectPlayLobbyA->GetConnectionSettings(0,
        lpConnectionSettings, &dwSize);
    if FAILED(hr)
        goto FAILURE;

Step 3: Configuring the session Description

You should examine the DPSESSIONDESC2 structure to ensure that all the flags and properties that your application needs are set properly. If modifications are necessary, store the modified connection settings by using the IDirectPlayLobby3::SetConnectionSettings method.

The following example shows how to configure the session description and set the connection settings:

// Before the game connects, it should configure the session
// description with any settings it needs.

// Set the flags and maximum players used by the game.
lpConnectionSettings->lpSessionDesc->dwFlags = DPSESSION_MIGRATEHOST |
    DPSESSION_KEEPALIVE;
lpConnectionSettings->lpSessionDesc->dwMaxPlayers = MAXPLAYERS;

// Store the updated connection settings.
hr = lpDirectPlayLobbyA->SetConnectionSettings(0, 0,
        lpConnectionSettings);
if FAILED(hr)
    goto FAILURE;

Step 4: Connecting to a Session

After the session description is properly configured, your application can use the IDirectPlayLobby3::ConnectEx method to start and connect itself to a session. If this method returns DP_OK, you can create one or more players. If it returns DPERR_NOTLOBBIED, the user will have to manually select a communication medium for your application. (You can identify the service providers installed on the system by using the IDirectPlay4::EnumConnections function.) If any other error value is returned, your application should report an error that indicates that lobbying the application failed.

The following example shows how to connect to a session:

// Connect to the session. Returns an ANSI IDirectPlay4A interface.
hr = lpDirectPlayLobby3A->ConnectEx(0, IID_IDirectPlay4A, &lplpDP, NULL);
if FAILED(hr)
    goto FAILURE;

Step 5: Creating a Player

If the application was successfully started by using the IDirectPlayLobby3::ConnectEx method, it can now create one or more players. It can use the IDirectPlay4::CreatePlayer method to create a player with the name specified in the DPNAME structure (which was filled in by the IDirectPlayLobby3::GetConnectionSettings method).

The following example shows how to create a player:

// create a player with the name returned in the connection settings
hr = lpDirectPlay3A->CreatePlayer(&dpidPlayer,
                                      lpConnectionSettings->lpPlayerName,
                                      lpDPInfo->hPlayerEvent, NULL, 0, 0);
if FAILED(hr)
    goto FAILURE;

Now your application is connected and you are ready to play.

Tutorial 2: Connecting by Using a Dialog Box

If a lobby did not start your application, you should include code that allows the user to manually enter the connection information. To demonstrate how to manually connect to the session and create one or more players, the DPCHAT sample performs the following steps:

  • Step 1: Creating the DirectPlay Object
  • Step 2: Enumerating and Initializing the Service Providers
  • Step 3: Joining a Session
  • Step 4: Creating a Session
  • Step 5: Creating a Player

Step 1: Creating the DirectPlay Object

Before any methods can be called, the application must create an interface to a DirectPlay object.

The following example shows how the create the IDirectPlay4A interface:

HRESULT CreateDirectPlayInterface( LPDIRECTPLAY4A *lplpDirectPlay4A )
{
   // Create an IDirectPlay4 interface
   return CoCreateInstance( CLSID_DirectPlay, NULL, CLSCTX_INPROC_SERVER,
                            IID_IDirectPlay4A, (LPVOID*)&lpDirectPlay4A);
}

Step 2: Enumerating and Initializing the Service Providers

The next step in creating a manual connection is to request that the user select a communication medium for the application. Your application can identify the service providers installed on a personal computer by using the EnumConnections method.

The following example shows how to enumerate the service providers:

lpDirectPlay3A->EnumConnections(&DPCHAT_GUID,
                                         DirectPlayEnumConnectionsCallback, hWnd, 0);

The second parameter in the EnumConnections method is a callback that enumerates service providers registered with DirectPlay. The following example shows one possible way of implementing this callback function:

BOOL FAR PASCAL DirectPlayEnumConnectionsCallback(
     LPCGUID lpguidSP, LPVOID lpConnection, DWORD dwConnectionSize,
     LPCDPNAME lpName, DWORD dwFlags, LPVOID lpContext)
{
   HWND     hWnd = (HWND) lpContext;
   LRESULT	iIndex;
   LPVOID   lpConnectionBuffer;

   // Store service provider name in combo box
   iIndex = SendDlgItemMessage(hWnd, IDC_SPCOMBO, CB_ADDSTRING, 0,
       (LPARAM) lpName->lpszShortNameA);
   if (iIndex == CB_ERR)
     goto FAILURE;

   // make space for connection
   lpConnectionBuffer = GlobalAllocPtr(GHND, dwConnectionSize);
   if (lpConnectionBuffer == NULL)
     goto FAILURE;

   // Store pointer to connection  in combo box
   memcpy(lpConnectionBuffer, lpConnection, dwConnectionSize);
   SendDlgItemMessage(hWnd, IDC_SPCOMBO, CB_SETITEMDATA, (WPARAM) iIndex,
       (LPARAM) lpConnectionBuffer);

FAILURE:
    return (TRUE);
}

Once the user selects which connection to use, you need to retrieve the connection data that comes back with the enumeration, and initialize the DirectPlay object with this data.

hr = lpDirectPlay4A->InitializeConnection(lpConnection, 0);

Step 3: Joining a Session

If the user wants to join an existing session, enumerate the available sessions by using the IDirectPlay4::EnumSessions method, present the choices to the user, and then connect to that session by using the IDirectPlay4::Open method, specifying the DPOPEN_JOIN flag. The service provider might display a dialog box requesting some information from the user before it can enumerate the sessions.

See Tutorial 4 for details on the asynchronous EnumSessions functionality.

The following example shows how to enumerate the available sessions:

// Search for this kind of session.
ZeroMemory(&sessionDesc, sizeof(DPSESSIONDESC2));
sessionDesc.dwSize = sizeof(DPSESSIONDESC2);
sessionDesc.guidApplication = DPCHAT_GUID;

hr = lpDirectPlay4A->EnumSessions(&sessionDesc, 0, EnumSessionsCallback,
    hWnd, DPENUMSESSIONS_AVAILABLE);
if FAILED(hr)
    goto FAILURE;

In the previous example, the third parameter in the IDirectPlay4A::EnumSessions method is a callback that enumerates the available sessions. The following example shows one way to implement this callback function:

BOOL FAR PASCAL EnumSessionsCallback(
    LPCDPSESSIONDESC2 lpSessionDesc, LPDWORD lpdwTimeOut,
    DWORD dwFlags, LPVOID lpContext)
{
HWND   hWnd = lpContext;
LPGUID lpGuid;
LONG   iIndex;

// Determine if the enumeration has timed out.
if (dwFlags & DPESC_TIMEDOUT)
    return (FALSE);            // Do not try again

// Store the session name in the list.
iIndex = SendDlgItemMessage(hWnd, IDC_SESSIONLIST, LB_ADDSTRING,
    (WPARAM) 0, (LPARAM) lpSessionDesc->lpszSessionNameA);
if (iIndex == CB_ERR)
    goto FAILURE;

// Make space for the session instance GUID.
lpGuid = (LPGUID) GlobalAllocPtr(GHND, sizeof(GUID));
if (lpGuid == NULL)
    goto FAILURE;

// Store the pointer to the GUID in the list.
*lpGuid = lpSessionDesc->guidInstance;
SendDlgItemMessage(hWnd, IDC_SESSIONLIST, LB_SETITEMDATA,
    (WPARAM) iIndex, (LPARAM) lpGuid);

FAILURE:
    return (TRUE);
}

After the user has selected a session, your application can allow the user to join an existing session. The following example shows how to join an existing session:

// Join an existing session.
ZeroMemory(&sessionDesc, sizeof(DPSESSIONDESC2));
sessionDesc.dwSize = sizeof(DPSESSIONDESC2);
sessionDesc.guidInstance = *lpguidSessionInstance;

hr = lpDirectPlay4A->Open(&sessionDesc, DPOPEN_JOIN);
if FAILED(hr)
    goto OPEN_FAILURE;

Step 4: Creating a Session

If the user wants to create a new session, your application can create it by using the IDirectPlay4::Open method and specifying the DPOPEN_CREATE flag. Again, the service provider might display a dialog box requesting information from the user before it can create the session.

The following example shows how to create a new session:

// Host a new session.
ZeroMemory(&sessionDesc, sizeof(DPSESSIONDESC2));
sessionDesc.dwSize = sizeof(DPSESSIONDESC2);
sessionDesc.dwFlags = DPSESSION_MIGRATEHOST | DPSESSION_KEEPALIVE;
sessionDesc.guidApplication = DPCHAT_GUID;
sessionDesc.dwMaxPlayers = MAXPLAYERS;
sessionDesc.lpszSessionNameA = lpszSessionName;

hr = lpDirectPlay3A->Open(&sessionDesc, DPOPEN_CREATE);
if FAILED(hr)
    goto OPEN_FAILURE;

Step 5: Creating a Player

After a session has been created or joined, your application can create one or more players by using the IDirectPlay4::CreatePlayer method. The following example shows one way to create a player:

// Fill out the name structure.
ZeroMemory(&dpName, sizeof(DPNAME));
dpName.dwSize = sizeof(DPNAME);
dpName.lpszShortNameA = lpszPlayerName;
dpName.lpszLongNameA = NULL;

// Create a player with this name.
hr = lpDirectPlay3A->CreatePlayer(&dpidPlayer, &dpName,
    lpDPInfo->hPlayerEvent, NULL, 0, 0);
if FAILED(hr)
    goto CREATEPLAYER_FAILURE;

Your application can determine a player's communication capabilities by using the IDirectPlay4::GetCaps and IDirectPlay4::GetPlayerCaps methods. Your application can find other players by using the IDirectPlay4::EnumPlayers method.

Now your application is connected and you are ready to play.

Tutorial 3: Overriding the Service Provider Dialogs

DirectPlay now gives applications the ability to suppress the standard service provider dialogs. Below is a brief outline of how this is done. A code example can be found in the OVERRIDE sample application.

It is generally not possible to suppress all service provider dialogs. The standard TCP/IP, modem, and serial service provider dialogs can be suppressed (IPX has no dialog box). However, there is the possibility that third party service providers might require fairly complex information from the user which cannot be overridden in any general way. The solution is to simply allow these dialog boxes to appear over your application user interface. If the application is a DirectDraw® full-screen application, be sure to turn off page flipping before calling IDirectPlay4::EnumSessions or IDirectPlay4::Open to create a session.

Another way to suppress service provider dialog boxes is to make your application lobby-aware. Most third party service providers will also have a lobby from which to launch games, and games launched from a lobby do not display a connection dialog box.

An application first calls IDirectPlay4::EnumConnections to see which connections are available, presents the list to the user, and allows the user to select one. Once the user has selected one, the application can attempt to override the dialog box before calling IDirectPlay4::EnumSessions or IDirectPlay4::Open.

These are the steps you should follow to suppress service provider dialog boxes:

  1. Examine the service provider GUID of the selected service provider to see if it matches one of the known service providers that the application knows how to override. If the service provider GUID is unknown, then skip the remaining steps and be prepared to allow a dialog box to appear.
  2. Display the appropriate user interface to collect the information needed from the user for that specific service provider. IPX requires no information. TCP/IP requires an IP address for EnumSessions (DPAID_INet or DPAID_INetW), but requires nothing to create a session using Open. Modem-to-modem requires the user to select a modem (DPAID_Modem or DPAID_ModemW) and also needs a phone number (DPAID_Phone or DPAID_PhoneW) when calling EnumSessions. Serial link needs the DPCOMPORTADDRESS structure (DPAID_ComPort) filled in to configure the COM port for both EnumSessions and Open.
  3. Build a DirectPlay Address using the IDirectPlayLobby3::CreateCompoundAddress method. The address elements that must be passed in are the service provider GUID (DPAID_ServiceProvider) and the individual address components for the selected service provider.
  4. Initialize the DirectPlay object by calling InitializeConnection with the DirectPlay Address.
  5. Call EnumSessions with the DPENUMSESSIONS_RETURNSTATUS flag. This will prevent any status dialog boxes from appearing and, if the connection cannot be made immediately, EnumSessions will return with a DPERR_CONNECTING error. Your application must periodically call EnumSessions until DP_OK is returned (meaning the enumeration was successful) or some other error is returned (meaning it failed).
  6. If a session is to be created using the Open method with DPOPEN_CREATE, specify the DPOPEN_RETURNSTATUS flag as well. Like DPENUMSESSIONS_RETURNSTATUS, this will suppress status dialog boxes and return DPERR_CONNECTING until the function is complete.

Note: In some cases, the application will need to query the service provider at run time to obtain a list of valid choices for a particular DirectPlay Address element. For example, to obtain a list of the modems installed in the system. The application must create a separate DirectPlay object, initialize the modem service provider, and then call IDirectPlay4::GetPlayerAddress with a DirectPlay ID of zero to obtain a DirectPlay Address that will contain the list of modems. After releasing the DirectPlay object, the application must parse the address using IDirectPlayLobby3::EnumAddress and extract the modem list to present to the user.

Tutorial 4: Creating Self-Refreshing Session Lists

IDirectPlay4::EnumSessions can be called asynchronously. This gives an application the ability to maintain a self-refreshing session list. This procedure is used in five of the DirectPlay samples, Bellhop, DPChat, DPSlots, Duel, and Override. You can find a code example in any of these sample applications.

The steps you need to follow to create a self-refreshing session list are:

  1. Call IDirectPlay4::EnumSessions with the DPENUMSESSIONS_ASYNC flag and a time-out of zero (which will use the service provider default). The method will not enumerate any sessions and will return immediately. However, DirectPlay is enumerating sessions in the background.
  2. Display the user interface in which all the sessions will appear. Set a timer to go off at whatever interval you want to refresh your session list. The application can find out what the default time-out interval of the enumeration is by calling IDirectPlay4::GetCaps.
  3. Each time the timer goes off, call EnumSessions to obtain the current session list. This is a complete active session list with stale sessions deleted, new sessions added, and existing sessions updated. Delete all the items from the list before calling EnumSessions and add the sessions back to the list in the EnumSessionsCallback2 function.
  4. Check the error result returned by EnumSessions and stop the timer if an error other than DPERR_CONNECTING is returned. It is possible for the connection to be lost or canceled by the user.


DirectPlay Reference

The DirectPlay C++/COM Reference provides detailed information about functions, callbacks, and the IDirectPlay4 and IDirectPlayLobby3 interface methods, with syntax, parameter descriptions, flag descriptions, return values, and comments about how they are used. It also describes the members of Microsoft® DirectPlay® structures, system messages, lobby messages, and defined properties, and the possible error values that can be returned.

  • Functions
  • Callback Functions
  • IDirectPlay4 Interface
  • IDirectPlayLobby3 Interface
  • Structures
  • System Messages
  • Standard Lobby Messages
  • DirectPlay Defined Properties
  • Return Values
  • Further Reading


Functions

The DirectPlay functions are:

  • DirectPlayCreate - note that this function is obsolete. It is recommended that you use CoCreateInstance instead.
  • DirectPlayEnumerate - note that this function is obsolete. It is recommended that you use IDirectPlay4::EnumConnections instead.
  • DirectPlayLobbyCreate


DirectPlayCreate

This function is obsolete and remains for compatibility with applications written using DirectX 3. It is recommended that applications create the desired DirectPlay interface directly using CoCreateInstance. By using CoCreateInstance you can obtain an IDirectPlay4 interface directly rather than getting an IDirectPlay interface, having to use QueryInterface to access an IDirectPlay4 interface, and releasing the IDirectPlay interface.

Creates a new DirectPlay object and obtains an IDirectPlay interface pointer. If the application supplies GUID_NULL for the lpGUIDSP parameter, this function creates a DirectPlay object but does not initialize a service provider. The application can then call the IDirectPlay4::InitializeConnection method to initialize the service provider or lobby provider.

The application can supply a service provider GUID (see DirectPlayEnumerate) to indicate which service provider to bind.

In order to use the latest DirectPlay functionality, the application must obtain an IDirectPlay4 or IDirectPlay4A interface pointer using the QueryInterface method.

Syntax

HRESULT WINAPI DirectPlayCreate(
  LPGUID lpGUIDSP,
  LPDIRECTPLAY FAR *lplpDP,
  IUnknown *lpUnk
  );

Parameters

lpGUIDSP
Pointer to the GUID of the service provider that the DirectPlay object should be initialized with. Pass in a pointer to GUID_NULL to create an uninitialized DirectPlay object.
lplpDP
Pointer to an interface pointer to be initialized with a valid IDirectPlay interface. The application will need to use the QueryInterface method to obtain an IDirectPlay2, IDirectPlay4 Interface (UNICODE strings) or IDirectPlay2A, IDirectPlay4A (ANSI strings) interface.
lpUnk
Pointer to the containing IUnknown. This parameter is provided for future compatibility with COM aggregation features. Presently, however, the DirectPlayCreate function returns an error if this parameter is anything but NULL.

Return Value

Returns DP_OK if successful, or one of the following error values otherwise:
CLASS_E_NOAGGREGATION
DPERR_EXCEPTION
DPERR_INVALIDPARAMS
DPERR_UNAVAILABLE

DPERR_UNAVAILABLE is returned if a DirectPlay object could not be created. DPERR_INVALIDPARAMS is returned if the GUID provided is invalid.

Remarks

This function attempts to initialize a DirectPlay object and sets a pointer to it if successful. Your application should call the DirectPlayEnumerate function immediately before initialization to determine what types of service providers are available (the DirectPlayEnumerate function fills in the lpGUIDSP parameter of DirectPlayCreate).

This function returns a pointer to an IDirectPlay interface. The current interfaces for DirectX 6 are IDirectPlay4 and IDirectPlay4A, which need to be obtained through a call to the QueryInterface method on the IDirectPlay interface returned by DirectPlayCreate.

See Also

IDirectPlay4::InitializeConnection, DirectPlayEnumerate


DirectPlayEnumerate

Enumerates the DirectPlay service providers installed on the system.

This function is obsolete and remains for compatibility with applications written using DirectX 3. It will only enumerate service providers, not DirectPlay Addresses (connections). It is recommended that applications use the IDirectPlay4::EnumConnections method to enumerate all the connections available to the application after creating an IDirectPlay4 interface.

This function will not enumerate service providers that have the Enumerate value in the registry set to zero. For backward compatibility, this function will only return simple service providers registered under the "Service Providers" registry key.

Syntax

HRESULT WINAPI DirectPlayEnumerate(
  LPDPENUMDPCALLBACK lpEnumCallback,
  LPVOID lpContext
  );

Parameters

lpEnumCallback
Pointer to a callback function that will be called with a description of each DirectPlay service provider installed in the system. Depending on whether UNICODE is defined or not, the prototype for the callback function will have the service provider name lpSPName defined as a LPWSTR (for Unicode) or LPSTR (for ANSI).
lpContext
Pointer to an application-defined structure that will be passed to the callback function each time the function is called.

Return Value

Returns DP_OK if successful, or one of the following error values otherwise:
DPERR_EXCEPTION
DPERR_GENERIC
DPERR_INVALIDPARAMS

DPERR_INVALIDPARAMS is returned if an invalid enumeration callback was supplied.

Remarks

This function will enumerate service providers installed in the system even though the system might not be capable of using those service providers. For example, a TAPI service provider will be part of the enumeration even though the system might not have a modem installed.

See Also

IDirectPlay4::EnumConnections, DirectPlayCreate


DirectPlayLobbyCreate

Creates an instance of a DirectPlayLobby object. This function attempts to initialize a DirectPlayLobby object and set a pointer to it.

Syntax

HRESULT WINAPI DirectPlayLobbyCreate(
  LPGUID lpGUIDSP,
  LPDIRECTPLAYLOBBY *lplpDPL,
  IUnknown *lpUnk,
  LPVOID lpData,
  DWORD dwDataSize
  );

Parameters

lpGUIDSP
Reserved for future use; must be set to NULL.
lplpDPL
Pointer to a pointer to be initialized with a valid IDirectPlayLobby interface. To get an IDirectPlayLobby3 interface, use this function to get an IDirectPlayLobby interface, then call:
  IDirectPlayLobby->QueryInterface( IID_IDirectPlayLobby3, (LPVOID*) &lpDP2 );
lpUnk
Pointer to the containing IUnknown interface. This parameter is provided for future compatibility with COM aggregation features. Presently, however, DirectPlayLobbyCreate returns an error if this parameter is anything but NULL.
lpData
Extra data needed to create the DirectPlayLobby object. This parameter must be set to NULL.
dwDataSize
This parameter must be set to zero.

Return Value

Returns DP_OK if successful, or one of the following error values otherwise:
CLASS_E_NOAGGREGATION
DPERR_INVALIDPARAMS
DPERR_OUTOFMEMORY


Callback Functions

The DirectPlay callback functions are:

  • EnumAddressCallback
  • EnumAddressTypeCallback
  • EnumConnectionsCallback
  • EnumDPCallback
  • EnumLocalApplicationsCallback
  • EnumPlayersCallback2
  • EnumSessionsCallback2


EnumAddressCallback

Application-defined callback function for the IDirectPlayLobby3::EnumAddress method.

Syntax

BOOL FAR PASCAL EnumAddressCallback(
  REFGUID guidDataType,
  DWORD dwDataSize,
  LPCVOID lpData,
  LPVOID lpContext
  );

Parameters

guidDataType
Pointer to a globally unique identifier (GUID) indicating the type of this data chunk. For example, this parameter might be &DPAID_Phone or &DPAID_INet. (In C++, it is a reference to the GUID.)
dwDataSize
Size, in bytes, of the data chunk.
lpData
Pointer to the constant data.
lpContext
Context passed to the callback function.

Return Value

Returns TRUE to continue the enumeration or FALSE to stop it.

Remarks

The service provider should examine the GUID in the guidDataType parameter and process or store the value specified in lpData. Unrecognized values in guidDataType can be ignored.

Any pointers returned in a callback function are temporary and are valid only in the body of the callback function. If the application needs to save pointer information, it must allocate memory to hold the data, copy the data, and then store the pointer to this new data. In this function, lpData is temporary.


EnumAddressTypeCallback

Application-defined callback function for the IDirectPlayLobby3::EnumAddressTypes method.

Syntax

BOOL FAR PASCAL EnumAddressTypeCallback(
  REFGUID guidDataType,
  LPVOID lpContext,
  DWORD dwFlags
  );

Parameters

guidDataType
Pointer to a globally unique identifier (GUID) indicating the address type. (In C++, it is a reference to the GUID.) Predefined address types are DPAID_Phone, DPAID_INet, and DPAID_ComPort. For more information about these address types, see DirectPlay Address.
lpContext
Context passed to the callback function.
dwFlags
Reserved; do not use.

Return Value

Returns TRUE to continue the enumeration or FALSE to stop it.


EnumConnectionsCallback

Application-defined callback function for the IDirectPlay4::EnumConnections method.

Syntax

BOOL FAR PASCAL EnumConnectionsCallback(
  LPCGUID lpguidSP,
  LPVOID lpConnection,
  DWORD dwConnectionSize,
  LPCDPNAME lpName,
  DWORD dwFlags,
  LPVOID lpContext
  );

Parameters

lpguidSP
The GUID of the DirectPlay service provider or lobby provider associated with the connection. Use this GUID to uniquely identify the service or lobby provider, rather than using the order in the enumeration or the name.
lpConnection
A read-only pointer to a buffer that contains the connection. This parameter is passed to the IDirectPlay4::InitializeConnection method to initialize the DirectPlay object. This buffer contains a DirectPlay Address.
dwConnectionSize
The size, in bytes, of the lpConnection buffer.
lpName
A read-only pointer to a DPNAME structure. The structure contains the short name of the connection that should appear to the user.
If IDirectPlay4::EnumConnections was called on an ANSI interface, reference the strings as ANSI. If EnumConnections was called on a Unicode interface, reference the strings as Unicode.
dwFlags
Flags to indicate the type of connection. Not used at this time.
lpContext
Pointer to an application-defined context.

Return Value

Returns TRUE to continue the enumeration or FALSE to stop it.

Remarks

The application must implement this function in order to use the IDirectPlay4::EnumConnections method. It is called once for each connection that is enumerated.

The application should allocate memory and copy each of the connections for presentation to the user and for use in the IDirectPlay4::InitializeConnection method.

See Also

IDirectPlay4::EnumConnections, IDirectPlay4::InitializeConnection, Using DirectPlay Addresses


EnumDPCallback

Application-defined callback function for the DirectPlayEnumerate function. Depending on whether UNICODE is defined or not, the prototype for the callback function will have lpSPName defined as either the LPWSTR type (for Unicode) or the LPSTR type (for ANSI).

Syntax

BOOL FAR PASCAL EnumDPCallback(
  LPGUID lpguidSP,
  LPSTR/LPWSTR lpSPName,
  DWORD dwMajorVersion,
  DWORD dwMinorVersion,
  LPVOID lpContext
  );

Parameters

lpguidSP
Pointer to the unique identifier of the DirectPlay service provider.
lpSPName
Pointer to a string containing the driver description. Depending on whether the UNICODE symbol is defined or not, the parameter will be of the LPWSTR type (Unicode) or the LPSTR type (ANSI).
dwMajorVersion and dwMinorVersion
Major and minor version numbers of the driver.
lpContext
Pointer to an application-defined context.

Return Value

Returns TRUE to continue the enumeration or FALSE to stop it.

Remarks

Any pointers returned in a callback function are temporary and are valid only in the body of the callback function. If the application needs to save pointer information, it must allocate memory to hold the data, copy the data, and then store the pointer to this new data. In this function, lpGUIDSP and lpSPName are temporary.


EnumLocalApplicationsCallback

Application-defined callback function for the IDirectPlayLobby3::EnumLocalApplications method.

Syntax

BOOL FAR PASCAL EnumLocalApplicationsCallback(
  LPCDPLAPPINFO lpAppInfo,
  LPVOID lpContext,
  DWORD dwFlags
  );

Parameters

lpAppInfo
Pointer to a read-only DPLAPPINFO structure containing information about the application being enumerated.
lpContext
Context passed from the IDirectPlayLobby3::EnumLocalApplications call.
dwFlags
Reserved; do not use.

Return Value

Returns TRUE to continue the enumeration or FALSE to stop it.

Remarks

Any pointers returned in a callback function are temporary and are valid only in the body of the callback function. If the application needs to save pointer information, it must allocate memory to hold the data, copy the data, and then store the pointer to this new data. In this function, lpAppInfo is temporary. Also note that the pointers inside the structure specified in the lpAppInfo parameter - lpszAppNameA and lpszAppName - are also temporary.


EnumPlayersCallback2

Application-defined callback function. The application must implement this function and pass a pointer to it in the IDirectPlay4::EnumGroups, IDirectPlay4::EnumGroupPlayers, IDirectPlay4::EnumPlayers, and IDirectPlay4::EnumGroupsInGroup methods. The callback is called once for each player/group that is enumerated.

Syntax

BOOL FAR PASCAL EnumPlayersCallback2(
  DPID dpId,
  DWORD dwPlayerType,
  LPCDPNAME lpName,
  DWORD dwFlags,
  LPVOID lpContext
  );

Parameters

dpId
DPID of the player or group being enumerated.
dwPlayerType
Type of entity, either DPPLAYERTYPE_GROUP or DPPLAYERTYPE_PLAYER.
lpName
Read-only pointer to a DPNAME structure containing the name of the player or group. This pointer is only valid for the duration of the callback function. Any data that is to be saved for future reference must be copied to some application-owned memory.
dwFlags
Flags describing the group or player being enumerated.
DPENUMGROUPS_HIDDEN — the group was created using the hidden flag.
DPENUMGROUPS_SHORTCUT — the group is a shortcut.
DPENUMGROUPS_STAGINGAREA — the group is a staging area.
DPENUMPLAYERS_GROUP — both players and groups are being enumerated. This flag is returned only if it was specified in the enumeration method calling this callback.
DPENUMPLAYERS_LOCAL — the player or group exists on a local computer. This flag is returned only if it was specified in the enumeration method calling this callback.
DPENUMPLAYERS_OWNER — the player is the owner of the group. This flag is returned only if it was specified in the IDirectPlay4::EnumGroupPlayers method calling this callback.
DPENUMPLAYERS_REMOTE — the player or group exists on a remote computer. This flag is returned only if it was specified in the enumeration method calling this callback.
DPENUMPLAYERS_SERVERPLAYER — the player is the server player in an application/server session. Only one server player exists in each session.
DPENUMPLAYERS_SESSION — the player or group exists in the session identified by lpguidInstance in the enumeration method. This flag is returned only if it was specified in the enumeration method calling this callback.
DPENUMPLAYERS_SPECTATOR — the player is a spectator (applies to players only).
lpContext
Pointer to an application-defined context.

Return Value

Returns TRUE to continue the enumeration or FALSE to stop it.

Remarks

Any pointers returned in a callback function are temporary and are valid only in the body of the callback function. If the application needs to save pointer information, it must allocate memory to hold the data, copy the data, and then store the pointer to this new data.

See Also

DPNAME, IDirectPlay4::EnumGroups, IDirectPlay4::EnumPlayers, IDirectPlay4::EnumGroupPlayers, IDirectPlay4::EnumGroupsInGroup


EnumSessionsCallback2

Application-defined callback function for the IDirectPlay4::EnumSessions method.

Syntax

BOOL FAR PASCAL EnumSessionsCallback2(
  LPCDPSESSIONDESC2 lpThisSD,
  LPDWORD lpdwTimeOut,
  DWORD dwFlags,
  LPVOID lpContext
  );

Parameters

lpThisSD
Pointer to a DPSESSIONDESC2 structure describing the enumerated session. This parameter will be set to NULL if the enumeration has timed out.
lpdwTimeOut
Pointer to a variable containing the current time-out value. This parameter can be reset when the DPESC_TIMEDOUT flag is returned if you want to wait longer for sessions to reply.
dwFlags
Typically, this flag is set to zero.
DPESC_TIMEDOUT
The enumeration has timed out. Reset lpdwTimeOut and return TRUE to continue, or FALSE to stop the enumeration.
lpContext
Pointer to an application-defined context.

Return Value

Returns TRUE to continue the enumeration or FALSE to stop it.

Remarks

The application must implement this function in order to use the IDirectPlay4::EnumSessions method. This callback function will be called once for each session that is enumerated. Once all the session are enumerated, the callback function will be called one additional time with the DPESC_TIMEDOUT flag.

Applications should look at the flags of the DPSESSIONDESC2 to determine the nature of the session.

Any pointers returned in a callback function are temporary and are valid only in the body of the callback function. If the application needs to save pointer information, it must allocate memory to hold the data, copy the data, and then store the pointer to this new data. In this function, lpThisSD is temporary. Also note that the pointers inside the structure specified in the lpThisSD parameter - lpszSessionName / lpszSessionNameA and lpszPassword / lpszPasswordA - are also temporary.


IDirectPlay4 Interface

Applications use the methods of the IDirectPlay4 interface to create DirectPlay objects and work with system-level variables. (The IDirectPlay4A interface is the same as the IDirectPlay4 interface, except that IDirectPlay4A uses ANSI characters, and IDirectPlay4 uses Unicode.) This section is a reference to the methods of this interface.

The methods of the IDirectPlay4 interface can be organized into the following groups.

Session management | Close
EnumConnections
EnumSessions
GetCaps
GetGroupConnectionSettings
GetSessionDesc
InitializeConnection
Open
SetGroupConnectionSettings
SetSessionDesc
StartSession
Player management | CreatePlayer
DestroyPlayer
EnumPlayers
GetPlayerAccount
GetPlayerAddress
GetPlayerCaps
GetPlayerData
GetPlayerFlags
GetPlayerName
SetPlayerData
SetPlayerName
Message management | CancelMessage
CancelPriority
GetMessageCount
GetMessageQueue
Receive
Send
SendChatMessage
SendEx
Group management | AddGroupToGroup
AddPlayerToGroup
CreateGroup
CreateGroupInGroup
DeleteGroupFromGroup
DeletePlayerFromGroup
DestroyGroup
EnumGroupPlayers
EnumGroups
EnumGroupsInGroup
GetGroupData
GetGroupFlags
GetGroupName
GetGroupOwner
GetGroupParent
SetGroupData
SetGroupName
SetGroupOwner
Initialization | Initialize
Security and authentication | SecureOpen

The IDirectPlay4 interface, like all COM interfaces, inherits the IUnknown interface methods. The IUnknown interface supports the following three methods:
AddRef
QueryInterface
Release


IDirectPlay4::AddGroupToGroup

IDirectPlay4 Interface

Adds a shortcut to a group to an already existing group. This allows the linked group to be enumerated by the IDirectPlay4::EnumGroupsInGroup method. To remove a group's shortcut from another group, call DeleteGroupFromGroup.

Syntax

HRESULT AddGroupToGroup(
  DPID idParentGroup,
  DPID idGroup
  );

Parameters

idParentGroup
ID of the group to which the shortcut will be added. Can be any valid group ID.
idGroup
The group ID of the group whose shortcut will be added. Can be any valid group ID.

Return Value

Returns DP_OK if successful, or one of the following error values otherwise:
DPERR_ACCESSDENIED
DPERR_CONNECTIONLOST
DPERR_INVALIDGROUP

Remarks

This method can be used to place a group "inside" more than one group.

A DPMSG_ADDGROUPTOGROUP system message is generated to inform players of this change.

See Also

IDirectPlay4::CreateGroupInGroup, IDirectPlay4::DeleteGroupFromGroup, IDirectPlay4::EnumGroupsInGroup, DPMSG_ADDGROUPTOGROUP


IDirectPlay4::AddPlayerToGroup

IDirectPlay4 Interface

Add a player to an existing group. A player can be a member of multiple groups. Groups cannot be added to other groups using this API (see IDirectPlay4::AddGroupToGroup). An application can add any player to any group (including players and groups that weren't created locally).

Syntax

HRESULT AddPlayerToGroup(
  DPID idGroup,
  DPID idPlayer
  );

Parameters

idGroup
group ID of the group to be augmented.
idPlayer
Player ID of the player to be added to the group.

Return Value

Returns DP_OK if successful, or one of the following error values otherwise:
DPERR_CANTADDPLAYER
DPERR_CONNECTIONLOST
DPERR_INVALIDGROUP
DPERR_INVALIDPLAYER
DPERR_NOSESSIONS

This method returns DPERR_INVALIDPLAYER if the player DPID is not a player id or if the id is not for a local player.

Remarks

A DPMSG_ADDPLAYERTOGROUP system message will be generated and sent to all the other players.

See Also

IDirectPlay4::CreateGroup, IDirectPlay4::DeletePlayerFromGroup, DPMSG_ADDPLAYERTOGROUP


IDirectPlay4::CancelMessage

IDirectPlay4 Interface

Used to cancel a specific message (or all the messages) that are still in the send queue. CancelMessage applies only to asynchronous messages.

In order to cancel a specific message, the application must obtain and save the message ID returned by the IDirectPlay4::SendEx method.

Messages that have left the message queue and are partially sent cannot be canceled. A message sent to a group cannot be canceled after it has been sent to at least one member of the group.

Canceling a message still generates a DPMSG_SENDCOMPLETE system message indicating the message was canceled.

Syntax

HRESULT CancelMessage(
  DWORD dwMsgID,
  DWORD dwFlags
  );

Parameters

dwMsgID
ID of the specific message to be canceled. This ID is returned when the message is sent using IDirectPlay4::SendEx. Specify zero to cancel all messages.
dwFlags
This parameter is reserved. Must be zero.

Return Value

Returns DP_OK if successful, or one of the following error values otherwise:
DPERR_CANCELFAILED
DPERR_INVALIDFLAGS
DPERR_INVALIDPARAMS
DPERR_UNKNOWNMESSAGE
DPERR_UNSUPPORTED

This method returns DPERR_CANCELFAILED if the message cannot be canceled. This method returns DPERR_UNKNOWNMESSAGE if the ID of the message to be canceled is invalid. It returns DP_OK if there are no messages in the send queue.

Remarks

If the DirectPlay Protocol was specified in the session description, then all the options on CancelMessage are available. Otherwise, an application should call GetCaps to determine what options the service provider has implemented.

See Also

IDirectPlay4::SendEx, IDirectPlay4::Send, IDirectPlay4::GetMessageQueue, DPMSG_SENDCOMPLETE, IDirectPlay4::CancelPriority


IDirectPlay4::CancelPriority

IDirectPlay4 Interface

Used to cancel all messages of a particular priority or range of priorities that are still in the send queue. CancelPriority applies only to asynchronous messages.

Messages that have left the message queue and are partially sent cannot be canceled. A message sent to a group cannot be canceled once it has been sent to at least one member of the group.

Canceling a message still generates a DPMSG_SENDCOMPLETE system message indicating the message was canceled.

Syntax

HRESULT CancelPriority(
  DWORD dwMinPriority,
  DWORD dwMaxPriority,
  DWORD dwFlags
  );

Parameters

dwMinPriority
The minimum priority in the range to be canceled.
dwMaxPriority
The maximum priority in the range to be canceled. Must be greater than dwMinPriority. Set to MAXPRIORITY for the maximum possible priority.
dwFlags
This parameter is reserved. Must be zero.

Return Value

Returns DP_OK if successful, or one of the following error values otherwise:
DPERR_INVALIDFLAGS
DPERR_INVALIDPARAMS
DPERR_UNSUPPORTED

This method returns DP_OK if there are no messages in the send queue.

See Also

IDirectPlay4::SendEx, IDirectPlay4::Send, IDirectPlay4::GetMessageQueue, DPMSG_SENDCOMPLETE, IDirectPlay4::CancelMessage


IDirectPlay4::Close

IDirectPlay4 Interface

Closes a previously opened session. Any locally created groups will migrate to be owned by the host of the session.

Syntax

HRESULT Close( );

Return Value

Returns DP_OK if successful, or one of the following error values otherwise:
DPERR_INVALIDOBJECT
DPERR_INVALIDPARAMS
DPERR_NOSESSIONS

Remarks

All locally created players will be destroyed and appropriate DPMSG_DELETEPLAYERFROMGROUP and DPMSG_DESTROYPLAYERORGROUP system messages will be sent to other session participants.

See Also

IDirectPlay4::DestroyPlayer, DPMSG_DESTROYPLAYERORGROUP, IDirectPlay4::Open


IDirectPlay4::CreateGroup

IDirectPlay4 Interface

Creates a group in the current session. A group is a logical collection of players or other groups.

Syntax

HRESULT CreateGroup(
  LPDPID lpidGroup,
  LPDPNAME lpGroupName,
  LPVOID lpData,
  DWORD dwDataSize,
  DWORD dwFlags
  );

Parameters

lpidGroup
Pointer to a variable that will be filled with the DirectPlay group ID. This value is defined by DirectPlay.
lpGroupName
Pointer to a DPNAME structure that holds the name of the group. NULL indicates that the group has no initial name. The name in lpGroupName is provided for human use only; it is not used internally and need not be unique.
lpData
Pointer to a block of application-defined remote data to associate initially with the group ID. NULL indicates that the group has no initial data. The data specified here is assumed to be remote data that will be propagated to all the other applications in the session as if IDirectPlay4::SetGroupData were called.
dwDataSize
Size, in bytes, of the data block that lpData points to.
dwFlags
Flag indicating what type of group to create. By default (dwFlags = 0), ownership of the group will migrate to the host when the owner leaves the session, and the group persists until it is explicitly destroyed.
Can be one of the following values:
DPGROUP_HIDDEN
Creates the group with the hidden flag. When the group is enumerated, the hidden flag is set. In a lobby session, hidden groups are only available through shortcuts created with IDirectPlay4::AddGroupToGroup. This flag works much like the DPPLAYER_SPECTATOR flag for players.
DPGROUP_STAGINGAREA
Creates the group as a staging area. A staging area is used to marshal players together in order to launch a new session.

Return Value

Returns DP_OK if successful, or one of the following error values otherwise:
DPERR_CANTADDPLAYER
DPERR_CONNECTIONLOST
DPERR_INVALIDFLAGS
DPERR_INVALIDPARAMS

Remarks

If the group is created in a client/server session, no group notification messages are sent. Groups are only visible on the machine that created them, regardless of whether the machine is the client or the host.

If the group is created in a peer-to-peer session, CreateGroup will generate a DPMSG_CREATEPLAYERORGROUP system message that will be sent to all the other players. The application can then use IDirectPlay4::Send to send a message to all the players in a group by sending one message to the group ID. DirectPlay will either use multicast to send the message (if the service provider supports it) or send individual messages to each player in the group.

The group ID returned to the application should be used to identify the group for message passing and data association. Player and group IDs assigned by DirectPlay will always be unique within the session.

Groups created with CreateGroup are top-level groups in the session. They are enumerated with IDirectPlay4::EnumGroups. In contrast, the IDirectPlay4::CreateGroupInGroup method creates a group that is a sub-group of a parent group.

Groups can also be used by the application for general organization. In a lobby session, a staging area is used as the mechanism for collecting players for the purpose of starting a new application session using IDirectPlay4::StartSession.

The player who creates a group is the default owner of it. Only the owner can change group properties such as the name and remote data. If the owner leaves the session, ownership is transferred to the host of the session.

Any player aware of a group in a session can change the membership of the group or delete the group.

Groups will persist in the session until they are explicitly destroyed.

See Also

DPNAME, DPMSG_CREATEPLAYERORGROUP, IDirectPlay4::AddGroupToGroup,IDirectPlay4::DestroyGroup, IDirectPlay4::EnumGroups, IDirectPlay4::EnumGroupPlayers, IDirectPlay4::Send, IDirectPlay4::SetGroupData, IDirectPlay4::SetGroupName, IDirectPlay4::CreateGroupInGroup, IDirectPlay4::GetGroupFlags


IDirectPlay4::CreateGroupInGroup

IDirectPlay4 Interface

Creates a group within an existing group. A group created within another group can only be enumerated using the IDirectPlay4::EnumGroupsInGroup method. A group created this way can be destroyed by calling the IDirectPlay4::DestroyGroup method.

Syntax

HRESULT CreateGroupInGroup(
  DPID idParentGroup,
  LPDPID lpidGroup,
  LPDPNAME lpGroupName,
  LPVOID lpData,
  DWORD dwDataSize,
  DWORD dwFlags
  );

Parameters

idParentGroup
DPID of the group within which a group will be created. Must be an already existing group.
lpidGroup
Pointer to the DPID that will be filled in with the DirectPlay group ID of the created group.
lpGroupName
Pointer to a DPNAME structure that holds the name of the group to be created. NULL indicates that the group has no initial name.
lpData
Pointer to a block of application-defined remote data to associate initially with the group ID. NULL indicates that the group has no initial data. The data specified here is assumed to be remote data that will be propagated to all the other applications in the session as if the IDirectPlay4::SetGroupData method had been called.
dwDataSize
Size, in bytes, of the data block that the lpData parameter points to.
dwFlags
Flag indicating what type of group to create. Default (dwFlags = 0) is a normal group.
DPGROUP_HIDDEN
Creates the group with the hidden flag. When the group is enumerated, the hiddle flag is set. In a lobby session, hidden groups are only available through shortcuts created with IDirectPlay4::AddGroupToGroup.
DPGROUP_STAGINGAREA
Creates the group as a staging area. A staging area can be used to launch DirectPlay sessions using the IDirectPlay4::StartSession method.

Return Value

Returns DP_OK if successful, or one of the following error values otherwise:
DPERR_CANTADDPLAYER
DPERR_CONNECTIONLOST
DPERR_INVALIDFLAGS
DPERR_INVALIDGROUP
DPERR_INVALIDPARAMS

This method returns DPERR_CANTADDPLAYER if the group could not be created. It returns DPERR_INVALIDGROUP if the parent group ID is invalid.

Remarks

If the group is created in a client/server session, no group notification messages are sent. Groups are only visible on the machine that created them, regardless of whether the machine is the client or the host.

If the group is created in a peer-to-peer session, CreateGroupInGroup will generate a DPMSG_CREATEPLAYERORGROUP system message generated to inform players of this change.

If you destroy a top-level group, any member groups it contains are destroyed as well, and the appropriate destruction messages are sent.

See Also

IDirectPlay4::DestroyGroup, IDirectPlay4::EnumGroupsInGroup, DPMSG_CREATEPLAYERORGROUP


IDirectPlay4::CreatePlayer

IDirectPlay4 Interface

Creates a local player for the current session.

Syntax

HRESULT CreatePlayer(
  LPDPID lpidPlayer,
  LPDPNAME lpPlayerName,
  HANDLE hEvent,
  LPVOID lpData,
  DWORD dwDataSize,
  DWORD dwFlags
  );

Parameters

lpidPlayer
Pointer to a variable that will be filled with the DirectPlay player ID. This value is defined by DirectPlay.
lpPlayerName
Pointer to a DPNAME structure that holds the name of the player. NULL indicates that the player has no initial name information. The name in lpPlayerName is provided for human use only. It is not used internally and need not be unique.
hEvent
An event object created by the application that will be signaled by DirectPlay when a message addressed to this player is received.
lpData
Pointer to a block of application-defined data to associate with the player ID. NULL indicates that the player has no initial data. The data specified in this parameter is assumed to be remote data that will be propagated to all the other applications in the session, as if IDirectPlay4::SetPlayerData were called.
dwDataSize
Size, in bytes, of the data block that lpData points to.
dwFlags
Flags indicating what type of player this is. Default (dwFlags = 0) is a nonspectator, nonserver player.
DPPLAYER_SERVERPLAYER - the player is a server player for client/server communications. Only the host can create a server player. There can only be one server player in a session. CreatePlayer will always return a player ID of DPID_SERVERPLAYER if this flag is specified.
DPPLAYER_SPECTATOR - the player is created as a spectator. A spectator player behaves exactly as a normal player except the player is flagged as a spectator. The application can then limit what a spectator player can do. The behavior of a spectator player is completely defined by the application. DirectPlay simply propagates this flag.

Return Value

Returns DP_OK if successful, or one of the following error values otherwise:
DPERR_CANTADDPLAYER
DPERR_CANTCREATEPLAYER
DPERR_CONNECTIONLOST
DPERR_INVALIDFLAGS
DPERR_INVALIDPARAMS
DPERR_NOCONNECTION

Remarks

A single process can have multiple local players that communicate through a DirectPlay object with other players on the same computer or players on remote computers.

Upon successful completion, this method sends a DPMSG_CREATEPLAYERORGROUP system message to all the other players in the session announcing that a new player has joined the session. By default, all local players receive copies of all the system messages.

Your application should use the player ID returned to the application to identify the player for message passing and data association. Player and group IDs assigned by DirectPlay will always be unique within the session.

Only the application that created the player can:

  • change the player's name.
  • change the player's remote data.
  • send messages from the player.

If the application closes the session, any local players created will be automatically destroyed. Using IDirectPlay4::DestroyPlayer, the session host or the application that created the player can destroy the player at any time.

If the application uses a separate thread to retrieve DirectPlay messages, it is highly recommended that a non-NULL hEvent be supplied and used for synchronization. This event will be set when this player receives a message. Within the message receive thread, use the Win32 API WaitForSingleObject (or use WaitForMultipleObjects if more than one event is used) within the thread to determine if a player has messages. It is inefficient to loop on IDirectPlay4::Receive inside a separate thread waiting for a message. The same event can be used for all the local players, or the application can supply different events for each player. The application is responsible for creating and destroying the event. See Synchronization for more information.

See Also

DPNAME, DPMSG_CREATEPLAYERORGROUP, IDirectPlay4::DestroyPlayer, IDirectPlay4::EnumPlayers, IDirectPlay4::Receive, IDirectPlay4::Send, IDirectPlay4::SetPlayerData, IDirectPlay4::SetPlayerName, IDirectPlay4::GetPlayerFlags


IDirectPlay4::DeleteGroupFromGroup

IDirectPlay4 Interface

Removes a shortcut to a group previously added with the IDirectPlay4::AddGroupToGroup method from a group. Deleting the shortcut does not destroy the group.

Syntax

HRESULT DeleteGroupFromGroup(
  DPID idParentGroup,
  DPID idGroup
  );

Parameters

idParentGroup
The group DPID of the group containing the shortcut to be deleted. Can be any valid group DPID.
idGroup
The group DPID of the group to delete. Can be any valid group DPID.

Return Value

Returns DP_OK if successful, or one of the following error messages otherwise:
DPERR_ACCESSDENIED
DPERR_CONNECTIONLOST
DPERR_INVALIDGROUP

Remarks

A DPMSG_DELETEGROUPFROMGROUP system message is generated to inform players of this change.

See Also

IDirectPlay4::AddGroupToGroup, DPMSG_DELETEGROUPFROMGROUP


IDirectPlay4::DeletePlayerFromGroup

IDirectPlay4 Interface

Removes a player from a group.

Syntax

HRESULT DeletePlayerFromGroup(
  DPID idGroup,
  DPID idPlayer
  );

Parameters

idGroup
Group ID of the group to be adjusted.
idPlayer
Player ID of the player to be removed from the group.

Return Value

Returns DP_OK if successful, or one of the following error messages otherwise:
DPERR_CONNECTIONLOST
DPERR_INVALIDGROUP
DPERR_INVALIDOBJECT
DPERR_INVALIDPLAYER

Remarks

A DPSYS_DELETEPLAYERFROMGROUP system message is generated to inform the other players of this change. For a list of system messages, see Using System Messages.

A player can delete any player from a group, even if that group was created by some other computer.

See Also

IDirectPlay4::AddPlayerToGroup, DPMSG_DELETEPLAYERFROMGROUP


IDirectPlay4::DestroyGroup

IDirectPlay4 Interface

Deletes a group from the session. The ID belonging to this group will not be reused during the current session.

Syntax

HRESULT DestroyGroup(
  DPID idGroup
  );

Parameters

idGroup
The ID of the group being removed from the game.

Return Value

Returns DP_OK if successful, or one of the following error messages otherwise:
DPERR_CONNECTIONLOST
DPERR_INVALIDGROUP
DPERR_INVALIDOBJECT
DPERR_INVALIDPARAMS
DPERR_INVALIDPLAYER

Remarks

It is not necessary to empty a group before deleting it. The individual players belonging to the group are not destroyed. This method will generate a DPMSG_DELETEPLAYERFROMGROUP system message for each player in the group, and then a DPMSG_DESTROYPLAYERORGROUP system message. For a list of system messages, see Using System Messages.

Any application can destroy any group even if the group was not created locally.

See Also

IDirectPlay4::CreateGroup, DPMSG_DESTROYPLAYERORGROUP


IDirectPlay4::DestroyPlayer

IDirectPlay4 Interface

Deletes a local player from the session, removes any pending messages destined for that player from the message queue, and removes the player from any groups to which the player belonged. The player ID will not be reused during the current session.

In general, only the application that created the player can destroy the player. However, the host of the session can also destroy the player.

Syntax

HRESULT DestroyPlayer(
  DPID idPlayer
  );

Parameters

idPlayer
Player ID of the locally owned player to be removed from the session. When DestroyPlayer is called by the host of the session, this DPID can be that of any player, local or remote.

Return Value

Returns DP_OK if successful, or one of the following error messages otherwise:
DPERR_ACCESSDENIED
DPERR_CONNECTIONLOST
DPERR_INVALIDOBJECT
DPERR_INVALIDPLAYER
DPERR_UNAVAILABLE

Remarks

This method generates a DPMSG_DELETEPLAYERFROMGROUP system message for each group that the player belongs to and then generates a DPMSG_DESTROYPLAYERORGROUP system message.

A player cannot be destroyed if the player has pending asynchronous messages in the send queue. All messages must either be completed or cancelled.

See Also

IDirectPlay4::CreatePlayer, DPMSG_DESTROYPLAYERORGROUP


IDirectPlay4::EnumConnections

IDirectPlay4 Interface

Enumerates all the registered service providers and lobby providers that are available to the application. These should be presented to the user to make a selection. The connection that the user selects should be passed to the IDirectPlay4::InitializeConnection method.

Syntax

HRESULT EnumConnections(
  LPCGUID lpguidApplication,
  LPDPENUMCONNECTIONSCALLBACK lpEnumCallback,
  LPVOID lpContext,
  DWORD dwFlags
  );

Parameters

lpguidApplication
Pointer to an application globally unique identifier (GUID). Only service providers and lobby providers that are usable by this application will be returned. If set to a NULL pointer, a list of all the connections is enumerated regardless of the application GUID.
lpEnumCallback
Pointer to a user-supplied EnumConnectionsCallback function that will be called for each available connection.
lpContext
Pointer to a user-defined context that is passed to the callback function.
dwFlags
Flags that specify the type of connections to be enumerated. The default (dwFlags = 0) will enumerate DirectPlay service providers only. Possible values are:
DPCONNECTION_DIRECTPLAY — enumerate DirectPlay service providers to communicate in an application session.
DPCONNECTION_DIRECTPLAYLOBBY — enumerate DirectPlay lobby providers to communicate with a lobby server.

Return Value

Returns DP_OK if successful, or one of the following error values otherwise:
DPERR_CONNECTIONLOST
DPERR_INVALIDFLAGS
DPERR_INVALIDPARAMS

Remarks

This method replaces the DirectPlayEnumerate function. DirectPlayEnumerate still works, but only returns registered service providers.

The order in which the service and lobby providers are returned is not guaranteed to be the same in subsequent calls to EnumConnections.

Not all the enumerated connections are available for use. For example, this method will return the modem service provider even if the user has no modem installed. The application can call the IDirectPlay4::InitializeConnection method on each connection and check for an error code to determine whether the service provider can be used.

Calling this method on the IDirectPlay4A (ANSI) interface always returns a suitably localized, single-byte character string. No multi-byte characters are used, so there will be no problems displaying strings using fonts that do not support multi-byte characters. Calling this method on the IDirectPlay4 (Unicode) interface returns a localized, wide character description.

Some service providers can register themselves as private. These service providers are not enumerated using this method. To use private service providers, you must explicitly reference them by their GUID, either by lobby launching the application or by creating a DirectPlay Address and passing it to InitializeConnection.

See Also

IDirectPlay4::InitializeConnection, EnumConnectionsCallback, DirectPlay Address


IDirectPlay4::EnumGroupPlayers

IDirectPlay4 Interface

Enumerates the players belonging to a specific group in the currently open session. If there is no open session, players in a remote session can be enumerated by specifying the DPENUMPLAYERS_session flag and the guidInstance of the session. Password-protected remote sessions cannot be enumerated.

A pointer to an application-implemented callback function must be supplied, and DirectPlay calls it once for each player in the group that matches the criteria specified in dwFlags.

You cannot use EnumGroupPlayers in a lobby session you are not connected to.

Syntax

HRESULT EnumGroupPlayers(
  DPID idGroup,
  LPGUID lpguidInstance,
  LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
  LPVOID lpContext,
  DWORD dwFlags
  );

Parameters

idGroup
DPID of the group whose players are to be enumerated.
lpguidInstance
Pointer to a globally unique identifier (GUID) identifying the session to be enumerated. This parameter is ignored unless the DPENUMPLAYERS_SESSION flag is specified. The GUID must be equal to one of the sessions enumerated by IDirectPlay4::EnumSessions.
lpEnumPlayersCallback2
Pointer to the EnumPlayersCallback2 function that will be called for every player in the group that matches the criteria specified in dwFlags.
lpContext
Pointer to an application-defined context that is passed to each enumeration callback.
dwFlags
Flags specifying how the enumeration is to be done. The default (dwFlags = 0) enumerates players in a group in the current active session. You should use a logical OR operation to combine the flags that you want to specify. Only players that meet all the criteria of the combined flags will be enumerated. For example, if you specify (DPENUMPLAYERS_LOCAL | DPENUMPLAYERS_SPECTATOR) only players in the group that are local and are spectator players will be enumerated. If you specify (DPENUMPLAYERS_LOCAL | DPENUMPLAYERS_REMOTE), no players will be enumerated because no player can be both local and remote.
Can be one or more of the following values:
DPENUMPLAYERS_LOCAL
Enumerates players created locally by this DirectPlay object.
DPENUMPLAYERS_OWNER
Enumerates only the player that is the owner of this group.
DPENUMPLAYERS_REMOTE
Enumerates players created by remote DirectPlay objects.
DPENUMPLAYERS_SERVERPLAYER
Enumerates the server player.
DPENUMPLAYERS_SESSION
Enumerates the players for the session identified by lpguidInstance. This flag can only be used if there is no current open session. This flag cannot be used in a lobby session.
DPENUMPLAYERS_SPECTATOR
Enumerates players who are spectator players.

Return Value

Returns DP_OK if successful, or one of the following error messages otherwise:
DPERR_ACCESSDENIED
DPERR_CONNECTIONLOST
DPERR_INVALIDPARAMS
DPERR_INVALIDGROUP
DPERR_NOSESSIONS
DPERR_UNAVAILABLE

This method returns DPERR_ACCESSDENIED if the session is a lobby session you are not connected to. It returns DPERR_INVALIDPARAMS if an invalid callback, an invalid guidInstance, or if invalid flags were supplied. It returns DPERR_NOSESSIONS if there is no active session. It returns DPERR_UNAVAILABLE if the session could not be enumerated.

Remarks

By default, this method will enumerate all players in the current session. The DPENUMPLAYERS_SESSION flag can be used, along with a session instance GUID, to request that a session's host provide its list for enumeration. Use of the DPENUMPLAYERS_SESSION flag with this method must occur after the IDirectPlay4::EnumSessions method has been called, and before any calls to the IDirectPlay4::Close or IDirectPlay4::Open methods.

The DPENUMPLAYERS_OWNER flag is returned in the callback, indicating which player is the owner of the group.

See Also

IDirectPlay4::CreatePlayer, IDirectPlay4::DestroyPlayer, IDirectPlay4::AddPlayerToGroup, IDirectPlay4::DeletePlayerFromGroup


IDirectPlay4::EnumGroups

IDirectPlay4 Interface

Enumerates all the top-level groups in the current session. Top-level groups are groups that were created with the IDirectPlay4::CreateGroup method. If there is no open session, groups in a remote session can be enumerated by specifying the DPENUMGROUPS_session flag and the guidInstance of the session. Password-protected remote sessions cannot be enumerated.

A pointer to an application-implemented callback function must be supplied, and DirectPlay calls it once for each group in the session that matches the criteria specified in dwFlags.

You cannot use EnumGroups in a lobby session you are not connected to.

Syntax

HRESULT EnumGroups(
  LPGUID lpguidInstance,
  LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
  LPVOID lpContext,
  DWORD dwFlags
  );

Parameters

lpguidInstance
This parameter should be NULL to enumerate groups in the currently open session. If there is no open session, this parameter can be a pointer to a globally unique identifier (GUID) identifying the session to be enumerated. The GUID must be equal to one of the sessions enumerated by IDirectPlay4::EnumSessions. This parameter is ignored unless the DPENUMGROUPS_SESSION flag is specified.
lpEnumPlayersCallback2
Pointer to the EnumPlayersCallback2 function that will be called for every group in the session that matches the criteria specified in dwFlags.
lpContext
Pointer to an application-defined context that is passed to each enumeration callback.
dwFlags
Flags specifying how the enumeration is to be done. Default (dwFlags = 0) enumerates all groups in the current active session. You should use a logical OR operation to combine the flags that you want to specify. Only groups that meet all the criteria of the combined flags will be enumerated. For example, if you specify (DPENUMGROUPS_LOCAL | DPENUMGROUPS_STAGINGAREA) only groups that are local and are staging areas will be enumerated. If you specify (DPENUMGROUPS_LOCAL | DPENUMGROUPS_REMOTE), no groups will be enumerated because no group can be both local and remote.
Can be one or more of the following values:
DPENUMGROUPS_ALL
Enumerates all groups in this session.
DPENUMGROUPS_HIDDEN
Enumerates only hidden groups that are currently available.
DPENUMGROUPS_LOCAL
Enumerates groups created locally by this DirectPlay object.
DPENUMGROUPS_REMOTE
Enumerates groups created by remote DirectPlay objects.
DPENUMGROUPS_SESSION
Performs enumeration in the session identified by the lpguidInstance parameter. This flag can only be used if there is no current active session. You cannot use this flag in a lobby session.
DPENUMGROUPS_STAGINGAREA
Enumerates groups that are staging areas. (Staging areas are used to marshal players together in order to launch a new session.)

Return Value

Returns DP_OK if successful, or one of the following error messages otherwise:
DPERR_CONNECTIONLOST
DPERR_INVALIDPARAMS
DPERR_NOSESSIONS
DPERR_UNAVAILABLE

This method returns DPERR_INVALIDPARAMS if an invalid callback, an invalid guidInstance, or invalid flags were supplied. It returns DPERR_NOSESSIONS if there is no open session. It returns DPERR_UNAVAILABLE if the remote session could not be enumerated.

Remarks

To enumerate the subgroups in a group, use IDirectPlay4::EnumGroupsInGroup.

See Also

EnumPlayersCallback2, IDirectPlay4::CreateGroup, IDirectPlay4::DestroyGroup, IDirectPlay4::EnumSessions


IDirectPlay4::EnumGroupsInGroup

IDirectPlay4 Interface

Enumerates all groups and shortcuts to groups that are contained within another group. Groups are placed inside other groups by creating them with the IDirectPlay4::CreateGroupInGroup method or by adding them to a group with the IDirectPlay4::AddGroupToGroup method. This method is not recursive.

You cannot use EnumGroupsInGroup in a lobby session you are not connected to.

Syntax

HRESULT EnumGroupsInGroup(
  DPID idGroup,
  LPGUID lpguidInstance,
  LPDPENUMPLAYERSCALLBACK2 lpEnumCallback,
  LPVOID lpContext,
  DWORD dwFlags
  );

Parameters

idGroup
DPID of the group whose subgroups are to be enumerated.
lpguidInstance
Pointer to a globally unique identifier (GUID) identifying the session to be enumerated. This parameter is ignored unless the DPENUMPLAYERS_SESSION flag is specified. The GUID must equal one of the sessions enumerated by the IDirectPlay4::EnumSessions method.
lpEnumCallback
Pointer to the EnumPlayersCallback2 function that will be called for every group in the group that matches the criteria specified in dwFlags.
lpContext
Pointer to an application-defined context that is passed to each enumeration callback.
dwFlags
Flags specifying how the enumeration will be done. The default (dwFlags = 0) enumerates all groups in the current active session. You should use a logical OR operation to combine the flags that you want to specify. Only groups that meet all the criteria of the combined flags will be enumerated. For example, if you specify (DPENUMGROUPS_LOCAL | DPENUMGROUPS_STAGINGAREA) only groups that are local and are staging areas will be enumerated. If you specify (DPENUMGROUPS_LOCAL | DPENUMGROUPS_REMOTE), no groups will be enumerated because no group can be both local and remote.
Can be one or more of the following values:
DPENUMGROUPS_ALL
Enumerates all groups in the group.
DPENUMGROUPS_HIDDEN
Enumerates only the currently available hidden groups in the group.
DPENUMGROUPS_LOCAL
Enumerates groups in the group created locally by this DirectPlay object.
DPENUMGROUPS_REMOTE
Enumerates groups in the group created by remote DirectPlay objects.
DPENUMGROUPS_SESSION
Performs enumeration in the session identified by the lpguidInstance parameter. This flag can only be used if there is no current active session. This flag cannot be used in lobby sessions.
DPENUMGROUPS_SHORTCUT
Enumerates groups that are shortcuts added to the group using IDirectPlay4::AddGroupToGroup. (A shortcut is a link to another group.)
DPENUMGROUPS_STAGINGAREA
Enumerates groups in the group that are staging areas. (Staging areas are used to marshal players together in order to launch a new session.)

Return Value

Returns DP_OK if successful, or one of the following error messages otherwise:
DPERR_CONNECTIONLOST
DPERR_INVALIDFLAGS
DPERR_INVALIDGROUP
DPERR_INVALIDPARAMS
DPERR_NOSESSIONS
DPERR_UNSUPPORTED

This method returns DPERR_INVALIDPARAMS if an invalid callback or an invalid guidInstance is supplied. It returns DPERR_NOSESSIONS if there is no active session. It returns DPERR_UNSUPPORTED if the session could not be enumerated.

See Also

IDirectPlay4::CreateGroupInGroup, IDirectPlay4::DestroyGroup, IDirectPlay4::AddGroupToGroup, IDirectPlay4::DeleteGroupFromGroup


IDirectPlay4::EnumPlayers

IDirectPlay4 Interface

Enumerates the players in the current open session. If there is no open session, players in a remote session can be enumerated by specifying the DPENUMPLAYERS_SESSION flag and the guidInstance of the session. Password protected remote sessions cannot be enumerated.

A pointer to an application-implemented callback function must be supplied and DirectPlay calls it once for each player in the session that matches the criteria specified in dwFlags.

Within a lobby session, this method will always return DPERR_ACCESSDENIED.

Syntax

HRESULT EnumPlayers(
  LPGUID lpguidInstance,
  LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
  LPVOID lpContext,
  DWORD dwFlags
  );

Parameters

lpguidInstance
This parameter should be NULL to enumerate players in the currently open session. If there is no open session, this parameter can be a pointer to a GUID identifying the session to be enumerated. The GUID must be equal to one of the sessions enumerated by IDirectPlay4::EnumSessions. This parameter is ignored unless the DPENUMPLAYERS_session flag is specified.
lpEnumPlayersCallback2
Pointer to the EnumPlayersCallback2 function that will be called for every player in the session that matches the criteria specified in dwFlags.
lpContext
Pointer to an application-defined context that is passed to each enumeration callback.
dwFlags
Flags specifying how the enumeration is to be done. Default (dwFlags = 0) enumerates all players in the current active session. You should OR together the flags that you want to specify. Only players that meet all the criteria of the combined flags will be enumerated. For example, if you specify (DPENUMPLAYERS_LOCAL | DPENUMPLAYERS_SPECTATOR) only players that are local and are spectator players will be enumerated. If you specify (DPENUMPLAYERS_LOCAL | DPENUMPLAYERS_REMOTE), no players will be enumerated because no player can be both local and remote.
Can be one or more of the following values:
DPENUMPLAYERS_ALL
Enumerates all players in this session.
DPENUMPLAYERS_GROUP
Includes groups in the enumeration of players.
DPENUMPLAYERS_LOCAL
Enumerates players created locally by this DirectPlay object.
DPENUMPLAYERS_REMOTE
Enumerates players created by remote DirectPlay objects.
DPENUMPLAYERS_SERVERPLAYER
Enumerates the server player.
DPENUMPLAYERS_SESSION
Enumerates the players for the session identified by lpguidInstance. This flag can only be used if there is no current open session.
DPENUMPLAYERS_SPECTATOR
Enumerates players who are spectator players.

Return Value

Returns DP_OK if successful, or one of the following error values otherwise:
DPERR_CONNECTIONLOST
DPERR_INVALIDPARAMS
DPERR_NOSESSIONS
DPERR_UNAVAILABLE

This method returns DPERR_INVALIDPARAMS if an invalid callback, an invalid guidInstance, or invalid flags were supplied. It returns DPERR_NOSESSIONS if there is no open session. It returns DPERR_UNAVAILABLE if the remote session could not be enumerated.

Remarks

By default, this method will enumerate players in the current open session. Groups can also be included in the enumeration by using the DPENUMPLAYERS_GROUP flag. The DPENUMPLAYERS_SESSION flag can be used, along with a session instance GUID, to request that a session's host provide its list for enumeration. This method cannot be called from within an IDirectPlay4::EnumSessions enumeration. Furthermore, use of the DPENUMPLAYERS_SESSION flag with this method must occur after the IDirectPlay4::EnumSessions method has been called, and before any calls to the IDirectPlay4::Close or IDirectPlay4::Open methods.

See Also

IDirectPlay4::CreatePlayer, IDirectPlay4::DestroyPlayer, IDirectPlay4::EnumSessions


IDirectPlay4::EnumSessions

IDirectPlay4 Interface

Enumerates all the active sessions for a particular application and/or all the active lobby sessions that serve a particular application. This method can be called after a DirectPlay object has been created and initialized either by DirectPlayCreate or IDirectPlay4::InitializeConnection.

This method returns an error if called while a session is already open.

Syntax

HRESULT EnumSessions(
  LPDPSESSIONDESC2 lpsd,
  DWORD dwTimeout,
  LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
  LPVOID lpContext,
  DWORD dwFlags
  );

Parameters

lpsd
Pointer to the DPSESSIONDESC2 structure describing the sessions to be enumerated. Only those sessions that meet the criteria set in this structure will be enumerated. The guidApplication member can be set to the globally unique identifier (GUID) of an application of interest if it is known, or to GUID_NULL to obtain all sessions. The lpszPassword member is only needed if you want private sessions. All data members besides guidApplication and lpszPassword are ignored.
dwTimeout
In the synchronous case, the total amount of time, in milliseconds, that DirectPlay will wait for replies to the enumeration request (not the time between each enumeration). Any replies received after this time-out will be ignored. The application will be blocked until the time-out expires.
In the asynchronous case, this is the interval, in milliseconds, that enumeration requests will be broadcast by DirectPlay in order to update the internal sessions list.
If the time-out is set to zero, a default time-out appropriate for the service provider and connection type will be used. It is recommended that you set this value to zero. The application can determine this time-out by calling IDirectPlay4::GetCaps and examining the dwTimeout data member of the DPCAPS structure.
lpEnumSessionsCallback2
Pointer to the application-supplied EnumSessionsCallback2 function to be called for each DirectPlay session responding.
lpContext
Pointer to a user-defined context that is passed to each enumeration callback.
dwFlags
The default is zero, which is equivalent to DPENUMSESSIONS_AVAILABLE. When enumerating sessions with DPENUMSESSIONS_ALL or DPENUMSESSIONS_PASSWORDREQUIRED, it is important for the application to know which sessions cannot be joined and which sessions are password-protected so the user can be warned or prompted for a password.
DPENUMSESSIONS_ALL
Enumerate all active sessions, whether they are accepting new players or not. Sessions in which the player limit has been reached, new players have been disabled, or joining has been disabled will be enumerated.
Password-protected sessions will not be enumerated unless the DPENUMSESSIONS_PASSWORDREQUIRED flag is also specified.
If DPENUMSESSIONS_ALL is not specified, DPENUMSESSIONS_AVAILABLE is assumed.
DPENUMSESSIONS_ASYNC
Enumerates all the current sessions in the session cache and returns immediately. Starts the asynchronous enumeration process if not already started. Updates to the session list continue until cancelled by calling EnumSessions with the DPENUMSESSIONS_STOPASYNC flag, or by calling Open, or Release.
If this flag is not specified, the enumeration is done synchronously.
DPENUMSESSIONS_AVAILABLE
Enumerate all sessions that are accepting new players to join. Sessions that have reached their maximum number of players, or have disabled new players, or have disabled joining will not be enumerated.
Password-protected sessions will not be enumerated unless the DPENUMSESSIONS_PASSWORDREQUIRED flag is also specified.
DPENUMSESSIONS_PASSWORDREQUIRED
When used in combination with one of the two flags DPENUMSESSIONS_AVAILABLE or DPENUMSESSIONS_ALL, enables password-protected sessions to be enumerated in addition to sessions without password protection.
If this flag is not specified, no password-protected sessions will be returned.
DPENUMSESSIONS_RETURNSTATUS
If this flag is specified, the enumeration will not display any dialog boxes showing the connection progress status. If the connection cannot be made immediately, the method will return with the DPERR_CONNECTING error. The application must keep calling EnumSessions until either DP_OK is returned, indicating successful completion, or some other error code is returned, indicating an error.
DPENUMSESSIONS_STOPASYNC
Enumerates all the current sessions in the session cache and cancels the asynchronous enumeration process.

Return Value

Returns DP_OK if successful, or one of the following error values otherwise:
DPERR_CONNECTING
DPERR_CONNECTIONLOST
DPERR_EXCEPTION
DPERR_GENERIC
DPERR_INVALIDOBJECT
DPERR_INVALIDPARAMS
DPERR_NOCONNECTION
DPERR_UNINITIALIZED
DPERR_USERCANCEL

This method returns DPERR_GENERIC if the session is already open. It returns DPERR_UNINITIALIZED if the DirectPlay object has not been initialized. It returns DPERR_USERCANCEL if the user cancelled the enumeration process (usually by cancelling a service provider dialog box). It returns DPERR_CONNECTING if the method is in the process of connecting to the network.

Remarks

EnumSessions works by requesting that the service provider locate one or more hosts on the network and send them an enumeration request. The replies that are received make up the sessions that are enumerated.

EnumSessions can be called synchronously (default) or asynchronously. When called synchronously, DirectPlay will clear the internal session cache, send out an enumeration request, and collect replies until the specified time-out expires. Each session will then be returned to the application through the callback function. The application will be blocked until all the sessions have been returned through the callback function.

When called asynchronously (DPENUMSESSIONS_ASYNC), all the current sessions (if any) in the session cache will be returned to the application through the callback function and then the method will return. DirectPlay will then automatically send out enumeration requests with the period of the time-out parameter and listen for replies. Each reply will be used to update the session cache:

  • Sessions already in the cache will be updated.
  • Sessions that have not been updated for a set period of time (and thus have expired) will be deleted.
  • New sessions will be added.

The application must call EnumSessions (with the DPENUMSESSIONS_ASYNC flag) again to obtain the most up-to-date session list with all the expired sessions deleted, new sessions added, and updated sessions. Subsequent calls to EnumSessions will not generate an enumeration request. Enumeration requests will be generated periodically by DirectPlay until the process is either cancelled by calling EnumSessions with the DPENUMSESSIONS_STOPASYNC flag, a session is opened using the IDirectPlay4::Open method, or the DirectPlay object is released.

To change the description of the sessions being enumerated asynchronously, you must stop the asynchronous enumeration and then start it up again. For example, you cannot start an enumeration without a password and then later, during an asychronous call, add a password and have it begin enumerating private sessions using that password. Conversely, if you specify the correct password, then change to an incorrect password, you will still enumerate the session. However, you can call EnumSessions with the DPENUMSESSIONS_STOPASYNC flag, then specify the password, and the private session will be enumerated.

Once enumeration of the available sessions is complete, the application can join one of the sessions using the IDirectPlay4::Open method. Only sessions in the session cache can be opened. An application may attempt to open a session that has expired since the last time EnumSessions was called in which case an error will be returned.

No authentication is performed when enumerating sessions on a secure server. All sessions that meet the enumeration criteria will be returned. Authentication will be done when the application attempts to open one of these sessions with IDirectPlay4::Open or IDirectPlay4::SecureOpen.

If the application was not started by a lobby, the service provider can display a dialog box asking the user for information (such as a phone number or IP address) in order to perform the enumeration on the network, if that information was not provided in IDirectPlay4::InitializeConnection. If the service provider can do a broadcast enumeration and requires no extra information from the user, no dialog box will appear. If the user cancels a service provider dialog box, EnumSessions returns DPERR_USERCANCEL.

See Also

DPSESSIONDESC2, IDirectPlay4::Open, IDirectPlay4::SecureOpen


IDirectPlay4::GetCaps

IDirectPlay4 Interface

Obtains the capabilities of this DirectPlay object.

Syntax

HRESULT GetCaps(
  LPDPCAPS lpDPCaps,
  DWORD dwFlags
  );

Parameters

lpDPCaps
Pointer to a DPCAPS structure that will be filled with the capabilities of the DirectPlay object. The dwSize member of the DPCAPS structure must be filled in before using IDirectPlay4::GetCaps.
dwFlags
If this parameter is set to 0, the capabilities will be computed for nonguaranteed messaging.
DPGETCAPS_GUARANTEED
Retrieves the capabilities for a guaranteed message delivery.

Return Value

Returns DP_OK if successful, or one of the following error values otherwise:
DPERR_INVALIDOBJECT
DPERR_INVALIDPARAMS

Remarks

This method returns the capabilities of the current session, while the IDirectPlay4::GetPlayerCaps method returns the capabilities of the requested player.

Note that capabilities indicating which aspects of SendEx are supported are not available until after the session has been opened. If the application hosting the session has specified the DPSESSION_DIRECTPLAYPROTOCOL flag in the DPSESSIONDESC2 structure, then all the SendEx options are supported.

See Also

DPCAPS, IDirectPlay4::GetPlayerCaps, IDirectPlay4::Send


IDirectPlay4::GetGroupConnectionSettings

IDirectPlay4 Interface

Retrieves the connection settings for a group from the DPLCONNECTION structure. Any sessions launched from this group will use these settings. This method can only be used in a lobby session.

Syntax

HRESULT GetGroupConnectionSettings(
  DWORD dwFlags,
  DPID idGroup,
  LPVOID lpData,
  LPDWORD lpdwDataSize
  );

Parameters

dwFlags
Not used. Must be zero.
idGroup
The DPID of the group to get the connection settings for.
lpData
Pointer to a buffer into which the DPLCONNECTION structure and all its data will be copied. Set this parameter to NULL to request only the size of data. The lpdwDataSize parameter will be set to the minimum size required to hold the data.
lpdwDataSize
Pointer to a variable that is initialized to the size of the buffer before calling this method. After the method returns, this parameter will be set to the size, in bytes, of the data. If the buffer was too small (DPERR_BUFFERTOOSMALL), then this parameter will be set to the minimum buffer size required.

Return Value

Returns DP_OK if successful, or one of the following error values otherwise:
DPERR_ACCESSDENIED
DPERR_BUFFERTOOSMALL
DPERR_INVALIDGROUP
DPERR_INVALIDFLAGS
DPERR_INVALIDPARAMS
DPERR_UNSUPPORTED

Remarks

group connection settings are only relevant for staging area groups.

You can see if a game has been launched by looking at the guidInstance data member of the DPSESSIONDESC2 structure, whose pointer is contained in the lpSessionDesc data member of the DPLCONNECTION structure returned by this method. The guidInstance will be GUID_NULL until a game has been launched.

See Also

DPLCONNECTION, IDirectPlayLobby3::RunApplication, IDirectPlay4::SetGroupConnectionSettings, DPGROUP_STAGINGAREA


IDirectPlay4::GetGroupData

IDirectPlay4 Interface

Retrieves an application-specific data block that was associated with a group ID by using IDirectPlay4::SetGroupData.

Syntax

HRESULT GetGroupData(
  DPID idGroup,
  LPVOID lpData,
  LPDWORD lpdwDataSize,
  DWORD dwFlags
  );

Parameters

idGroup
group ID for which data is being requested.
lpData
Pointer to a buffer where the application-specific group data is to be written. Set this parameter to NULL to request only the size of data. The lpdwDataSize parameter will be set to the size required to hold the data.
lpdwDataSize
Pointer to a variable that is initialized to the size of the buffer before calling the method. After the method returns, this parameter will be set to the size, in bytes, of the group data. If the buffer was too small (DPERR_BUFFERTOOSMALL), then this parameter will be set to the buffer size required.
dwFlags
If this parameter is set to 0, the remote data will be retrieved.
DPGET_LOCAL
Retrieves the local data set by this application
DPGET_REMOTE
Retrieves the current data from the remote shared data space.

Return Value

Returns DP_OK if successful, or one of the following error values otherwise:
DPERR_BUFFERTOOSMALL
DPERR_INVALIDGROUP
DPERR_INVALIDOBJECT
DPERR_INVALIDPARAMS
DPERR_INVALIDPLAYER

Remarks

DirectPlay can maintain two types of group data: local and remote. The application must specify which type of data to retrieve. Local data was set by this DirectPlay object by using the DPSET_LOCAL flag. Remote data might have been set by any application in the session by using the DPSET_REMOTE flag.

See Also

IDirectPlay4::SetGroupData


IDirectPlay4::GetGroupFlags

IDirectPlay4 Interface

Returns the flags describing the group.

Syntax

HRESULT GetGroupFlags(
  DPID idGroup,
  LPDWORD lpdwFlags
  );

Parameters

idGroup
The DPID of the group whose flag settings are to be retrieved.
lpdwFlags
Pointer to a DWORD to be set to the group flag settings. Can be one or more of the following:
DPGROUP_LOCAL - the group was created by this application. If this flag is not specified, the group is a remote group.
DPGROUP_STAGINGAREA - the group is a staging area.

Return Value

Returns DP_OK if successful, or one of the following error values otherwise:
DPERR_INVALIDGROUP
DPERR_INVALIDPARAMS

See Also

IDirectPlay4::CreateGroup


IDirectPlay4::GetGroupName

IDirectPlay4 Interface

Returns the name associated with a group.

Syntax

HRESULT GetGroupName(
  DPID idGroup,
  LPVOID lpData,
  LPDWORD lpdwDataSize
  );

Parameters

idGroup
ID of the group whose name is being requested.
lpData
Pointer to a buffer where the name data is to be written. Set this parameter to NULL to request only the size of data. lpdwDataSize will be set to the size required to hold the data.
lpdwDataSize
Pointer to a variable that is initialized to the size of the buffer before calling the method. After the method returns, this parameter will be set to the size, in bytes, of the name data. If the buffer was too small (DPERR_BUFFERTOOSMALL), then this parameter will be set to the buffer size that is required.

Return Value

Returns DP_OK if successful, or one of the following error values otherwise:
DPERR_BUFFERTOOSMALL
DPERR_INVALIDGROUP
DPERR_INVALIDOBJECT
DPERR_INVALIDPARAMS
DPERR_INVALIDPLAYER

Remarks

After the method returns, the pointer lpData should be cast to the DPNAME structure to read the group name data.

See Also

DPNAME, IDirectPlay4::SetGroupName


IDirectPlay4::GetGroupOwner

IDirectPlay4 Interface

Returns the DPID of the current owner of the group. This method is only valid in a lobby session.

Syntax

HRESULT GetGroupOwner(
  DPID idGroup,
  LPDPID lpidOwner
  );

Parameters

idGroup
ID of the group whose owner is being requested.
lpidOwner
Pointer to a DPID to be set to the ID of the owner.

Return Value

Returns DP_OK if successful, or one of the following error values otherwise:
DPERR_GENERIC
DPERR_INVALIDGROUP
DPERR_INVALIDPARAMS
DPERR_UNAVAILABLE

See Also

IDirectPlay4::SetGroupOwner


IDirectPlay4::GetGroupParent

IDirectPlay4 Interface

Returns the DPID of the parent of the group.

Syntax

HRESULT GetGroupParent(
  DPID idGroup,
  LPDPID lpidParent
  );

Parameters

idGroup
ID of the group whose parent is being requested.
lpidParent
Pointer to a DPID to be set to the ID of the parent group. If this method returns a parent ID of zero, the group is a root group.

Return Value

Returns DP_OK if successful, or one of the following error values otherwise:
DPERR_INVALIDGROUP
DPERR_INVALIDPARAMS

See Also

IDirectPlay4::CreateGroupInGroup


IDirectPlay4::GetMessageCount

IDirectPlay4 Interface

Queries for the number of messages in the receive queue for a specific local player.

Syntax

HRESULT GetMessageCount(
  DPID idPlayer,
  LPDWORD lpdwCount
  );

Parameters

idPlayer
ID of the player whose message count is requested. The player must be local.
lpdwCount
Pointer to a variable that will be set to the message count when this method returns.

Return Value

Returns DP_OK if successful, or one of the following error values otherwise:
DPERR_INVALIDOBJECT
DPERR_INVALIDPARAMS
DPERR_INVALIDPLAYER

See Also

IDirectPlay4::Receive


IDirectPlay4::GetMessageQueue

IDirectPlay4 Interface

Determines how many messages are in the send or receive queue. By monitoring the status of the send queue, an application can regulate how many messages to send to other players in the session based on the bandwidth of the underlying network.

Note that the queue size on a machine is for all players in the session on that machine, not for an individual player, if there is more than one player in the session on a single machine.

Syntax

HRESULT GetMessageQueue(
  DPID idFrom,
  DPID idTo,
  DWORD dwFlags,
  LPDWORD lpdwNumMsgs,
  LPDWORD lpdwNumBytes
  );

Parameters

idFrom
ID of the player sending the messages whose queue status is desired. Zero returns information about all sent messages. If idTo is also specified, only information about messages that are both from the player with idFrom and to the player with idTo is returned.
idTo
ID of the player sent the messages whose queue status is desired. Zero returns information about all sent messages. If idFrom is also specified, only information about messages that are both from the player with idFrom and to the player with idTo is returned. Note that you cannot specify a group ID for idTo.
dwFlags
Determines what type of information about the queue to obtain. Default (dwFlags = 0) returns information about the send queue. Can be one, and only one, of the following values:
DPMESSAGEQUEUE_SEND
Retrieves information about the send queue.
DPMESSAGEQUEUE_RECEIVE
Retrieves information about the receive queue.
lpdwNumMsgs
Pointer to a DWORD that will be filled with the number of messages in the queue. If NULL, no value is returned.
lpdwNumBytes
Pointer to a DWORD that will be filled with the total number of bytes in the queue. If NULL, no value is returned.

Return Value

Returns DP_OK if successful, or one of the following error values otherwise:
DPERR_INVALIDFLAGS
DPERR_INVALIDPARAMS
DPERR_INVALIDPLAYER
DPERR_UNSUPPORTED

Returns DPERR_INVALIDPLAYER if you check the receive queue (DPMESSAGEQUEUE_RECEIVE) while specifying idTo for a remote player. Returns DPERR_INVALIDPLAYER if you check the send queue (DPMESSAGEQUEUE_SEND) while specifying idFrom for a remote player. Returns DPERR_INVALIDFLAGS if you specify both the receive queue and the send queue flags (dwFlags = DPMESSAGEQUEUE_RECEIVE|DPMESSAGEQUEUE_SEND). Returns DPERR_UNSUPPORTED if you attempt to check the send queue when DirectPlay protocol is not turned on and the service provider does not support checking the send queue.

Remarks

You cannot check message queues on remote machines.

See Also

IDirectPlay4::Send, IDirectPlay4::SendEx


IDirectPlay4::GetPlayerAccount

IDirectPlay4 Interface

In a secure session, can be called by the session host to obtain account information about the specified player.

Syntax

HRESULT GetPlayerAccount(
  DPID idPlayer,
  DWORD dwFlags,
  LPVOID lpData,
  LPDWORD lpdwDataSize
  );

Parameters

idPlayer
The DPID of the player whose account information is to be retrieved.
dwFlags
Not used. Must be zero.
lpData
A pointer to a buffer (allocated by the application) where the account data is to be written. A DPACCOUNTDESC structure will be copied as well as any data referenced by the members of the structure; therefore, the number of bytes copied is variable. Cast the lpData parameter to LPDPACCOUNTDESC in order to read the name. By passing NULL, the application can request the number of bytes required be put in the lpdwDataSize parameter. The application can then allocate the space and call this method again.
lpdwDataSize
A pointer to a DWORD that is initialized with the size of the buffer. After the method returns, lpdwDataSize will be set to the number of bytes that were actually copied into the buffer. If the buffer was too small the method returns DPERR_BUFFERTOOSMALL, and lpdwDataSize is set to the minimum required buffer size.

Return Value

Returns DP_OK if successful, or one of the following error values otherwise:
DPERR_ACCESSDENIED
DPERR_BUFFERTOOSMALL
DPERR_INVALIDFLAGS
DPERR_INVALIDPARAMS
DPERR_INVALIDPLAYER

Remarks

The information returned by GetPlayerAccount uniquely identifies an account. This information can be used to record the transactions or other activities of a logged-in player.

See Also

IDirectPlay4::SecureOpen


IDirectPlay4::GetPlayerAddress

IDirectPlay4 Interface

Retrieves the DirectPlay Address for a player.

The DirectPlay Address is a network address for a player using a specific service provider. You should call the IDirectPlayLobby3::EnumAddress method to parse the DirectPlay Address buffer retrieved by IDirectPlay4::GetPlayerAddress.

If this method is called on a local player, it returns the network address of the computer if it is available. In some cases, more than one address can be returned (for example, with TCP/IP where the computer has both a network card and a dial-up Internet connection).

Syntax

HRESULT GetPlayerAddress(
  DPID idPlayer,
  LPVOID lpData,
  LPDWORD lpdwDataSize
  );

Parameters

idPlayer
Player ID that the address is being requested for. Pass in zero to obtain a list of valid address options for a service provider (for example, a list of valid modem choices for the modem-to-modem service provider).
lpData
Pointer to a buffer where the DirectPlay Address is to be written. Set this parameter to NULL to request only the size of data. The lpdwDataSize parameter will be set to the size required to hold the data.
lpdwDataSize
Pointer to a variable that is initialized to the size of the buffer before calling this method. After the method returns, this parameter will be set to the size, in bytes, of the DirectPlay Address data. If the buffer was too small, then this parameter will be set to the buffer size that is required and the method will return DPERR_BUFFERTOOSMALL.

Return Value

Returns DP_OK if successful, or one of the following error values otherwise:
DPERR_BUFFERTOOSMALL
DPERR_INVALIDOBJECT
DPERR_INVALIDPARAMS
DPERR_INVALIDPLAYER
DPERR_UNAVAILABLE

This method returns DPERR_UNAVAILABLE if the address for the requested player ID is not available.

Remarks

To get a list of valid modem choices, pass in zero for the idPlayer parameter. A list of modem choices will be returned as a list of ANSI or Unicode strings with a zero-length string at the end.

The DirectPlay Address will contain both ANSI and Unicode strings with the address, regardless of what interface this method is called on.

For more information about the DirectPlay Address, see DirectPlay Address.

See Also

IDirectPlayLobby3::EnumAddress


IDirectPlay4::GetPlayerCaps

IDirectPlay4 Interface

Retrieves the current capabilities of a specified player.

Syntax

HRESULT GetPlayerCaps(
  DPID idPlayer,
  LPDPCAPS lpPlayerCaps,
  DWORD dwFlags
  );

Parameters

idPlayer
Player ID for which the capabilities should be computed.
lpPlayerCaps
Pointer to a DPCAPS structure that will be filled with the capabilities. The dwSize member of the DPCAPS structure must be filled in before using IDirectPlay4::GetPlayerCaps.
dwFlags
If this parameter is set to 0, the capabilities will be computed for nonguaranteed messaging.
DPGETCAPS_GUARANTEED
Retrieves the capabilities for a guaranteed message delivery.

Return Value

Returns DP_OK if successful, or one of the following error values otherwise:
DPERR_INVALIDOBJECT
DPERR_INVALIDPARAMS
DPERR_INVALIDPLAYER

Remarks

This method returns the capabilities of the requested player, while the IDirectPlay4::GetCaps method returns the capabilities of the current session.

See Also

DPCAPS, IDirectPlay4::GetCaps, IDirectPlay4::Send


IDirectPlay4::GetPlayerData

IDirectPlay4 Interface

Retrieves an application-specific data block that was associated with a player ID by using IDirectPlay4::SetPlayerData.

Syntax

HRESULT GetPlayerData(
  DPID idPlayer,
  LPVOID lpData,
  LPDWORD lpdwDataSize,
  DWORD dwFlags
  );

Parameters

idPlayer
ID of the player for which data is being requested.
lpData
Pointer to a buffer where the application-specific player data is to be written. Set this parameter to NULL to request only the size of data. The lpdwDataSize parameter will be set to the size required to hold the data.
lpdwDataSize
Pointer to a variable that is initialized to the size of the buffer before calling this method. After the method returns, this parameter will be set to the size, in bytes, of the player data. If the buffer was too small (DPERR_BUFFERTOOSMALL), then this parameter will be set to the buffer size required.
dwFlags
If this parameter is set to 0, the remote data will be retrieved.
DPGET_LOCAL
Retrieves the local data set by this application.
DPGET_REMOTE
Retrieves the current data from the remote shared data space.

Return Value

Returns DP_OK if successful, or one of the following error values otherwise:
DPERR_BUFFERTOOSMALL
DPERR_INVALIDFLAGS
DPERR_INVALIDOBJECT
DPERR_INVALIDPLAYER

Remarks

DirectPlay can maintain two types of player data: local and remote. The application must specify which type of data to retrieve. Local data was set by this DirectPlay object by using the DPSET_LOCAL flag. Remote data might have been set by any application in the session by using the DPSET_REMOTE flag.

See Also

IDirectPlay4::SetPlayerData


IDirectPlay4::GetPlayerFlags

IDirectPlay4 Interface

Returns the flags describing the player.

Syntax

HRESULT GetPlayerFlags(
  DPID idPlayer,
  LPDWORD lpdwFlags
  );

Parameters

idPlayer
The DPID of the player whose flag settings are to be retrieved.
lpdwFlags
Pointer to a DWORD to be set to the player's flag settings. Can be one or more of the following:
DPPLAYER_LOCAL - the player was created by this application. If this flag is not specified, the player is a remote player.
DPPLAYER_SERVERPLAYER - the player is a server player for client/server communications.
DPPLAYER_SPECTATOR - the player was created as a spectator.

Return Value

Returns DP_OK if successful, or one of the following error values otherwise:
DPERR_INVALIDPARAMS
DPERR_INVALIDPLAYER

See Also

IDirectPlay4::CreatePlayer


IDirectPlay4::GetPlayerName

IDirectPlay4 Interface

Retrieves the name associated with a player.

Syntax

HRESULT GetPlayerName(
  DPID idPlayer,
  LPVOID lpData,
  LPDWORD lpdwDataSize
  );

Parameters

idPlayer
ID of the player whose name is requested.
lpData
Pointer to a buffer where the name data is to be written. Set this parameter to NULL to request only the size of data. The lpdwDataSize parameter will be set to the size required to hold the data.
lpdwDataSize
Pointer to a variable that is initialized to the size of the buffer before calling this method. After the method returns, this parameter will be set to the size, in bytes, of the name data. If the buffer was too small (DPERR_BUFFERTOOSMALL), then this parameter will be set to the buffer size required.

Return Value

Returns DP_OK if successful, or one of the following error values otherwise:
DPERR_BUFFERTOOSMALL
DPERR_INVALIDOBJECT
DPERR_INVALIDPLAYER

Remarks

After this method returns, the pointer lpData should be cast to the DPNAME structure to read the group name data.

See Also

DPNAME, IDirectPlay4::SetPlayerName


IDirectPlay4::GetSessionDesc

IDirectPlay4 Interface

Retrieves the properties of the current open session.

Syntax

HRESULT GetSessionDesc(
  LPVOID lpData,
  LPDWORD lpdwDataSize
  );

Parameters

lpData
Pointer to a buffer where the session description data is to be written. Set this parameter to NULL to request only the size of data. The lpdwDataSize parameter will be set to the size required to hold the data.
lpdwDataSize
Pointer to a variable that is initialized to the size of the buffer before calling this method. After the method returns, this parameter will be set to the size, in bytes, of the session data. If the buffer was too small (DPERR_BUFFERTOOSMALL), then this parameter will be set to the buffer size required. If this parameter is NULL, the method returns DPERR_INVALIDPARAM.

Return Value

Returns DP_OK if successful, or one of the following error values otherwise:
DPERR_BUFFERTOOSMALL
DPERR_INVALIDOBJECT
DPERR_INVALIDPARAMS
DPERR_NOCONNECTION

Remarks

After this method returns, the pointer lpData should be cast to the DPSESSIONDESC2 structure to read the session description data.

See Also

DPSESSIONDESC2, IDirectPlay4::EnumSessions, IDirectPlay4::Open


IDirectPlay4::Initialize

IDirectPlay4 Interface

This method is provided for compliance with the COM protocol.

Syntax

HRESULT Initialize(
  LPGUID lpGUID
  );

Parameters

lpGUID
Pointer to the globally unique identifier (GUID) used as the interface identifier.

Return Value

Returns DPERR_ALREADYINITIALIZED.

Remarks

Because the DirectPlay object is initialized when it is created, this method always returns the DPERR_ALREADYINITIALIZED return value.

See Also

IUnknown::AddRef, IUnknown::QueryInterface


IDirectPlay4::InitializeConnection

IDirectPlay4 Interface

Initializes a DirectPlay connection. All the information about the connection, including the service provider to use, the network address of the server, and the GUID of the session, is passed in through the lpConnection parameter.

Syntax

HRESULT InitializeConnection(
  LPVOID lpConnection,
  DWORD dwFlags
  );

Parameters

lpConnection
Pointer to a buffer that contains all the information about the connection to be initialized as a DirectPlay Address.
dwFlags
Not used. Must be zero.

Return Value

Returns DP_OK if successful, or one of the following error values otherwise:
DPERR_ALREADYINITIALIZED
DPERR_INVALIDFLAGS
DPERR_INVALIDPARAMS
DPERR_UNAVAILABLE

This method returns DPERR_ALREADYINITIALIZED if InitializeConnection has previously been called on this object. It returns DPERR_UNAVAILABLE if the service provider could not be initialized. This can be because the resources necessary to operate this service provider are not present (for example, TCP/IP stack not present).

Remarks

The lpConnection parameter supplied to this method can be obtained from the IDirectPlay4::EnumConnections method, or the application can create one directly using the IDirectPlayLobby3::CreateCompoundAddress method.

This method loads and initializes the appropriate service provider. The lpConnection parameter is passed on to the service provider, which extracts and saves any relevant information. This information is used when the IDirectPlay4::EnumSessions or IDirectPlay4::Open method is called so that the service provider does not pop up a dialog box asking for that information.

This method replaces DirectPlayCreate as the means of binding a service provider to a DirectPlay object. The primary benefits of InitializeConnection are that you can override the service provider dialogs, and you can initialize a lobby provider.

See Also

IDirectPlay4::EnumConnections, IDirectPlayLobby3::CreateCompoundAddress, DirectPlay Address


IDirectPlay4::Open

IDirectPlay4 Interface

Used to join a session that has been enumerated by a previous call to IDirectPlay4::EnumSessions or to create a new session that other users can enumerate and join.

Syntax

HRESULT Open(
  LPDPSESSIONDESC2 lpsd,
  DWORD dwFlags
  );

Parameters

lpsd
Pointer to the DPSESSIONDESC2 structure describing the session to be created or joined. If a session is being joined, then only the dwSize, guidInstance, and lpszPassword data members need to be specified. A password need only be supplied if the enumerated session had the DPSESSION_PASSWORD flag set.
If a session is being created, then the application must completely fill out the DPSESSIONDESC2 structure with the properties of the sessions to be created. The guidInstance will be generated by DirectPlay.
dwFlags
One and only one of the following flags:
DPOPEN_CREATE
Create a new instance of an application session. The local computer will be the name server and host of the session.
DPOPEN_JOIN
Join an existing instance of an application session for the purpose of participating. The application will be able to create players and send and receive messages.
DPOPEN_RETURNSTATUS
If this flag is specified, the method will not display any dialog boxes showing the connection progress status. If the connection cannot be made immediately, the method will return with the DPERR_CONNECTING error. The application must keep calling Open until either DP_OK is returned, indicating successful completion, or some other error code is returned, indicating an error.

Return Value

Returns DP_OK if successful, or one of the following error values otherwise:
DPERR_ACCESSDENIED
DPERR_ALREADYINITIALIZED
DPERR_AUTHENTICATIONFAILED
DPERR_CANNOTCREATESERVER
DPERR_CANTLOADCAPI
DPERR_CANTLOADSECURITYPACKAGE
DPERR_CANTLOADSSPI
DPERR_CONNECTING
DPERR_CONNECTIONLOST
DPERR_ENCRYPTIONFAILED
DPERR_ENCRYPTIONNOTSUPPORTED
DPERR_INVALIDFLAGS
DPERR_INVALIDPARAMS
DPERR_INVALIDPASSWORD
DPERR_LOGONDENIED
DPERR_NOCONNECTION
DPERR_NONEWPLAYERS
DPERR_NOSESSIONS
DPERR_SIGNFAILED
DPERR_TIMEOUT
DPERR_UNINITIALIZED
DPERR_USERCANCEL

This method returns DPERR_ALREADYINITIALIZED if there is already an open session on this DirectPlay object. It returns DPERR_TIMEOUT if the session did not respond to the Open request. It returns DPERR_USERCANCEL if the user cancelled the enumeration process(usually by cancelling a service provider dialog box). It returns DPERR_NOSESSIONS if it is called to join an existing session but the session isn't in the internal session list (or the session guidInstance is corrupted).

Remarks

Once an application has joined a session, it can create a player and start communicating with other players in the session. The application will not receive any messages nor can it send any messages on this DirectPlay object until it creates a local player using IDirectPlay4::CreatePlayer.

In order to have two sessions open simultaneously, the application must create two DirectPlay objects and open a session on each one.

To join a session, it is only necessary to fill in the dwSize and guidInstance members of the DPSESSIONDESC2 structure. The lpszPassword member must also be filled in if the session was marked as password protected. An enumerated session will have the DPSESSION_PASSWORDREQUIRED flag set if it requires a password.

If joining a secure session, you must use SecureOpen to provide login credentials. The enumerated session will have the DPSESSION_SECURESERVER flag set if it requires credentials.

If you specify the DPSESSION_SECURESERVER flag in the DPSESSIONDESC2 structure, the session will be opened with the default security package, NTLM (NT LAN Manager). To specify an alternate security package, use SecureOpen.

When an application attempts to join a session, the server can reject the Open request or ignore it (in which case Open will time-out). Attempting to join a session where new players are disabled, joining is disabled, the player limit has been reached, or an incorrect password is supplied will result in a DPERR_NONEWPLAYERS or DPERR_INVALIDPASSWORD error.

See Also

DPSESSIONDESC2, IDirectPlay4::Close, IDirectPlay4::SecureOpen, IDirectPlay4::EnumSessions


IDirectPlay4::Receive

IDirectPlay4 Interface

Retrieves a message from the message queue.

Syntax

HRESULT Receive(
  LPDPID lpidFrom,
  LPDPID lpidTo,
  DWORD dwFlags,
  LPVOID lpData,
  LPDWORD lpdwDataSize
  );

Parameters

lpidFrom
Pointer to a DPID that will be set to the sender's player ID when this method returns. If the DPRECEIVE_FROMPLAYER flag is specified, this variable must be initialized with the player ID before calling this method.
lpidTo
Pointer to a DPID that will be set to the receiver's player ID when this method returns. If the DPRECEIVE_TOPLAYER flag is specified, this variable must be initialized with the player ID before calling this method.
dwFlags
One or more of the following control flags can be set. By default (dwFlags = 0), the first available message will be retrieved.
DPRECEIVE_ALL
Returns the first available message. This is the default.
DPRECEIVE_PEEK
Returns a message as specified by the other flags, but does not remove it from the message queue. This flag must be specified if lpData is NULL.
DPRECEIVE_TOPLAYER and DPRECEIVE_FROMPLAYER
If both DPRECEIVE_TOPLAYER and DPRECEIVE_FROMPLAYER are specified, Receive will only return messages that are 1) sent to the player specified by lpidTo and 2) sent from the player specified by lpidFrom. Note that both conditions must be met.
If only DPRECEIVE_TOPLAYER is specified, Receive will only return messages sent to the player specified by lpidTo.
If only DPRECEIVE_FROMPLAYER is specified, Receive will only return messages sent from the player specified by lpidFrom.
If neither DPRECEIVE_TOPLAYER nor DPRECEIVE_FROMPLAYER is set, Receive will return the first available message.
lpData
Pointer to a buffer where the message data is to be written. Set this parameter to NULL to request only the size of data. The lpdwDataSize parameter will be set to the size required to hold the data. If the message came from player ID DPID_SYSMSG, the application should cast lpData to DPMSG_GENERIC and check the dwType member to see what type of system message it is before processing it.
lpdwDataSize
Pointer to a DWORD that is initialized to the size of the buffer before calling this method. After the method returns, this parameter will be set to the number of bytes copied into the buffer. If the buffer was too small (DPERR_BUFFERTOOSMALL), then this parameter will be set to the buffer size required. The message order in the receive queue can change between calls to IDirectPlay4::Receive. Therefore, it is possible to get a DPERR_BUFFERTOOSMALL error again even after the application has allocated the memory requested from the previous call to IDirectPlay4::Receive. It is best to keep reallocating memory until a DPERR_BUFFERTOOSMALL error is not received.

Return Value

Returns DP_OK if successful, or one of the following error values otherwise:
DPERR_BUFFERTOOSMALL
DPERR_GENERIC
DPERR_INVALIDOBJECT
DPERR_INVALIDPARAMS
DPERR_INVALIDPLAYER
DPERR_NOMESSAGES

Remarks

Any message received from a player ID defined as DPID_SYSMSG is a system message used to notify the application of a change in the session. In those cases, the lpData of system messages should be cast to DPMSG_GENERIC and the dwType member should be examined to see what specific system message it is.

Messages that were sent to a player ID defined as DPID_ALLPLAYERS or to a group ID still appear to come from the sending player ID. An application will only receive messages directed to a local player. A player cannot receive a message in which the values pointed to by lpidFrom and lpidTo are equal.

If DPSESSION_NOMESSAGEID is specified in the session description, the lpidFrom will always be 0xFFFFFFFF and the lpidTo value is arbitrary.

All the service providers shipped with DirectPlay perform integrity checks on the data to protect against corruption. Any message retrieved using Receive is guaranteed to be free from corruption.

See Also

DPMSG_GENERIC, IDirectPlay4::Send


IDirectPlay4::SecureOpen

IDirectPlay4 Interface

Creates or joins a secure session. When joining a secure session, use this method to supply login credentials.

When creating a new session, the host computer can specify an alternate security package to use. When joining a session, a computer can specify a user name and password.

Syntax

HRESULT IDirectPlay4::SecureOpen(
  LPCDPSESSIONDESC2 lpsd,
  DWORD dwFlags,
  LPCDPSECURITYDESC lpSecurity,
  LPCDPCREDENTIALS lpCredentials
  )

Parameters

lpsd
Pointer to the DPSESSIONDESC2 structure describing the session to be created or joined. If a session is to be joined, then only the guidInstance and lpszPassword members need to be specified. The password need only be supplied if the enumerated session had the DPSESSION_PASSWORDREQUIRED flag set.
If a session is to be created, then the application must completely fill out the DPSESSIONDESC2 structure with the properties of the sessions to be created. The guidInstance will be generated by DirectPlay. NOTE: The DPSESSION_SECURESERVER flag must be set to indicate that all computers attempting to open the session must be authenticated.

If you don't specify the DPSESSION_SECURESERVER flag when filling out the DPSESSIONDESC2 structure, SecureOpen will open an unsecure session, just as if you had called Open.

dwFlags
One of the following flags:
DPOPEN_CREATE
Creates a new instance of a secured session.
DPOPEN_JOIN
Joins an existing instance of a secured session.
DPOPEN_RETURNSTATUS
If this flag is specified, the method will not display any dialog boxes showing the connection progress status. If the connection cannot be made immediately, the method will return with the DPERR_CONNECTING error. The application must keep calling SecureOpen until either DP_OK is returned, indicating successful completion, or some other error code is returned, indicating an error.
lpSecurity
Pointer to a DPSECURITYDESC structure containing the security package to use. Set this parameter to NULL to use the default security package (NT LAN Manager) and CryptoAPI package (Microsoft RSA Base Cryptographic Provider). Relevant only when creating a session. Must be set to NULL when joining a session.
lpCredentials
Pointer to a DPCREDENTIALS structure containing the logon name, password, and domain to be authenticated on the server. NULL if there are no credentials. Credentials are ignored when creating a session.

Return Value

Returns DP_OK if successful or one of the following error values:
DPERR_ACCESSDENIED
DPERR_ALREADYINITIALIZED
DPERR_AUTHENTICATIONFAILED
DPERR_CANNOTCREATESERVER
DPERR_CANTLOADCAPI
DPERR_CANTLOADSECURITYPACKAGE
DPERR_CANTLOADSSPI
DPERR_CONNECTING
DPERR_CONNECTIONLOST
DPERR_ENCRYPTIONFAILED
DPERR_ENCRYPTIONNOTSUPPORTED
DPERR_INVALIDFLAGS
DPERR_INVALIDPARAMS
DPERR_INVALIDPASSWORD
DPERR_LOGONDENIED
DPERR_NOCONNECTION
DPERR_NONEWPLAYERS
DPERR_SIGNFAILED
DPERR_TIMEOUT
DPERR_UNINITIALIZED
DPERR_USERCANCEL

This method DPERR_LOGONDENIED after being called with invalid creadentials or without credentials when credentials are required. The application must collect the user's credentials and call SecureOpen again.

Remarks

When joining a session, first call SecureOpen with no credentials. If the method returns DPERR_LOGONDENIED, then the application must collect the user name and password from the user and call SecureOpen again, passing in the user's credentials through the lpCredentials parameter. If the method returns DP_OK, then the player was able to login with the credentials he or she had specified earlier during system logon (network logon in NTLM).

See Also

IDirectPlay4::Open


IDirectPlay4::Send

IDirectPlay4 Interface

Sends a message to another player, to a group of players, or to all players in the session. To send a message to another player, specify the target player's player ID. To send a message to a group of players, send the message to the group ID assigned to the group. To send a message to the entire session, send the message to the player ID DPID_ALLPLAYERS. Messages can be sent using either a guaranteed or nonguaranteed protocol on a per message basis. If the session is being hosted on a secure server, messages can be sent encrypted (to ensure privacy) or digitally signed (to ensure authenticity) on a per message basis.

Syntax

HRESULT Send(
  DPID idFrom,
  DPID idTo,
  DWORD dwFlags,
  LPVOID lpData,
  DWORD dwDataSize
  );

Parameters

idFrom
ID of the sending player. The player ID must correspond to one of the local players on this computer.
idTo
The destination ID of the message. To send a message to another player, specify the ID of the player. To send a message to all the players in a group, specify the ID of the group. To send a message to all the players in the session, use the constant symbol DPID_ALLPLAYERS. To send a message to the server player, specify the constant symbol DPID_SERVERPLAYER. A player cannot send a message to itself.
dwFlags
Indicates how the message should be sent. By default (dwFlags = 0), the message is sent nonguaranteed.
DPSEND_ENCRYPTED
Sends the messages encrypted. This can only be done in a secure session. This flag can only be used if the DPSEND_GUARANTEED flag is also set. The message will be sent as a DPMSG_SECUREMESSAGE system message.
DPSEND_GUARANTEED
Sends the message by using a guaranteed method of delivery.
DPSEND_SIGNED
Sends the message with a digital signature. This can only be done in a secure session. This flag can only be used if the DPSEND_GUARANTEED flag is also set. The message will be sent as a DPMSG_SECUREMESSAGE system message.
lpData
Pointer to the data being sent.
dwDataSize
Length of the data being sent.

Return Value

Returns DP_OK if successful or one of the following error values:
DPERR_BUSY
DPERR_CONNECTIONLOST
DPERR_INVALIDPARAMS
DPERR_INVALIDPLAYER
DPERR_NOTLOGGEDIN
DPERR_SENDTOOBIG

This method returns DPERR_INVALIDPARAMS if the encrypted or signed flag is specified for a message that is not also specified as guaranteed. It returns DPERR_NOTLOGGEDIN when the client application tries to send a secure message without first logging in.

If a message is sent to a group, a return value of DP_OK does not necessarily mean that every player in the group got the message. If the message was sent guaranteed, DP_OK means that DirectPlay made a best effort to send it to all the players in the group. Typically, players that don't receive the message are killed because there is a problem with their connection.

Remarks

Use IDirectPlay4::SendEx for asynchronous send options.

Messages can be sent guaranteed or nonguaranteed. By default, messages are sent nonguaranteed, which means that DirectPlay does no verification that the message reached the intended recipient. Sending a guaranteed message takes much longer — a minimum of two to three times longer than nonguaranteed messages. Applications should try to minimize sending guaranteed messages as much as possible and to design the application to tolerate lost messages. All the service providers shipped with DirectPlay perform integrity checks on the data to protect against corruption. Any message sent using this method is guaranteed to be free from corruption.

System messages are always sent guaranteed, whether or not the service provider natively supports guaranteed messages, and whether or not you set the DirectPlay protocol flag. The DirectPlay protocol will be used automatically to send system messages guaranteed.

For non-system messages, if an application sets the DirectPlay protocol flag and sends a message guaranteed (by setting the DPSEND_GUARANTEED flag), the message will be sent guaranteed whether the service provider supports guaranteed messages or not.

For non-system messages, if an application does not set the DirectPlay protocol flag and sends a message guaranteed, the message will be sent guaranteed only if the service provider supports it. If the service provider does not support guaranteed messages, the message will not be sent guaranteed, regardless of the DPSEND_GUARANTEED flag.

An application invokes the DirectPlay protocol by setting the DPSESSION_DIRECTPLAYPROTOCOL flag when creating a session.

A player cannot send a message to itself. If a player sends a message to a group that it is part of or to DPID_ALLPLAYERS, it will not receive a copy of that message. The exception to this rule is if the DPSESSION_NOMESSAGEID was specified in the session description (DPSESSIONDESC2). Then it is possible for a player to receive a message that it sent to a group. Because there is no DirectPlay message ID header on the message (indicating who sent the message), it cannot filter out messages based on the message ID.

When DPSESSION_NOMESSAGEID is used, the idFrom parameter has no meaning and the idTo parameter is used simply to direct the message to the correct target computer. If the target computer has more than one player on it, it cannot be determined whose receive queue the message will appear in. When the message is received, it will appear to have come from player DPID_UNKNOWN.

There is no limit to the size of messages that can be transmitted using the Send method. DirectPlay will automatically break up large messages into packets (packetize) and reassemble them on the receiving end. Beware of sending large messages nonguaranteed — if even one of the packets fails to reach the receiver, the entire message is ignored. The application can determine the maximum size of a message before it starts packetizing by calling GetCaps and examining the dwMaxBufferSize member of the DPCAPS structure.

When you send an encryted or signed message, it is not delivered as an application message, but as a system message, DPMSG_SECUREMESSAGE.

See Also

IDirectPlay4::Receive, IDirectPlay4::SendEx, IDirectPlay4::SendChatMessage, DPMSG_SECUREMESSAGE


IDirectPlay4::SendChatMessage

IDirectPlay4 Interface

Sends a text message to another player, a group of players, or all players. This method supports both Unicode (the IDirectPlay4 interface) and ANSI strings (the IDirectPlay4A interface). The player receiving the chat message is informed through a DPMSG_CHAT system message in the player's receive queue. This method must be used in a lobby session.

Syntax

HRESULT SendChatMessage(
  DPID idFrom,
  DPID idTo,
  DWORD dwFlags,
  LPDPCHAT lpChatMessage
  );

Parameters

idFrom
ID of the sending player. The player ID must correspond to one of the local players on this computer.
idTo
ID of the player to send the message to, the group ID of the group of players to send the message to, or DPID_ALLPLAYERS to send the message to all players in the session.
dwFlags
Indicates how the message should be sent. If this parameter is set to 0, the message is sent nonguaranteed.
DPSEND_GUARANTEED
Sends the message by using a guaranteed method of delivery if it is available.
lpChatMessage
Pointer to a DPCHAT structure containing the message to be sent.

Return Value

Returns DP_OK if successful or one of the following error values:
DPERR_ACCESSDENIED
DPERR_CONNECTIONLOST
DPERR_INVALIDFLAGS
DPERR_INVALIDPARAMS
DPERR_INVALIDPLAYER

This method returns DPERR_INVALIDPARAMS if the idTo ID is not a valid player or group. It returns DPERR_INVALIDPLAYER if the idFrom ID is not a valid player. It returns DPERR_ACCESSDENIED if the idFrom ID is not a local player.

Remarks

This method facilitates player to player chatting within a lobby session where it is possible for different client applications to be connected. You must use this method in a lobby session. Use is optional in an application seession.

The receiving player will receive a system message (idFrom = DPID_SYSTEM). The DPCHAT structure will specify which player the chat message came from.

See Also

DPCHAT, DPMSG_CHAT, IDirectPlay4::Send


IDirectPlay4::SendEx

IDirectPlay4 Interface

Sends a message to another player, to a group of players, or to all players in the session. SendEx is an enhanced version of the Send method and has more options available. SendEx supports both guaranteed and nonguaranteed messages. It also enables you to send asynchronous messages and to set the priority and timeout of a message.

Syntax

HRESULT SendEx(
  DPID idFrom,
  DPID idTo,
  DWORD dwFlags,
  LPVOID lpData,
  DWORD dwDataSize,
  DWORD dwPriority,
  DWORD dwTimeout,
  LPVOID lpContext,
  LPDWORD lpdwMsgID
  );

Parameters

idFrom
ID of the sending player. The player ID must correspond to one of the local players on the computer from which the message is sent.
idTo
The destination ID of the message. To send a message to another player, specify the ID of the player. To send a message to all the players in a group, specify the ID of the group. To send a message to all the players in the session, use the constant symbol DPID_ALLPLAYERS. To send a message to the server player, specify the constant symbol DPID_SERVERPLAYER. A player cannot send a message to himself or herself.
dwFlags
Indicates how the message should be sent. By default (dwFlags = 0), the message is sent nonguaranteed.
DPSEND_ASYNC
Sends the message asynchronously. The function returns immediately and fills in the lpdwMsgID parameter. If this flag is not specified, the function does not return until the message has been sent (and acknowledged, if sent guaranteed). A DPMSG_SENDCOMPLETE system message is posted when the send has completed.

When this flag is used, the return value will be DPERR_PENDING if the message is put in the send queue. This is not a fatal error, but just a return value that lets you know the message did not get sent immediately.

DPSEND_ENCRYPTED
Sends the messages encrypted. This can only be done in a secure session. This flag can only be used if the DPSEND_GUARANTEED flag is also set. The message will be sent as a DPMSG_SECUREMESSAGE system message.
DPSEND_GUARANTEED
Sends the message by using a guaranteed method of delivery if it is available.
DPSEND_NOSENDCOMPLETEMSG
If this flag is set, no completion message is posted. This flag can only be used if the DPSEND_ASYNC flag is also set.
DPSEND_SIGNED
Sends the message with a digital signature. This can only be done in a secure session. This flag can only be used if the DPSEND_GUARANTEED flag is also set. The message will be sent as a DPMSG_SECUREMESSAGE system message.
lpData
Pointer to the data being sent.
dwDataSize
Length of the data being sent.
dwPriority
Priority of the message in the range from zero to 65535. Zero is the lowest priority message. A larger number indicates a message with a higher priority. A message with a given priority will only be sent when there are no messages in the queue with a higher priority.

Note: Not all service providers support this option. If it is not supported, specifying a non-zero priority will return a DPERR_UNSUPPORTED error. Call GetCaps to determine is this option is supported or not.

dwTimeout
Optional application-supplied timeout, in milliseconds, that specifies a time limit for delivering the message. If the message cannot be delivered within this time, it is automatically canceled and a DPMSG_SENDCOMPLETE message is posted. Zero indicates that no timeout should be used.

Note: Not all service providers support this option. If it is not supported, specifying a non-zero timeout will return a DPERR_UNSUPPORTED error. Call GetCaps to determine is this option is supported or not.

lpContext
An application-defined context that is returned to the application as part of the completion message when the send has been completed. Can be NULL.
lpdwMsgID
Pointer to a DWORD that will be filled in with a DirectPlay-generated ID for the message. Use this ID to check the status of the message or to cancel it. Pass NULL if no message ID is needed. This parameter is only returned for asynchronous messages.

Return Value

For synchronous messages, returns DP_OK if successful. For asynchronous messages, returns DPERR_PENDING if the send reaches the point where it is successfully queued. You will then get the completion status from the DPMSG_SENDCOMPLETE message. Otherwise, returns one of the following error values:
DPERR_BUSY
DPERR_CONNECTIONLOST
DPERR_INVALIDFLAGS
DPERR_INVALIDPARAMS
DPERR_INVALIDPLAYER
DPERR_INVALIDPRIORITY
DPERR_NOTLOGGEDIN
DPERR_SENDTOOBIG
DPERR_UNSUPPORTED

This method returns DPERR_INVALIDPARAMS if the encrypted or signed flag is specified for a message that is not also specified as guaranteed, or if the DPSEND_NOCOMPLETEMSG flag is specified for a message that is not asynchronous. It returns DPERR_INVALIDPRIORITY if the priority value is not between 0 and 65535. It returns DPERR_NOTSUPPORTED if you specify a non-zero priority and the service provider does not support priorities, or if you specify a non-zero timeout and the service provider does not support this option.

Remarks

If the DirectPlay Protocol was specified in the session description (by setting the DPSESSION_DIRECTPLAYPROTOCOL flag in the DPSESSIONDESC2 structure), then all the options on SendEx are available. Otherwise, an application should call GetCaps to determine what options the service provider has implemented. SendEx supports guaranteed and nonguaranteed messages. Messages sent guaranteed will not be blocked if there are pending messages waiting to be acknowledged by the receiver.

If a message is sent asynchronously (by setting the DPSEND_ASYNC flag), the message will be put into a send queue and the SendEx function will return immediately. A system message (DPMSG_SENDCOMPLETE) will be posted to the receive queue of the sending player indicating the result of the send.

You can give messages priorities. A message is sent when there are no higher priority messages waiting to be sent and when there is available bandwidth.

You can give a message a timeout. If DirectPlay cannot deliver the message in the time specified, it will be canceled.

The DPSEND_SIGNED and DPSEND_ENCRYPTED flags cannot be used if the order of delivery of guaranteed messages is not preserved because the DPSESSION_NOPRESERVEORDER flag is set in the session description (DPSESSIONDESC2).

If messages are sent using different priorities, signing and encryption may not work. It is best for the application to decide on one priority level for secure messages and only use the security flag on that priority level. This is because validation of secure messages depends on the order in which they are received and prioritization may change this order.

If the DirectPlay Protocol is active, it will attempt to throttle outbound network traffic. That is, it will not always send packets as fast as possible. It will send packets as fast as it can without overwhelming the inbound bandwidth of the receiving computer.

System messages are always sent guaranteed, whether or not the service provider natively supports guaranteed messages, and whether or not you set the DirectPlay protocol flag. The DirectPlay protocol will be used automatically to send system messages guaranteed.

For non-system messages, if an application sets the DirectPlay protocol flag and sends a message guaranteed (by setting the DPSEND_GUARANTEED flag), the message will be sent guaranteed whether the service provider supports guaranteed messages or not.

For non-system messages, if an application does not set the DirectPlay protocol flag and sends a message guaranteed, the message will be sent guaranteed only if the service provider supports it. If the service provider does not support guaranteed messages, the message will not be sent guaranteed, regardless of the DPSEND_GUARANTEED flag.

See Also

IDirectPlay4::Send, IDirectPlay4::CancelMessage, IDirectPlay4::CancelPriority, IDirectPlay4::GetMessageQueue,DPMSG_SENDCOMPLETE


IDirectPlay4::SetGroupConnectionSettings

IDirectPlay4 Interface

Sets the connection settings for a session that will be launched from this group. This method can only be used in a lobby session.

Syntax

HRESULT SetGroupConnectionSettings(
  DWORD dwFlags,
  DPID idGroup,
  LPDPLCONNECTION lpConnection
  );

Parameters

dwFlags
Not used. Must be zero.
idGroup
The DPID of the group to set the connection settings on.
lpConnection
Pointer to a DPLCONNECTION structure describing the application to be launched, the service provider to use, and the session description of the session to be created.

Return Value

Returns DP_OK if successful, or one of the following error values otherwise:
DPERR_ACCESSDENIED
DPERR_CONNECTIONLOST
DPERR_INVALIDGROUP
DPERR_INVALIDPARAMS
DPERR_UNSUPPORTED

Remarks

Call IDirectPlay4::GetGroupConnectionSettings before calling SetGroupConnectionSettings to see if any of the DPLCONNECTION structure members already have default values (non-NULL or non-zero). If so, you may get an error if you try to change these default values.

You do not have to set the lpAddress and dwAddressSize data members of the DPLCONNECTION structure with SetGroupConnectionSettings. In the DPSESSIONDESC2 structure within the DPLCONNECTION structure, you do not have to fill in the guidInstance member.

See Also

DPLCONNECTION, IDirectPlayLobby3::RunApplication, IDirectPlay4::GetGroupConnectionSettings


IDirectPlay4::SetGroupData

IDirectPlay4 Interface

Associates an application-specific data block with a group ID. Only the computer that created the group can change the remote data associated with it.

Syntax

HRESULT SetGroupData(
  DPID idGroup,
  LPVOID lpData,
  DWORD dwDataSize,
  DWORD dwFlags
  );

Parameters

idGroup
Group ID for which data is being set.
lpData
Pointer to the data to be set. Set to NULL to clear any existing group data.
dwDataSize
Size of the data buffer. If lpData is NULL and this parameter does not equal zero, the method returns DPERR_INVALIDPARAMS.
dwFlags
Flag indicating how the group data is propagated. If this parameter is set to zero, the remote group data will be set and propagated using nonguaranteed messaging.
DPSET_GUARANTEED
Propagates the data by using guaranteed messaging (if available). This flag can only be used with DPSET_REMOTE.
DPSET_LOCAL
This data is for local use only and will not be propagated.
DPSET_REMOTE
This data is for use by all the applications and will be propagated to all the other applications in the session. This flag can only be used on groups owned by the local session.

Return Value

Returns DP_OK if successful, or one of the following error values otherwise:
DPERR_ACCESSDENIED
DPERR_CONNECTIONLOST
DPERR_INVALIDGROUP
DPERR_INVALIDOBJECT
DPERR_INVALIDPARAMS

Remarks

DirectPlay can maintain two types of group data: local and remote. Local data is available only to the application on the local computer. Remote data is propagated to all the other applications in the session. A DPSYS_SETPLAYERORGROUPDATA system message will be sent to all players (including the sender) notifying them of the change unless DPSESSION_NODATAMESSAGES is set in the session description. You can safely store pointers to resources in the local data; the local data block is available (in the DPMSG_DESTROYPLAYERORGROUP system message) when the group is being destroyed, so that the application can free those resources. For a list of system messages, see Using System Messages.

This method should not be used for updating real-time information (such as position updates) because of the overhead introduced. IDirectPlay4::Send is much more efficient for updating real-time information. IDirectPlay4::SetGroupData is more appropriate for shared-state information that does not change often and is not time-critical (such as a team color).

See Also

DPMSG_SETPLAYERORGROUPDATA, IDirectPlay4::GetGroupData, IDirectPlay4::Send


IDirectPlay4::SetGroupName

IDirectPlay4 Interface

Sets the name of a group after it has been created. Only the computer that created the group can set the name of the group. A DPMSG_SETPLAYERORGROUPNAME system message will be sent to all the other players notifying them of the change unless DPSESSION_NODATAMESSAGES is set in the session description.

Syntax

HRESULT SetGroupName(
  DPID idGroup,
  LPDPNAME lpGroupName,
  DWORD dwFlags
  );

Parameters

idGroup
ID of the group for which the name is being set.
lpGroupName
Pointer to a DPNAME structure containing the name information for the group. Set this parameter to NULL if the group has no name information.
dwFlags
If this parameter is set to 0, the name will be propagated to all the remote systems by using nonguaranteed message passing. This value can only be used on groups owned by the local session.
DPSET_GUARANTEED
Propagates the data using guaranteed messaging (if available).
DPSET_LOCAL
This data is for local use only and will not be propagated.
DPSET_REMOTE
This data is for use by all the applications, and will be propagated to all the other applications in the session. This flag can only be used on groups owned by the local session.

Return Value

Returns DP_OK if successful, or one of the following error values otherwise:
DPERR_CONNECTIONLOST
DPERR_INVALIDGROUP
DPERR_INVALIDOBJECT
DPERR_INVALIDPARAMS
DPERR_INVALIDPLAYER

See Also

DPNAME, DPMSG_SETPLAYERORGROUPNAME, IDirectPlay4::GetGroupName, IDirectPlay4::Send


IDirectPlay4::SetGroupOwner

IDirectPlay4 Interface

Changes the owner of a group. This method is only available in a lobby session. It generates a DPMSG_SETGROUPOWNER system message.

Syntax

HRESULT SetGroupOwner(
  DPID idGroup,
  DPID idOwner
  );

Parameters

idGroup
ID of the group whose owner is being changed.
idOwner
DPID of the player to be set as the owner of the group.

Return Value

Returns DP_OK if successful, or one of the following error values otherwise:
DPERR_CONNECTIONLOST
DPERR_GENERIC
DPERR_INVALIDGROUP
DPERR_INVALIDPLAYER
DPERR_UNAVAILABLE

This method returns DPERR_UNAVAILABLE if the session is not a lobby session.

See Also

IDirectPlay4::GetGroupOwner, DPMSG_SETGROUPOWNER


IDirectPlay4::SetPlayerData

IDirectPlay4 Interface

Associates an application-specific data block with a player ID.

Syntax

HRESULT SetPlayerData(
  DPID idPlayer,
  LPVOID lpData,
  DWORD dwDataSize,
  DWORD dwFlags
  );

Parameters

idPlayer
ID of the player for which data is being set.
lpData
Pointer to the data to be set. Set this parameter to NULL and dwDataSize to zero to clear out any existing player data.
dwDataSize
Size of the data buffer. If lpData is NULL and this parameter does not equal zero, the method returns DPERR_INVALIDPARAMS.
dwFlags
If this parameter is set to 0, the remote player data will be set and propagated by using nonguaranteed messaging.
DPSET_GUARANTEED
Propagates the data by using guaranteed messaging (if available). This flag can only be used with DPSET_REMOTE.
DPSET_LOCAL
This data is for local use only and will not be propagated.
DPSET_REMOTE
This data is for use by all the applications, and will be propagated to all the other applications in the session.

Return Value

Returns DP_OK if successful, or one of the following error values otherwise:
DPERR_ACCESSDENIED
DPERR_CONNECTIONLOST
DPERR_INVALIDFLAGS
DPERR_INVALIDOBJECT
DPERR_INVALIDPARAMS
DPERR_INVALIDPLAYER

Remarks

SetPlayerData should not be used for updating real-time information (such as position updates) due to the overhead introduced. It is much more efficient to use Send for this. SetPlayerData is more appropriate for shared state information that doesn't change very often and is not time critical (such as a player's name).

DirectPlay can maintain two types of player data: local and remote. Local data is available only to the application on the local computer. Remote data is propagated to all the other applications in the session. This method returns DPERR_ACCESSDENIED if you try to set player data for a remote player. A DPMSG_SETPLAYERORGROUPDATA system message will be sent to all players (including the sender) notifying them of the change unless DPSESSION_NODATAMESSAGES is set in the session description. It is safe to store pointers to resources in the local data; the local data block is available (in the DPMSG_DESTROYPLAYERORGROUP system message) when the player is being destroyed, so the application can free those resources. For a list of system messages, see Using System Messages.

See Also

DPMSG_SETPLAYERORGROUPDATA, IDirectPlay4::GetPlayerData, IDirectPlay4::Send


IDirectPlay4::SetPlayerName

IDirectPlay4 Interface

Sets the name of a local player after it has been changed. Only the computer that created the player can change the name. A DPMSG_SETPLAYERORGROUPNAME system message will be sent to all the other players notifying them of the change unless DPSESSION_NODATAMESSAGES is set in the session description.

Syntax

HRESULT SetPlayerName(
  DPID idPlayer,
  LPDPNAME lpPlayerName,
  DWORD dwFlags
  );

Parameters

idPlayer
ID of the local player for which data is being sent.
lpPlayerName
Pointer to a DPNAME structure containing the name information for the player. Set this parameter to NULL if the player has no name information.
dwFlags
Flags indicating how the name will be propagated. It can be one of the following values:
DPSET_GUARANTEED
Propagates the data by using guaranteed messaging (if available).
DPSET_LOCAL
Data is not propagated to other players.
DPSET_REMOTE
Propagates the data to all players in the session using nonguaranteed message passing. This is the default value.

Return Value

Returns DP_OK if successful, or one of the following error values otherwise:
DPERR_CONNECTIONLOST
DPERR_INVALIDOBJECT
DPERR_INVALIDPLAYER

See Also

DPNAME, DPMSG_SETPLAYERORGROUPNAME, IDirectPlay4::GetPlayerName, IDirectPlay4::Send


IDirectPlay4::SetSessionDesc

IDirectPlay4 Interface

Changes the properties of the current session. Only the host of the session can change the session properties. If a nonhost attempts to call it, the method returns DPERR_ACCESSDENIED.

The updated session description will be propagated to all the other computers in the session. Each player will receive a DPMSG_SETSESSIONDESC system message .

You can't use SetSessionDesc in a lobby session.

Syntax

HRESULT SetSessionDesc(
  LPDPSESSIONDESC2 lpSessDesc,
  DWORD dwFlags
  );

Parameters

lpSessDesc
Pointer to the DPSESSIONDESC2 structure containing the new settings.
dwFlags
No flags are currently used by this method.

Return Value

Returns DP_OK if successful, or one of the following error values otherwise:
DPERR_ACCESSDENIED
DPERR_CONNECTIONLOST
DPERR_INVALIDPARAMS
DPERR_NOSESSIONS

This method returns DPERR_ACCESSDENIED if this computer does not have permission to change the session. Only the host can change the session properties. It returns DPERR_INVALIDPARAMS if the application attempts to change a property in the session description that cannot be changed or tries to give a property an invalid value.

Remarks

Changing the session description will cause a DPSYS_SETSESSIONDESC system message to be generated on all the other computers in the session.

The following members and flags of the DPSESSIONDESC2 structure can be changed using IDirectPlay4::SetSessionDesc:

dwFlags
DPSESSION_JOINDISABLED
DPSESSION_NEWPLAYERSDISABLED
DPSESSION_NODATAMESSAGES
DPSESSION_PRIVATE
dwMaxPlayers
If you set the maximum players to a value less than the current number of players, the method returns DPERR_INVALIDPARAMS.
lpszSessionName / lpszSessionNameA
lpszPassword / lpszPasswordA
dwUser1
dwUser2
dwUser3
dwUser4

If the following members and flags of the DPSESSIONDESC2 structure are changed, an error will occur (for example, if the DPSESSION_KEEPALIVE flag is currently set and you try to set this bit, you will not get an error, but if you try to clear this bit, you will get an error and IDirectPlay4::SetSessionDesc will fail):

dwSize
dwFlags
DPSESSION_NOMESSAGEID
DPSESSION_KEEPALIVE

The following members of the DPSESSIONDESC2 structure are ignored (that is, it does not matter what you pass in these members; DirectPlay will always use the values passed when IDirectPlay4::Open was called):

guidInstance
guidApplication
dwCurrentPlayers
dwReserved1
dwReserved2

See Also

DPSESSIONDESC2, IDirectPlay4::GetSessionDesc


IDirectPlay4::StartSession

IDirectPlay4 Interface

Use this method to initiate the launch of a DirectPlay session. Call SetGroupConnectionSettings first to specify what application to launch, which service provider to use, and what session description to use.

When StartSession is called, each player in the group receives a DPMSG_STARTSESSION instructing the player to launch the session.

Syntax

HRESULT StartSession(
  DWORD dwFlags,
  DPID idGroup
  );

Parameters

dwFlags
Not used. Must be zero.
idGroup
The DPID of the group to send start session commands to. The group must be a staging area.

Return Value

Returns DP_OK if successful or one of the following error values:
DPERR_ACCESSDENIED
DPERR_CONNECTIONLOST
DPERR_INVALIDFLAGS
DPERR_INVALIDGROUP
DPERR_INVALIDPARAMS

This method returns DPERR_INVALIDGROUP if the given group ID is not a valid staging area.

Remarks

A player joining a staging area group for which the session has already started can call this method to join the session. The player will receive a DPMSG_STARTSESSION message instructing it how to join the session.

You can determine if a session is already in progress by calling IDirectPlay4::GetGroupConnectionSettings and examining the guidInstance parameter it returns through a pointer in the DPLCONNECTION structure to the DPSESSIONDESC2 structure. If guidInstance is GUID_NULL, no session is in progress. If it is any other value, a session is already in progress.

See Also

DPMSG_STARTSESSION


IDirectPlayLobby3 Interface

Applications use the methods of the IDirectPlayLobby3 interface to manage applications and their associated data. This section is a reference to the methods of this interface. For a conceptual overview, see IDirectPlayLobby3 Interface.
Address management | CreateAddress
CreateCompoundAddress
EnumAddress
EnumAddressTypes
Application management | Connect
ConnectEx
EnumLocalApplications
RegisterApplication
RunApplication
UnregisterApplication
WaitForConnectionSettings
Data management | GetConnectionSettings
ReceiveLobbyMessage
SendLobbyMessage
SetConnectionSettings
SetLobbyMessageEvent


IDirectPlayLobby3::Connect

IDirectPlayLobby3 Interface

Connects an application to the session specified by the DPLCONNECTION structure currently stored with the DirectPlayLobby object.

Note This method will return an IDirectPlay2 or IDirectPlay2A interface. If this is not the desired DirectPlay COM interface, the application must obtain the correct interface (for example, IDirectPlay4 or IDirectPlay4A) by using QueryInterface and release this interface. A newer method, IDirectPlayLobby3::ConnectEx, allows the application to specify which DirectPlay COM interface to return.

By default, Connect returns after a connection is made or when the connection has timed-out. If you use the DPCONNECT_RETURNSTATUS flag, Connect returns immediately with a DPERR_CONNECTING error code indicating the connection is in progress. The application must continue calling this method periodically until DP_OK or a failure code is returned. The application can cancel the connection by releasing the IDirectPlayLobby3 interface.

Syntax

HRESULT Connect(
  DWORD dwFlags,
  LPDIRECTPLAY2 *lplpDP,
  IUnknown FAR *pUnk
  );

Parameters

dwFlags
Flags indicating how the connection is to be done. By default (dwFlags = 0), the method returns once a connection has been established or the operation has timed out.
DPCONNECT_RETURNSTATUS
Returns immediately with the status of the connection. The application must continue calling Connect until a success or error code is returned.
lplpDP
Pointer to a pointer to be initialized with a valid interface — either IDirectPlay2 (if called on IDirectPlayLobby3) or IDirectPlay2A (if called on IDirectPlayLobby3A). Note that if some other interface is desired, the application should use QueryInterface to obtain a pointer to the new interface and to release this one. Alternatively, the ConnectEx method can be used.
pUnk
Pointer to the containing IUnknown interface. This parameter is provided for future compatibility with COM aggregation features. Presently, however, IDirectPlayLobby3::Connect returns an error if this parameter is anything but NULL.

Return Value

Returns DP_OK if successful, or one of the following error values otherwise:
CLASS_E_NOAGGREGATION
DPERR_CONNECTING
DPERR_INVALIDFLAGS
DPERR_INVALIDINTERFACE
DPERR_INVALIDOBJECT
DPERR_INVALIDPARAMS
DPERR_NOTLOBBIED
DPERR_OUTOFMEMORY

The method returns DPERR_CONNECTING while the connection operation is in progress. Call the methods again to get an updated status.

Remarks

There is an upper limit of one minute on connection timeout.

After this method is successfully completed, the application can skip the process of calling IDirectPlay4::InitializeConnection, IDirectPlay4::EnumSessions, and IDirectPlay4::Open. The application should not ask the user a name but instead create a player using the player name information in the DPLCONNECTION structure.

Before calling this method, the application can examine the connection settings that will be used to start the application by using the IDirectPlayLobby3::GetConnectionSettings method. The application then can modify these settings and set them by using the IDirectPlayLobby3::SetConnectionSettings method. The application should pay particular attention to the DPSESSIONDESC2 structure to ensure that the proper session properties are set, especially dwFlags, dwMaxPlayers, and the dwUser members.

See Also

IDirectPlayLobby3::ConnectEx


IDirectPlayLobby3::ConnectEx

IDirectPlayLobby3 Interface

Connects an application to the session specified by the DPLCONNECTION structure currently stored with the DirectPlayLobby object.

This method is an extended version of the Connect method. This version allows the application to specify which version of the Microsoft® DirectPlay® COM interface to return.

By default, ConnectEx returns after a connection is made or the connection has timed out. If you use the DPCONNECT_RETURNSTATUS flag, ConnectEx returns immediately with a DPERR_CONNECTING error code indicating the connection is in progress. The application must continue calling this method periodically until DP_OK or a failure code is returned. The application can cancel the connection by releasing the IDirectPlayLobby3 interface.

Syntax

HRESULT ConnectEx(
  DWORD dwFlags,
  REFIID riid,
  LPVOID *lplpDP,
  IUnknown FAR *pUnk
  );

Parameters

dwFlags
Flags indicating how the connection is to be done. By default (dwFlags = 0), the method returns after a connection has been established or the operation has timed out.
DPCONNECT_RETURNSTATUS
Returns immediately with the status of the connection. The application must continue calling ConnectEx until a success or error code is returned.
riid
The IID of the specific DirectPlay COM interface to be returned; for example, IID_IDirectPlay4A.
lplpDP
Pointer to a pointer to be initialized with the DirectPlay interface as specified by the riid parameter.
pUnk
Pointer to the containing IUnknown interface. This parameter is provided for future compatibility with COM aggregation features. Presently, however, IDirectPlayLobby3::ConnectEx returns an error if this parameter is anything but NULL.

Return Value

Returns DP_OK if successful, or one of the following error values otherwise:
DPERR_CONNECTING
DPERR_INVALIDFLAGS
DPERR_INVALIDPARAMS

The method returns DPERR_CONNECTING while the connection operation is in progress. Call the methods again to get an updated status.

Remarks

There is an upper limit of one minute on connection timeout.

After this method is successfully completed, the application can skip the process of calling IDirectPlay4::InitializeConnection, IDirectPlay4::EnumSessions, and IDirectPlay4::Open. The application should not ask the user a name but instead create a player using the player name information in the DPLCONNECTION structure.

Before calling this method, the application can examine the connection settings that will be used to start the application by using the IDirectPlayLobby3::GetConnectionSettings method. The application then can modify these settings and set them by using the IDirectPlayLobby3::SetConnectionSettings method. The application should pay particular attention to the DPSESSIONDESC2 structure to ensure that the proper session properties are set, especially dwFlags, dwMaxPlayers, and the dwUser members.

See Also

IDirectPlayLobby3::ConnectEx


IDirectPlayLobby3::CreateAddress

IDirectPlayLobby3 Interface

Creates a DirectPlay Address, given a service provider-specific network address. The resulting address contains the globally unique identifier (GUID) of the service provider and data that the service provider can interpret as a network address.

Note that with IDirectPlayLobby3::CreateCompoundAddress you can create addresses with more than one data chunk. Therefore, you should use IDirectPlayLobby3::CreateCompoundAddress.

For more information about the DirectPlay Address, see DirectPlay Address. For a list of predefined Microsoft data types, see DirectPlay Address Data Types.

Syntax

HRESULT CreateAddress(
  REFGUID guidSP,
  REFGUID guidDataType,
  LPCVOID lpData,
  DWORD dwDataSize,
  LPVOID lpAddress,
  LPDWORD lpdwAddressSize
  );

Parameters

guidSP
Pointer to the GUID of the service provider. (In C++, it is a reference to the GUID.)
guidDataType
Pointer to the GUID identifying the specific network address type being used. (In C++, it is a reference to the GUID.) For information about predefined network address types, see DirectPlay Address.
lpData
Pointer to a buffer containing the specific network address.
dwDataSize
Size, in bytes, of the network address in lpData.
lpAddress
Pointer to a buffer in which the constructed DirectPlay Address is to be written.
lpdwAddressSize
Pointer to a variable containing the size of the DirectPlay Address buffer. Before calling this method, the service provider must initialize lpdwAddressSize to the size of the buffer. After the method has returned, this parameter will contain the number of bytes written to lpAddress. If the buffer was too small (DPERR_BUFFERTOOSMALL), this parameter will be set to the size required to store the DirectPlay Address.

Return Value

Returns DP_OK if successful, or one of the following error values otherwise:
DPERR_BUFFERTOOSMALL
DPERR_INVALIDPARAMS

Remarks

The IDirectPlayLobby3::CreateCompoundAddress method can be used to create longer DirectPlay Addresses than CreateAddress allows.

See Also

IDirectPlayLobby3::EnumAddress, IDirectPlayLobby3::CreateCompoundAddress


IDirectPlayLobby3::CreateCompoundAddress

IDirectPlayLobby3 Interface

Creates a DirectPlay Address from a list of individual data chunks. This method can be used to create longer DirectPlay Addresses than IDirectPlayLobby3::CreateAddress allows. For a list of predefined Microsoft data types, see DirectPlay Address Data Types.

Syntax

HRESULT CreateCompoundAddress(
  LPDPCOMPOUNDADDRESSELEMENT lpElements,
  DWORD dwElementCount,
  LPVOID lpAddress,
  LPDWORD lpdwAddressSize
  );

Parameters

lpElements
Pointer to the first element in an array of DPCOMPOUNDADDRESSELEMENT structures that will be used to generate the DirectPlay Address.
dwElementCount
The number of address elements in the array pointed to by the lpElements parameter.
lpData
Pointer to a buffer that the complete DirectPlay Address is to be written to. Pass NULL if only the required size of the buffer is desired.
lpdwDataSize
Pointer to a DWORD with the size of the lpData buffer. The DWORD will be modified to reflect the actual number of bytes copied into the buffer. If the buffer was too small, it will contain the number of bytes required.

Return Value

Returns DP_OK if successful, or one of the following error values otherwise:
DPERR_BUFFERTOOSMALL
DPERR_INVALIDFLAGS
DPERR_INVALIDPARAMS

See Also

IDirectPlayLobby3::CreateAddress, IDirectPlayLobby3::EnumAddress, DPCOMPOUNDADDRESSELEMENT


IDirectPlayLobby3::EnumAddress

IDirectPlayLobby3 Interface

Parses out chunks from the DirectPlay Address buffer.

Syntax

HRESULT EnumAddress(
  LPDPENUMADDRESSCALLBACK lpEnumAddressCallback,
  LPCVOID lpAddress,
  DWORD dwAddressSize,
  LPVOID lpContext
  );

Parameters

lpEnumAddressCallback
Pointer to a EnumAddressCallback function that will be called for each information chunk in the DirectPlay Address.
lpAddress
Pointer to the start of the DirectPlay Address buffer.
dwAddressSize
Size of the DirectPlay Address.
lpContext
Context that will be passed to the callback function.

Return Value

Returns DP_OK if successful, or one of the following error values otherwise:
DPERR_EXCEPTION
DPERR_INVALIDOBJECT
DPERR_INVALIDPARAMS

Remarks

For more information about the DirectPlay Address, see DirectPlay Address.

See Also

IDirectPlayLobby3::CreateAddress


IDirectPlayLobby3::EnumAddressTypes

IDirectPlayLobby3 Interface

Enumerates all the address types that a given service provider needs to build the DirectPlay Address. The application or lobby can use this information to obtain the correct information from the user and create a DirectPlay Address.

Syntax

HRESULT EnumAddressTypes(
  LPDPLENUMADDRESSTYPESCALLBACK lpEnumAddressTypeCallback,
  REFGUID guidSP,
  LPVOID lpContext,
  DWORD dwFlags
  );

Parameters

lpEnumAddressTypeCallback
Pointer to the EnumAddressTypeCallback function that will be called for each address type for a service provider. If the service provider takes no address type, the callback will not be called.
guidSP
Pointer to the GUID of the service provider whose address types are to be enumerated. (In C++, it is a reference to the GUID.)
lpContext
Context that will be passed to the callback function.
dwFlags
Reserved; must be zero.

Return Value

Returns DP_OK if successful, or one of the following error values otherwise:
DPERR_EXCEPTION
DPERR_INVALIDOBJECT
DPERR_INVALIDPARAMS

Remarks

For more information about the DirectPlay Address, see DirectPlay Address. You can use EnumAddressTypes to determine if a service provider displays dialog boxes prompting the user for information; for example, a dialog box that asks for an IP address. If the service provider takes no address types, then it needs no information and will not display the dialog boxes.

An application can call IDirectPlay4::GetPlayerAddress to obtain a list of valid choices for an address type. This is only available for the modem-to-modem service providers. DirectPlay Address data types that are null-terminated Unicode strings end in W (for example, DPAID_INetW), while DirectPlay Address data types that are null-terminated ANSI strings do not (for example, DPAID_INet). For a list of predefined Microsoft data types, see DirectPlay Address Data Types.

See Also

DirectPlay Address, IDirectPlayLobby3::CreateAddress


IDirectPlayLobby3::EnumLocalApplications

IDirectPlayLobby3 Interface

Enumerates what applications are registered with DirectPlay.

Calling this method on the IDirectPlayLobby3A (ANSI) interface returns a suitably localized, single-byte character string. No multi-byte characters are used so there are no problems displaying the strings using fonts that do not support multi-byte characters. Calling this method on the IDirectPlayLobby3 (Unicode) interface returns a localized, wide character description. Lobbies that are specifically localized should call this method on the Unicode interface.

Syntax

HRESULT EnumLocalApplications(
  LPDPENUMLOCALAPPLICATIONSCALLBACK lpEnumLocalAppCallback,
  LPVOID lpContext,
  DWORD dwFlags
  );

Parameters

lpEnumLocalAppCallback
Pointer to the EnumLocalApplicationsCallback function that will be called for each enumerated application.
lpContext
Context passed to the callback function.
dwFlags
Reserved; must be zero.

Return Value

Returns DP_OK if successful, or one of the following error values otherwise:
DPERR_GENERIC
DPERR_INVALIDINTERFACE
DPERR_INVALIDOBJECT
DPERR_INVALIDPARAMS
DPERR_OUTOFMEMORY

See Also

DPLAPPINFO


IDirectPlayLobby3::GetConnectionSettings

IDirectPlayLobby3 Interface

Retrieves the DPLCONNECTION structure that contains all the information needed to start and connect an application. The data returned is the same data that was passed to the IDirectPlayLobby3::RunApplication method by the lobby client, or set by calling the IDirectPlayLobby3::SetConnectionSettings method.

Syntax

HRESULT GetConnectionSettings(
  DWORD dwAppID,
  LPVOID lpData,
  LPDWORD lpdwDataSize
  );

Parameters

dwAppID
Identifies which application's connection settings to retrieve when called from a lobby client (that communicates with several applications). When called from an application (that only communicates with one lobby client), this parameter must be zero. This ID number is obtained from IDirectPlayLobby3::RunApplication.
lpData
Pointer to a buffer in which the connection settings are to be written. Set this parameter to NULL to request only the size of data. The lpdwDataSize parameter will be set to the minimum size required to hold the data.
lpdwDataSize
Pointer to a variable that is initialized to the size of the buffer before calling this method. After the method returns, this parameter will be set to the size, in bytes, of the data. If the buffer was too small (DPERR_BUFFERTOOSMALL), then this parameter will be set to the minimum buffer size required.

Return Value

Returns DP_OK if successful, or one of the following error values otherwise:
DPERR_BUFFERTOOSMALL
DPERR_GENERIC
DPERR_INVALIDINTERFACE
DPERR_INVALIDOBJECT
DPERR_INVALIDPARAMS
DPERR_NOTLOBBIED
DPERR_OUTOFMEMORY

Remarks

The lpData member should be cast to the DPLCONNECTION structure when the function returns to read the data from it.

See Also

DPLCONNECTION, IDirectPlayLobby3::RunApplication, IDirectPlayLobby3::SetConnectionSettings, IDirectPlayLobby3::WaitForConnectionSettings


IDirectPlayLobby3::ReceiveLobbyMessage

IDirectPlayLobby3 Interface

Retrieves the message sent between a lobby client application and a DirectPlay application. Messages are queued, so there is no danger of losing data if it is not read in time.

Syntax

HRESULT ReceiveLobbyMessage(
  DWORD dwFlags,
  DWORD dwAppID,
  LPDWORD lpdwMessageFlags,
  LPVOID lpData,
  LPDWORD lpdwDataSize
  );

Parameters

dwFlags
Reserved; must be zero.
dwAppID
Identifies which application's message to retrieve when called from a lobby client (that communicates with several applications). When called from an application (that communicates only with one lobby client), this parameter must be set to zero. This ID number is obtained by using the IDirectPlayLobby3::RunApplication method.
lpdwMessageFlags
Flags indicating what type of message is being returned. The default (lpdwMessageFlags = 0) indicates that the message is custom-defined by the sender. Processing of this type of message is optional. The receiver must interpret this message based on the identity of the sending application. A lobby can identify the sending application based on the GUID of the application that was launched. An application will need to identify the lobby by sending the lobby a standard message requesting an identifying GUID.
DPLMSG_STANDARD
Indicates that this is a DirectPlay-defined message. Processing of this type of message is optional.
DPLMSG_SYSTEM
Indicates that this is a DirectPlay generated system message used to inform the lobby of changes in the status of the application it launched.
lpData
Pointer to a buffer in which the message is to be written. Set this parameter to NULL to request only the size of message. The lpdwDataSize parameter will be set to the minimum size required to hold the message.
lpdwDataSize
Pointer to a variable that is initialized to the size of the buffer before calling this method. After the method returns, this parameter will be set to the size, in bytes, of the message. If the buffer was too small (DPERR_BUFFERTOOSMALL), then this parameter will be set to the minimum buffer size required.

Return Value

Returns DP_OK if successful, or one of the following error values otherwise:
DPERR_APPNOTSTARTED
DPERR_BUFFERTOOSMALL
DPERR_GENERIC
DPERR_INVALIDINTERFACE
DPERR_INVALIDOBJECT
DPERR_INVALIDPARAMS
DPERR_NOMESSAGES
DPERR_OUTOFMEMORY

See Also

IDirectPlayLobby3::RunApplication, IDirectPlayLobby3::SendLobbyMessage


IDirectPlayLobby3::RegisterApplication

IDirectPlayLobby3 Interface

Registers a lobby-aware application with DirectPlay. An application must be registered so that a DirectPlay lobby can launch it.

The application only needs to be registered once. The application must also be unregistered (see IDirectPlayLobby3::UnregisterApplication) when it is uninstalled.

Syntax

HRESULT RegisterApplication(
  DWORD dwFlags,
  LPDPAPPLICATIONDESC lpAppDesc
  );

Parameters

dwFlags
Reserved; must be zero.
lpAppDesc
Pointer to a DPAPPLICATIONDESC structure that has been filled in with all the registration values for the application.

Return Value

Returns DP_OK if successful, or one of the following error values otherwise:
DPERR_INVALIDFLAGS
DPERR_INVALIDPARAMS

See Also

DPAPPLICATIONDESC, IDirectPlayLobby3::UnregisterApplication


IDirectPlayLobby3::RunApplication

IDirectPlayLobby3 Interface

Starts an application and passes to it all the information necessary to connect it to a session. This method is used by a lobby client.

Syntax

HRESULT RunApplication(
  DWORD dwFlags,
  LPDWORD lpdwAppID,
  LPDPLCONNECTION lpConn,
  HANDLE hReceiveEvent
  );

Parameters

dwFlags
Reserved; must be zero.
lpdwAppId
Pointer to a variable that will be filled with an ID identifying the application that was started. The lobby client must save this application ID for use on with any calls to the IDirectPlayLobby3::SendLobbyMessage and IDirectPlayLobby3::ReceiveLobbyMessage methods.
lpConn
Pointer to a DPLCONNECTION structure that contains all the information necessary to specify which application to start and how to get it connected to a session instance without displaying any user dialog boxes.
hReceiveEvent
Specifies a synchronization event that will be set when a lobby message is received. This event can be changed later by using the IDirectPlayLobby3::SetLobbyMessageEvent method.

Return Value

Returns DP_OK if successful, or one of the following error values otherwise:
DPERR_CANTCREATEPROCESS
DPERR_GENERIC
DPERR_INVALIDINTERFACE
DPERR_INVALIDOBJECT
DPERR_INVALIDPARAMS
DPERR_OUTOFMEMORY
DPERR_UNKNOWNAPPLICATION

Remarks

This method will return after the application process has been created. The lobby client will receive a system message indicating the status of the application. If the lobby client is starting an application that will be hosting a session, it should wait until it receives a DPLSYS_DPLAYCONNECTSUCCEEDED system message before starting the other applications that will be joining the session. If the application was unable to create or join a session, a DPLSYS_DPLAYCONNECTFAILED message will be generated. The lobby client will also receive a DPLSYS_CONNECTIONSETTINGSREAD system message when the application has read the connection settings and a DPLSYS_APPTERMINATED system message when the application terminates.

It is important that the lobby client not release its IDirectPlayLobby3 interface before it receives a DPLSYS_CONNECTIONSETTINGSREAD system message. The lobby client can either check IDirectPlayLobby3::ReceiveLobbyMessage in a loop until it is received, or supply a synchronization event.

See Also

IDirectPlayLobby3::ReceiveLobbyMessage, IDirectPlayLobby3::GetConnectionSettings, IDirectPlayLobby3::SetLobbyMessageEvent


IDirectPlayLobby3::SendLobbyMessage

IDirectPlayLobby3 Interface

Sends a message between the application and the lobby client.

Syntax

HRESULT SendLobbyMessage(
  DWORD dwFlags,
  DWORD dwAppID,
  LPVOID lpData,
  DWORD dwDataSize
  );

Parameters

dwFlags
Flags indicating the type of message being sent. The default (dwFlags = 0) is a custom message defined by the application sending it. Other possible values are:
DPLMSG_STANDARD - this is a standard message defined by DirectPlay.
dwAppID
Identifies which application to send a message to when called from a lobby client (that communicates with several applications). When called from an application (that communicates with only one lobby client), this parameter must be zero. This ID is obtained by using the IDirectPlayLobby3::RunApplication method.
lpData
Pointer to the buffer containing the message to send.
dwDataSize
Size, in bytes, of the buffer.

Return Value

Returns DP_OK if successful, or one of the following error values otherwise:
DPERR_APPNOTSTARTED
DPERR_BUFFERTOOLARGE
DPERR_GENERIC
DPERR_INVALIDINTERFACE
DPERR_INVALIDOBJECT
DPERR_INVALIDPARAMS
DPERR_OUTOFMEMORY
DPERR_TIMEOUT

See Also

IDirectPlayLobby3::RunApplication, IDirectPlayLobby3::ReceiveLobbyMessage, DPLMSG_SETPROPERTY, DPLMSG_SETPROPERTYRESPONSE, DPLMSG_GETPROPERTY, DPLMSG_GETPROPERTYRESPONSE,


IDirectPlayLobby3::SetConnectionSettings

IDirectPlayLobby3 Interface

Modifies the DPLCONNECTION structure, which contains all the information needed to start and connect an application.

Syntax

HRESULT SetConnectionSettings(
  DWORD dwFlags,
  DWORD dwAppID,
  LPDPLCONNECTION lpConn
  );

Parameters

dwFlags
Reserved; must be zero.
dwAppID
When called from a lobby client (that communicates with several applications), this parameter identifies which application's connection settings to retrieve. When called from an application (that communicates with only one lobby client), this parameter must be zero. This ID is obtained by using the IDirectPlayLobby3::RunApplication method.
lpConn
Pointer to a DPLCONNECTION structure that contains all the information necessary to specify which application to start and how to get it connected to a session instance without displaying any user dialog boxes.

Return Value

Returns DP_OK if successful, or one of the following error values otherwise:
DPERR_GENERIC
DPERR_INVALIDINTERFACE
DPERR_INVALIDOBJECT
DPERR_INVALIDPARAMS
DPERR_OUTOFMEMORY

See Also

IDirectPlayLobby3::GetConnectionSettings


IDirectPlayLobby3::SetLobbyMessageEvent

IDirectPlayLobby3 Interface

Registers an event that will be set when a lobby message is received. The application must call this method if it needs to synchronize with messages. The lobby client can call this method to change the events specified in the call to the IDirectPlayLobby3::RunApplication method.

Syntax

HRESULT SetLobbyMessageEvent(
  DWORD dwFlags,
  DWORD dwAppID,
  HANDLE hReceiveEvent
  );

Parameters

dwFlags
Reserved; must be zero.
dwAppID
Identifies which application the event is associated with when called from a lobby client (that communicates with several applications). When called from an application (that communicates with only one lobby client), this parameter must be zero. This ID number is obtained from IDirectPlayLobby3::RunApplication.
hReceiveEvent
Event handle to be set when a message is received.

Return Value

Returns DP_OK if successful, or one of the following error values otherwise:
DPERR_GENERIC
DPERR_INVALIDINTERFACE
DPERR_INVALIDOBJECT
DPERR_INVALIDPARAMS
DPERR_OUTOFMEMORY

See Also

IDirectPlayLobby3::ReceiveLobbyMessage, IDirectPlayLobby3::SendLobbyMessage


IDirectPlayLobby3::UnregisterApplication

IDirectPlayLobby3 Interface

Deletes the registration entries for a DirectPlay application. The entries must be removed when the application is uninstalled.

Syntax

HRESULT UnregisterApplication(
  DWORD dwFlags,
  REFGUID guidApplication
  );

Parameters

dwFlags
Reserved; must be zero.
guidApplication
The globally unique identifier (GUID) of the application to remove from the registry. In C, this parameter is a pointer to a GUID. In C++, it is a reference to a GUID.

Return Value

Returns DP_OK if successful, or one of the following error values otherwise:
DPERR_INVALIDFLAGS
DPERR_INVALIDPARAMS
DPERR_UNKNOWNAPPLICATION

The method returns DPERR_UNKNOWNAPPLICATION if the GUID of the application could not be found in the registry.

See Also

IDirectPlayLobby3::RegisterApplication


IDirectPlayLobby3::WaitForConnectionSettings

IDirectPlayLobby3 Interface

Puts the application into wait mode, where the application waits for the connection settings. When the application is in wait mode, a lobby client that uses RunApplication will not launch a new instance of the application, but will send the connection settings directly to the application already running in wait mode.

When in wait mode, the application should poll for DPLSYS_NEWCONNECTIONSETTINGS system message. After that message is received, the application is automatically taken out of wait mode. The application can use ConnectEx to connect to a session.

Syntax

HRESULT WaitForConnectionSettings(
  DWORD dwFlags);

Parameters

dwFlags
Flag that puts the application into wait mode or takes it out of wait mode. By default (dwFlags = 0), the method puts the application into wait mode. Setting dwFlags to DPLWAIT_CANCEL takes the application out of wait mode. As soon as the connection settings are sent by the lobby client, the application will automatically be taken out of wait mode.

Return Value

Returns DP_OK if successful, or one of the following error values otherwise:
DPERR_INVALIDFLAGS
DPERR_UNAVAILABLE

The method returns DPERR_UNAVAILABLE if you set the flag to cancel wait mode and the application is not in wait mode.

Remarks

When the lobby client uses RunApplication, DirectPlay will look for any instances of the application that are waiting for connection settings. If none are found, then a new instance of the application is launched. If a waiting application is found, DirectPlay will send a DPLSYS_NEWCONNECTIONSETTINGS system message. The application can then read the connection settings with GetConnectionSettings and join a session using ConnectEx.


Structures

A new structure, DPAPPLICATIONDESC, has been added in Microsoft® DirectPlay® 6.0, and new flags have been added to the existing DPSESSIONDESC2 structure.

Several new data members were added to structures for DirectPlay 5.0, and these are supported in DirectPlay 6.0. Applications that need to be backward-compatible with DirectPlay 3.0 run times should either:

  • use the structures that existed in the DirectX 3.0 header files.
  • check the dwSize member in each structure before attempting to access to members of the structure.

The DirectPlay structures are:

  • DPACCOUNTDESC
  • DPAPPLICATIONDESC
  • DPCAPS
  • DPCHAT
  • DPCOMPORTADDRESS
  • DPCOMPOUNDADDRESSELEMENT
  • DPCREDENTIALS
  • DPLAPPINFO
  • DPLCONNECTION
  • DPNAME
  • DPSECURITYDESC
  • DPSESSIONDESC2


DPACCOUNTDESC

Describes the account information for a specific player.

Syntax

typedef struct {
  DWORD  dwSize;
  DWORD  dwFlags;
  union {
    LPWSTR  lpszAccountID;
    LPSTR   lpszAccountIDA;
  };
} DPACCOUNTDESC, FAR *LPDPACCOUNTDESC;

Members

dwSize
The size of the DPACCOUNTDESC structure, dwsize = sizeof(DPACCOUNTDESC).
dwFlags
Not used. Must be zero.
lpszAccountID
Pointer to a Unicode string containing the account identifier. This is a unique identifier that describes a player who is securely logged in. The format of the identifier depends on the Security Support Provider Interface (SSPI) package being used.
lpszAccountIDA
Pointer to an ANSI string containing the account identifier. This is a unique identifier that describes a player who is securely logged in. The format of the identifier depends on the SSPI package being used.

See Also

IDirectPlay4::GetPlayerAccount


DPAPPLICATIONDESC

Describes all the information necessary to register a lobby-aware application using IDirectPlayLobby3::RegisterApplication.

Syntax

typedef struct {
    DWORD   dwSize;
    DWORD   dwFlags;
    union {
      LPSTR    lpszApplicationNameA;
      LPWSTR   lpszApplicationName;
    }
    GUID    guidApplication;
    union {
      LPSTR     lpszFilenameA;
      LPWSTR    lpszFilename;
    }
    union {
      LPSTR   lpszCommandLineA;
      LPWSTR  lpszCommandLine;
    }
    union {
      LPSTR   lpszPathA;
      LPWSTR  lpszPath;
    }
    union {
      LPSTR    lpszCurrentDirectoryA;
      LPWSTR   lpszCurrentDirectory;
    }
    LPSTR   lpszDescriptionA;
    LPWSTR  lpszDescriptionW;
} DPAPPLICATIONDESC, FAR *LPDPAPPLICATIONDESC;

Members

dwSize
Size of the DPAPPLICATIONDESC structure, dwsize = sizeof(DPAPPLICATIONDESC).
dwFlags
Not used. Must be zero.
lpszApplicationNameA, lpszApplicationName
Pointer to a string containing the name of the application. Note: This title should not be localized. Use the lpszDescriptionA and lpszDescriptionW members to localize the application name.
guidApplication
Globally unique identifier (GUID) of the application. This should be the same as the value used in the guidApplication member of the DPSESSIONDESC2 structure when hosting a game session.
lpszFilenameA, lpszFilename
Pointer to a string containing the name of the executable to be launched. Note: The use of a stub executable should be avoided when launching from a lobby. In a lobby launch scenario, the stub should be bypassed and the main executable should be launched.
lpszCommandLineA, lpszCommandLine
Pointer to a string containing command line arguments to be passed to the executable when launched by a lobby.
lpszPathA, lpszPath
Pointer to a string containing the path where the executable is located.
lpszCurrentDirectoryA, lpszCurrentDirectory
Pointer to a string containing the path that the current directory should be set to. Typically, this is the same as lpszPath or lpszPathA.
lpszDescriptionA
Pointer to an ANSI single-byte character string containing a localized description of the application. When EnumLocalApplications is called on an ANSI interface (such as IDirectPlayLobby3A), this string will be returned if it is present. Otherwise, the lpszApplicationName data member will be returned. Note: This string should not contain any multi-byte characters. Set to NULL if no localized ANSI description is needed.
lpszDescriptionW
Pointer to a Unicode sting containing a localized description of the application. When EnumLocalApplications is called on a Unicode interface (such as IDirectPlayLobby3), this string will be returned if it is present. If it is not present, the lpszDescriptionA data member will be converted to Unicode and returned. If neither lpszDescriptionA nor lpszDescriptionW is present, the lpszApplicationName data member will be returned. Note: This string must consist solely of Unicode characters. Set to NULL if no localized Unicode description is needed.

See Also

RegisterApplication


DPCAPS

Contains the capabilities of a DirectPlay object after a call to the IDirectPlay4::GetCaps or IDirectPlay4::GetPlayerCaps method. Any of these capabilities can differ, depending on whether guaranteed or nonguaranteed capabilities are requested. This structure is read-only. Note that capabilities indicating which aspects of the SendEx method are supported, such as the DPCAPS_SENDPRIORITYSUPPORTED and DPCAPS_SENDTIMEOUTSUPPORTED flags in dwFlags, are not available until after the session has been opened. If the application hosting the session has specified the DPSESSION_DIRECTPLAYPROTOCOL flag in the DPSESSIONDESC2 structure, all the SendEx options are supported.

Syntax

typedef struct {
    DWORD dwSize;
    DWORD dwFlags;
    DWORD dwMaxBufferSize;
    DWORD dwMaxQueueSize;
    DWORD dwMaxPlayers;
    DWORD dwHundredBaud;
    DWORD dwLatency;
    DWORD dwMaxLocalPlayers;
    DWORD dwHeaderLength;
    DWORD dwTimeout;
} DPCAPS, FAR *LPDPCAPS;

Members

dwSize
Size of the DPCAPS structure, dwsize = sizeof(DPCAPS). Your application must set this member before it uses this structure; otherwise, an error will result.
dwFlags
Flags that indicate the properties of the DirectPlay object.
DPCAPS_ASYNCCANCELALLSUPPORTED
Indicates that canceling all pending asynchronous messages is supported. This flag indicates that the only form of cancellation supported is the ability to cancel all unsent messages. Any attempt to cancel messages by specifying a priority range or a message ID will return DPERR_UNSUPPORTED. By contrast, the DPCAPS_ASYNCCANCELSUPPORTED flag indicates that all types of cancellation are supported. Note that capabilities indicating which aspects of SendEx are supported are not available until after the session has been opened.
DPCAPS_ASYNCCANCELSUPPORTED
Indicates that canceling asynchronous messages is supported. All types of cancellation are supported: canceling by message ID, canceling by priority range, and canceling all unsent messages. Note that capabilities indicating which aspects of SendEx are supported are not available until after the session has been opened.
DPCAPS_ASYNCSUPPORTED
Indicates that asynchronous messaging is supported. Thus, an application can use the DPSEND_ASYNC flag on SendEx. See Remarks for more information. Note that capabilities indicating which aspects of SendEx are supported are not available until after the session has been opened.
DPCAPS_ENCRYPTIONSUPPORTED
Indicates that message encryption is supported by this DirectPlay object, either because the session is a secure session, or because the service provider can encrypt messages.
DPCAPS_GROUPOPTIMIZED
Indicates that the service provider bound to this DirectPlay object can optimize group (multicast) messaging.
DPCAPS_GUARANTEEDOPTIMIZED
Indicates that the service provider bound to this DirectPlay object supports guaranteed message delivery.
DPCAPS_GUARANTEEDSUPPORTED
Indicates that the DirectPlay object supports guaranteed message delivery, either because the service provider supports it, or because DirectPlay implements it on a nonguaranteed service provider.
DPCAPS_ISHOST
Indicates that the DirectPlay object created by the calling application is the session host.
DPCAPS_KEEPALIVEOPTIMIZED
Indicates that the service provider can detect when the connection to the session has been lost.
DPCAPS_SENDPRIORITYSUPPORTED
Indicates that the message priority set in SendEx is supported. Note that capabilities indicating which aspects of SendEx are supported are not available until after the session has been opened.
DPCAPS_SENDTIMEOUTSUPPORTED
Indicates that the timeout for messages specified in SendEx is supported. This flag can be set by the service provider or by DirectPlay. Note that capabilities indicating which aspects of SendEx are supported are not available until after the session has been opened.
DPCAPS_SIGNINGSUPPORTED
Indicates that message authentication is supported by this DirectPlay object, either because it is a secure session, or because the service provider can sign messages.
dwMaxBufferSize
Maximum number of bytes that can be sent in a single packet by this service provider. Larger messages will be sent by using more than one packet.
dwMaxQueueSize
This member is no longer used.
dwMaxPlayers
Maximum number of local and remote players supported in a session by this DirectPlay object.
dwHundredBaud
Bandwidth specified in multiples of 100 bits per second. For example, a value of 24 specifies 2400 bits per second.
dwLatency
Estimate of latency by the service provider, in milliseconds. If this value is 0, DirectPlay cannot provide an estimate. Accuracy for some service providers rests on application-to-application testing, taking into consideration the average message size. Latency can differ, depending on whether the application uses guaranteed or nonguaranteed message delivery.
dwMaxLocalPlayers
Maximum number of local players supported in a session.
dwHeaderLength
Size, in bytes, of the header that will be added to player messages by this DirectPlay object. Note that the header size depends on which service provider is in use.
dwTimeout
Service provider's suggested time-out value. By default, DirectPlay will use this time-out value when waiting for replies to messages.

Remarks

The DPCAPS_ASYNCSUPPORTED, DPCAPS_SENDTIMEOUTSUPPORTED, DPCAPS_SENDPRIORITYSUPPORTED, DPCAPS_ASYNCCANCELSUPPORTED, and DPCAPS_ASYNCCANCELALLSUPPORTED flags indicate the communications capabilities of the current session.

In order for an application to be able to use DPSEND_ASYNC on SendEx one (or both) of the following conditions must be true.

  • You specified the DPSESSION_DIRECTPLAYPROTOCOL flag when the session was created.
  • The service provider supports asynchronous messaging.

This means that modem, serial, and Internetwork Packet Exchange (IPX) service providers have guaranteed messaging available to them, but they do not have asynchronous messaging, unless you explicitly set the DPSESSION_DIRECTPLAYPROTOCOL flag. The TCP/IP service provider implements asynchronous messaging when the computer has Winsock 2.0 present.

See Also

IDirectPlay4::Send, IDirectPlay4::SendEx, IDirectPlay4::GetCaps, IDirectPlay4::GetPlayerCaps,


DPCHAT

Contains a DirectPlay chat message. Chat messages are sent with the IDirectPlay4::SendChatMessage method.

Syntax

typedef struct {
    DWORD	dwSize;
    DWORD	dwFlags;
    union{
      LPWSTR lpszMessage;
      LPSTR  lpszMessageA;
    };
} DPCHAT, FAR *LPDPCHAT;

Members

dwSize
The size of the DPCHAT structure, dwsize = sizeof(DPCHAT).
dwFlags
Not used. Must be 0.
lpszMessage
Pointer to a Unicode string containing the message to be sent. Can only be used with a Unicode interface (IDirectPlay4).
lpszMessageA
Pointer to an ANSI string containing the message to be sent. Can only be used with an ANSI interface (IDirectPlay4A).

See Also

IDirectPlay4::SendChatMessage

© 1998 Microsoft Corporation. All rights reserved. Terms of Use.


DPCOMPORTADDRESS

Contains information about the configuration of the COM port.

Syntax

typedef struct DPCOMPORTADDRESS{
    DWORD dwComPort;
    DWORD dwBaudRate;
    DWORD dwStopBits;
    DWORD dwParity;
    DWORD dwFlowControl;
} DPCOMPORTADDRESS;

typedef DPCOMPORTADDRESS FAR* LPDPCOMPORTADDRESS;

Members

dwComPort
Indicates the number of the COM port to use. The value for this member can be 1, 2, 3, or 4.
dwBaudRate
Indicates the baud of the COM port. The value for this member can be one of the following:
CBR_110 | CBR_300 | CBR_600
CBR_1200 | CBR_2400 | CBR_4800
CBR_9600 | CBR_14400 | CBR_19200
CBR_38400 | CBR_56000 | CBR_57600
CBR_115200 | CBR_128000 | CBR_256000
dwStopBits
Indicates the number of stop bits. The value for this member can be ONESTOPBIT, ONE5STOPBITS, or TWOSTOPBITS.
dwParity
Indicates the parity used on the COM port. The value for this member can be NOPARITY, ODDPARITY, EVENPARITY, or MARKPARITY.
dwFlowControl
Indicates the method of flow control used on the COM port. The following values can be used for this member:
DPCPA_DTRFLOW | Indicates hardware flow control with DTR.
DPCPA_NOFLOW | Indicates no flow control.
DPCPA_RTSDTRFLOW | Indicates hardware flow control with RTS and DTR.
DPCPA_RTSFLOW | Indicates hardware flow control with RTS.
DPCPA_XONXOFFFLOW | Indicates software flow control (xon/xoff).

Remarks

The constants that define baud, stop bits, and parity are defined in Winbase.h.


DPCOMPOUNDADDRESSELEMENT

Describes a DirectPlay Address data chunk. See DirectPlay Address Data Types for a list of predefined Microsoft data types.

Syntax

typedef struct {
    GUID    guidDataType;
    DWORD   dwDataSize;
    LPVOID  lpData;
} DPCOMPOUNDADDRESSELEMENT, FAR *LPDPCOMPOUNDADDRESSELEMENT;

Members

guidDataType
GUID identifying the type of data contained in this structure.
dwDataSize
Size of the data in bytes.
lpData
Pointer to a buffer containing the data.

See Also

IDirectPlayLobby3::CreateCompoundAddress


DPCREDENTIALS

Holds the user name, password, and domain to connect to a secure server.

Syntax

typedef struct {
    DWORD  dwSize;
    DWORD  dwFlags;
    union {
           LPWSTR lpszUsername;
           LPSTR  lpszUsernameA;
          };
    union {
           LPWSTR lpszPassword;
           LPSTR  lpszPasswordA;
          };
    union {
           LPWSTR lpszDomain;
           LPSTR  lpszDomainA;
          };

} DPCREDENTIALS, FAR *LPDPCREDENTIALS;

Members

dwSize
The size of the DPCREDENTIALS structure, dwsize = sizeof(DPCREDENTIALS).
dwFlags
Not used. Must be zero.
lpszUsername, lpszPassword, lpszDomain
Pointers to Unicode strings containing the user name, password, and domain name. Can only be used with a Unicode interface.
lpszUsernameA, lpszPasswordA, lpszDomainA
Pointers to ANSI strings containing the user name, password, and domain name. Can only be used with an ANSI interface.

See Also

IDirectPlay4::SecureOpen


DPLAPPINFO

Contains information about the application from the registry and is passed to the IDirectPlayLobby3::EnumLocalApplications callback function.

Syntax

typedef struct {
    DWORD  dwSize;
    GUID   guidApplication;
    union {
           LPSTR  lpszAppNameA;
           LPWSTR lpszAppName;
          };
} DPLAPPINFO, FAR *LPDPLAPPINFO;

Members

dwSize
The size of the DPLAPPINFO structure, dwsize = sizeof(DPLAPPINFO). Your application must set this member before it uses this structure; otherwise, an error will result.
guidApplication
Globally unique identifier (GUID) of the application.
lpszAppNameA, lpszAppName
Name of the application in ANSI or Unicode, depending on what interface is in use.


DPLCONNECTION

Contains the information needed to connect an application to a session.

Syntax

typedef struct {
    DWORD            dwSize;
    DWORD            dwFlags;
    LPDPSESSIONDESC2 lpSessionDesc;
    LPDPNAME         lpPlayerName;
    GUID             guidSP;
    LPVOID           lpAddress;
    DWORD            dwAddressSize;
} DPLCONNECTION, FAR *LPDPLCONNECTION;

Members

dwSize
The size of the DPLCONNECTION structure, dwsize = sizeof(DPLCONNECTION). Your application must set this member before it uses this structure; otherwise, an error will result. Examine this member to determine if the fields added in DirectPlay version 5 are available.
dwFlags
Indicates how to open a session.
DPLCONNECTION_CREATESESSION
Create a new session as described in the session description.
DPLCONNECTION_JOINSESSION
Join the existing session as described in the session description.
lpSessionDesc
Pointer to a DPSESSIONDESC2 structure describing the session to be created or the session to join.
lpPlayerName
Pointer to a DPNAME structure holding the name the player should be created with. This will be the name of the person registered in the lobby. The application can ignore this name.
guidSP
Globally unique identifier (GUID) of the service provider to use to connect to the session.
lpAddress
Pointer to a DirectPlay Address that contains the information that the service provider needs to connect to a session. For more information about the DirectPlay Address, see DirectPlay Address. For a list of Microsoft predefined address data types, see DirectPlay Address Data Types.
dwAddressSize
Size, in bytes, of the address data.

See Also

IDirectPlayLobby3::RunApplication, IDirectPlayLobby3::GetConnectionSettings, IDirectPlayLobby3::SetConnectionSettings


DPNAME

Contains name information for a DirectPlay entity, such as a player or group.

Syntax

typedef struct {
    DWORD dwSize;
    DWORD dwFlags;
    union {
        LPWSTR lpszShortName;
        LPSTR  lpszShortNameA;
    };
    union {
        LPWSTR lpszLongName;
        LPSTR  lpszLongNameA;
    };
} DPNAME, FAR *LPDPNAME;

Members

dwSize
The size of the DPNAME structure, dwsize = sizeof(DPNAME). Your application must set this member before it uses this structure; otherwise, an error will result.
dwFlags
Structure-specific flags. Currently set to zero.
lpszShortName and lpszLongName
Pointers to Unicode strings containing the short (friendly) and long (formal) names of a player or group. Use these members only if the IDirectPlay4 Interface interface is in use.
lpszShortNameA and lpszLongNameA
Pointers to ANSI strings containing the short (friendly) and long (formal) names of a player or group. Use these members only if the IDirectPlay4A interface is in use.

See Also

IDirectPlay4::CreateGroup, IDirectPlay4::CreatePlayer, IDirectPlay4::GetGroupName, IDirectPlay4::GetPlayerName, IDirectPlay4::SetGroupName, IDirectPlay4::SetPlayerName


DPSECURITYDESC

Describes the security properties of a DirectPlay session instance.

Syntax

typedef struct {
    DWORD  dwSize;
    DWORD  dwFlags;
    union {
           LPWSTR  lpszSSPIProvider;
           LPSTR   lpszSSPIProviderA;
    };
    union {
           LPWSTR lpszCAPIProvider;
           LPSTR  lpszCAPIProviderA;
    };
    DWORD  dwCAPIProviderType;
    DWORD  dwEncryptionAlgorithm;
} DPSECURITYDESC, FAR *LPDPSECURITYDESC;

Members

dwSize
The size of the DPSECURITYDESC structure, dwsize = sizeof(DPSECURITYDESC).
dwFlags
Not used. Must be zero.
lpszSSPIProvider, lpszSSPIProviderA
Pointer to a Unicode or ANSI string describing the Security Support Provider Interface (SSPI) package to use for authenticated logins. Pass NULL to use the default, the NTLM (NT LAN Manager) security provider.
lpszCAPIProvider, lpszCAPIProviderA
Pointer to a Unicode or ANSI string describing the CryptoAPI package to use for cryptography services. Pass NULL to use the default, the Microsoft RSA Base Cryptographic Provider v. 1.0.
dwCAPIProviderType
CryptoAPI service provider type. Pass zero to use the default type, PROV_RSA_FULL.
dwEncryptionAlgorithm
Encryption algorithm to use. DirectPlay only supports stream ciphers. Pass zero to use the default, the CALG_RC4 stream cipher.

Remarks

For more information about the CryptoAPI, see the CrpytoAPI and Cryptography topics at http://www.microsoft.com. The Microsoft RSA Base Cryptographic Provider is supplied by Microsoft and is included with the Windows 95 and Windows NT operating systems.

DirectPlay does not support block encryption.

See Also

IDirectPlay4::SecureOpen


DPSESSIONDESC2

Contains a description of an IDirectPlay4 Interface session's capabilities. (The DPSESSIONDESC structure is no longer used in the IDirectPlay4 interface.)

Note some of the session description flags are read-only and cannot be changed, and the rest can only be changed by the host. See the description of the dwFlags parameter for list.

Syntax

typedef struct {
    DWORD dwSize;
    DWORD dwFlags;
    GUID  guidInstance;
    GUID  guidApplication;
    DWORD dwMaxPlayers;
    DWORD dwCurrentPlayers;
    union  {
        LPWSTR lpszSessionName;
        LPSTR  lpszSessionNameA;
    };
    union  {
        LPWSTR lpszPassword;
        LPSTR  lpszPasswordA;
    };
    DWORD dwReserved1;
    DWORD dwReserved2;
    DWORD dwUser1;
    DWORD dwUser2;
    DWORD dwUser3;
    DWORD dwUser4;
} DPSESSIONDESC2, FAR *LPDPSESSIONDESC2;

Members

dwSize
Size of the DPSESSIONDESC2 structure, dwsize = sizeof(DPSESSIONDESC2). Your application must set this member before it uses this structure; otherwise, an error will result.
dwFlags
Combination of the following flags. The following flags cannot be changed once the session has started: DPSESSION_CLIENTSERVER, DPSESSION_DIRECTPLAYPROTOCOL, DPSESSION_KEEPALIVE, DPSESSION_MIGRATEHOST, DPSESSION_MULTICASTSERVER, DPSESSION_NOMESSAGEID, DPSESSION_OPTIMIZELATENCY, and DPSESSION_SECURESERVER. The other flags, DPSESSION_JOINDISABLED, DPSESSION_NEWPLAYERSDISABLED, DPSESSION_NODATAMESSAGES, DPSESSION_NOPRESERVEORDER, DPSESSION_PASSWORDREQUIRED, and DPSESSION_PRIVATE, can be changed after a session has started by using IDirectPlay4::SetSessionDesc, but only by the host.
DPSESSION_CLIENTSERVER
Specifies that this is a client/server session that is being hosted by an application-server process. This flag must be specified at the time the session is created. Any clients that join this session will only be able to enumerate the server player and any local players. The host of the session will see all the players. If this flag is not set, the session is a peer-to-peer session. If this flag is set, the host can only create a server player. This flag cannot be used with DPSESSION_MIGRATEHOST.
DPSESSION_DIRECTPLAYPROTOCOL
Specifies that this session should use the DirectPlay guaranteed protocol instead of the one implemented by the service provider. Use this flag if message throttling is desired (and you want the performance gains it provides).
DPSESSION_JOINDISABLED
Specifies that no new applications can join this session. Any call to the IDirectPlay4::Open method with the DPOPEN_JOIN flag and the globally unique identifier (GUID) of this session instance will cause an error. If this flag is not specified, new remote applications can join the session until the session player limit is reached.
DPSESSION_KEEPALIVE
Specifies that this session will automatically detect when remote players drop out of the game abnormally. Those players will be deleted from the session. If a temporary network outage caused the loss of the players, they will be informed when they return that they were dropped from the session through the DPMSG_SESSIONLOST system message. This flag must be specified at the time the session is created. If this flag is not specified, DirectPlay will not automatically keep the session alive if players are abnormally terminated.
DPSESSION_MIGRATEHOST
Specifies that if the current host exits, another computer in the session will become the host. The players on the new host computer will receive a DPMSG_HOST system message. This flag must be specified at the time the session is created. If this flag is not specified, the host will not migrate, new computers cannot join the session, and new players cannot be created if the current host leaves. Note that the DPSESSION_MIGRATEHOST flag cannot be used with the DPSESSION_CLIENTSERVER, DPSESSION_MULTICASTSERVER, or DPSESSION_SECURESERVER flags.
DPSESSION_MULTICASTSERVER
Specifies that in a peer-to-peer session, broadcast and group messages are routed through the host that acts like a multicast server. This flag must be specified at the time the session is created. The flag is only useful if the host has a high bandwidth connection to the network. If this flag is not specified, broadcast and group messages are sent directly between peers. This flag cannot be used with DPSESSION_MIGRATEHOST.
DPSESSION_NEWPLAYERSDISABLED
Specifies that new players cannot be created in the session. Any call to the IDirectPlay4::CreatePlayer method by an application in the session will result in an error. Also, new applications cannot join the session. If this flag is not specified, players can be created until the session player limit is reached.
DPSESSION_NODATAMESSAGES
Specifies that the session does not send system messages when remote player data, group data, or session data is changed with the IDirectPlay4::SetPlayerData, IDirectPlay4::SetGroupData, IDirectPlay4::SetPlayerName, IDirectPlay4::SetGroupName, or IDirectPlay4::SetSessionDesc method. If this flag is not specified, messages will be generated that indicate that the data changed.

Note that setting this flag also suppresses the DPMSG_SETSESSIONDESC message.

DPSESSION_NOMESSAGEID
Specifies that the session does not attach data to messages that indicate which player the message is from and to whom it is sent. Setting this flag saves message overhead if this information is not relevant. (For more information, see the IDirectPlay4::Receive method.) If this flag is not specified, the message ID will be added. This flag must be specified at the time the session is created.
DPSESSION_NOPRESERVEORDER
Specifies that this session does not preserve the order in which guaranteed messages are received. By default, the receive order of guaranteed messages is preserved. If the order is not needed, this flag can be used to eliminate possible delays in delivery.
DPSESSION_OPTIMIZELATENCY
Asks the service provider to optimize for latency (which turns off nagling in TCP/IP). The default is to optimize for bandwidth.
DPSESSION_PASSWORDREQUIRED
Specifies that this session is password-protected. Any applications wishing to join the session must supply the password in the IDirectPlay4::Open call. This is a read-only flag. It will be set automatically by DirectPlay when the host of the session specifies a non-NULL password.
DPSESSION_PRIVATE
Specifies that this is a private session. It can not respond to enumeration requests unless the request contains a non-NULL, matching password. If this flag is not specified, the session will respond to enumeration requests.
DPSESSION_SECURESERVER
Specifies that this session is being hosted on a secure server that will require authentication credentials before it can be opened. The host must specify this flag when the session is created. It cannot be changed later through IDirectPlay4::SetSessionDesc. This flag cannot be used with the DPSESSION_MIGRATEHOST flag.
guidInstance
GUID of the session instance.
guidApplication
GUID for the application running in the session instance. It uniquely identifies the application so that DirectPlay connects only to other computers running the same application. This member can be set to GUID_NULL to enumerate sessions for any application.
dwMaxPlayers
Maximum number of players allowed in this session. A value of zero means there is no maximum.
dwCurrentPlayers
Number of players currently in the session.
lpszSessionName
Pointer to a Unicode string containing the name of the session. Use only if a Unicode DirectPlay interface (IDirectPlay4 Interface) is being used.
lpszSessionNameA
Pointer to an ANSI string containing the name of the session. Use only if an ANSI DirectPlay interface (IDirectPlay4A) is being used.
lpszPassword
Pointer to a Unicode string containing the password used to join the session for participation. Use only if a Unicode DirectPlay interface (IDirectPlay4 Interface) is being used.
lpszPasswordA
Pointer to an ANSI string containing the password used to join the session for participation. Use only if an ANSI DirectPlay interface (IDirectPlay4A) is being used.
dwReserved1 and dwReserved2
Must be zero.
dwUser1, dwUser2, dwUser3, and dwUser4
Application-specific data for the session.

See Also

IDirectPlay4::EnumSessions, IDirectPlay4::GetSessionDesc, IDirectPlay4::Open, IDirectPlay4::SecureOpen, IDirectPlay4::SetSessionDesc, IDirectPlay4::CreatePlayer, DPPLAYER_SERVERPLAYER


System Messages

Two new system messages, DPMSG_SENDCOMPLETE and DPMSG_SETGROUPOWNER, have been added for Microsoft® DirectPlay® 6.0, and new flags have been added to the existing DPMSG_CREATEPLAYERORGROUP and DPMSG_DESTROYPLAYERORGROUP structures.

The DirectPlay system messages are:

  • DPMSG_ADDGROUPTOGROUP
  • DPMSG_ADDPLAYERTOGROUP
  • DPMSG_CHAT
  • DPMSG_CREATEPLAYERORGROUP
  • DPMSG_DELETEGROUPFROMGROUP
  • DPMSG_DELETEPLAYERFROMGROUP
  • DPMSG_DESTROYPLAYERORGROUP
  • DPMSG_GENERIC
  • DPMSG_HOST
  • DPMSG_SECUREMESSAGE
  • DPMSG_SENDCOMPLETE
  • DPMSG_SESSIONLOST
  • DPMSG_SETGROUPOWNER
  • DPMSG_SETPLAYERORGROUPDATA
  • DPMSG_SETPLAYERORGROUPNAME
  • DPMSG_SETSESSIONDESC
  • DPMSG_STARTSESSION


DPMSG_ADDGROUPTOGROUP

DirectPlay generates this message and sends it to every player when a group is added to a group.

Syntax

typedef struct{
    DWORD    dwType;
    DPID     dpIdParentGroup;
    DPID     dpIdGroup;
} DPMSG_ADDGROUPTOGROUP, FAR *LPDPMSG_ADDGROUPTOGROUP;

Members

dwType
Identifies the message. This member is DPSYS_ADDGROUPTOGROUP.
dpIdParentGroup
ID of the group to which the group was added.
dpIdGroup
ID of the group that was added to the group.

See Also

IDirectPlay4::AddGroupToGroup


DPMSG_ADDPLAYERTOGROUP

Contains information for the DPSYS_ADDPLAYERTOGROUP system message. DirectPlay generates this message and sends it to every player when a player is added to a group.

The application can use IDirectPlay4::GetPlayerCaps, IDirectPlay4::GetPlayerName, and IDirectPlay4::GetPlayerData for information about the player involved int his message, or IDirectPlay4::GetGroupName and IDirectPlay4::GetGroupData to get more information about the group involved in this message.

Syntax

typedef struct{
    DWORD dwType;
    DPID  dpIdGroup;
    DPID  dpIdPlayer;
} DPMSG_ADDPLAYERTOGROUP, FAR *LPDPMSG_ADDPLAYERTOGROUP;

Members

dwType
Identifies the message. This member is DPSYS_ADDPLAYERTOGROUP.
dpIdGroup
ID of the group to which the player was added.
dpIdPlayer
ID of the player that was added to the group.

See Also

IDirectPlay4::AddPlayerToGroup


DPMSG_CHAT

Contains information for the DPSYS_CHAT system message. The system message is generated for a local player receiving a chat message from another player.

Syntax

typedef struct{
    DWORD dwType;
    DWORD dwFlags;
    DPID  idFromPlayer;
    DPID  idToPlayer;
    DPID  idToGroup;
    LPDPCHAT  lpChat;
} DPMSG_CHAT, FAR *LPDPMSG_CHAT;

Members

dwType
Identifies the message. This member has the value DPSYS_CHAT.
dwFlags
Not used.
idFromPlayer
The DPID of the player from whom the message originated. DPID_SERVERPLAYER indicates the message originated from the server.
idToPlayer
The DPID of the player to whom the message was directed. If this DPID is zero, then the message was sent to a group or broadcast to everyone.
idToGroup
The DPID of the group to whom the message was directed. If this DPID is zero and idToPlayer is also zero, then the message was broadcast to everyone.
lpChat
Pointer to a DPCHAT structure containing the content of the chat message received.

Remarks

Use the idFromPlayer value to determine who sent the message. The value of lpidFrom available through Receive will always be zero, so you must retrieve the value of idFromPlayer in the DPMSG_CHAT structure.

See Also

IDirectPlay4::SendChatMessage, DPCHAT, IDirectPlay4::Receive


DPMSG_CREATEPLAYERORGROUP

Contains information for the DPSYS_CREATEPLAYERORGROUP system message. The system sends this message when players and groups are created in a session.

DirectPlay generates this message and sends it to each player when a new player or group is created in a session.

Syntax

typedef struct{
    DWORD  dwType;
    DWORD  dwPlayerType;
    DPID   dpId;
    DWORD  dwCurrentPlayers;
    LPVOID lpData;
    DWORD  dwDataSize;
    DPNAME dpnName;
    DPID   dpIDParent;
    DWORD  dwFlags;
} DPMSG_CREATEPLAYERORGROUP, FAR *LPDPMSG_CREATEPLAYERORGROUP;

Members

dwType
A DWORD that identifies the message. This member must be set to DPSYS_CREATEPLAYERORGROUP.
dwPlayerType
A DWORD that indicates whether the message applies to a player (DPPLAYERTYPE_PLAYER) or a group (DPPLAYERTYPE_GROUP).
dpId
ID of a player or group created.
dwCurrentPlayers
Current number of players in the session before this player was created.
lpData
Pointer to any application-specific, remote data associated with this player or group. If this member is NULL, there is no remote data.
dwDataSize
Size of the data contained in the buffer referenced by lpData.
dpnName
Structure containing the name of the player or group.
dpIDParent
ID of the parent group if this message is caused by a call to IDirectPlay4::CreateGroupInGroup; otherwise, the value is zero.
dwFlags
Player or group flags.
DPGROUP_HIDDEN
Set when a hidden group is created.

Remarks

The DirectPlay 5.0 version of this structure has two members added to the end, dpIdParent and dwFlags.

See Also

IDirectPlay4::CreateGroup, IDirectPlay4::CreatePlayer, IDirectPlay4::CreateGroupInGroup


DPMSG_DELETEGROUPFROMGROUP

DirectPlay generates this message and sends it to every player when a group is removed from a group. Note that this structure is identical to DPMSG_ADDGROUPTOGROUP.

Syntax

typedef struct{
    DWORD    dwType;
    DPID     dpIdParentGroup;
    DPID     dpIdGroup;
} DPMSG_ADDGROUPTOGROUP, FAR *LPDPMSG_ADDGROUPTOGROUP;
typedef DPMSG_ADDGROUPTOGROUP DPMSG_DELETEGROUPFROMGROUP;

Members

dwType
Identifies the message. This member is DPSYS_DELETEGROUPFROMGROUP.
dpIdParentGroup
ID of the group from which the group was removed.
dpIdGroup
ID of the group that was removed from the group.

See Also

IDirectPlay4::DeleteGroupFromGroup


DPMSG_DELETEPLAYERFROMGROUP

Contains information for the DPSYS_DELETEPLAYERFROMGROUP system message. DirectPlay generates this message and sends it to each local player on the computer when a player is deleted from a group.

For a description of the structure members, see the DPMSG_ADDPLAYERTOGROUP structure.

The application can use IDirectPlay4::GetPlayerCaps, IDirectPlay4::GetPlayerName, and IDirectPlay4::GetPlayerData for information about the player involved int his message, or IDirectPlay4::GetGroupName and IDirectPlay4::GetGroupData to get more information about the group involved in this message.

Syntax

typedef struct{
    DWORD dwType;
    DPID  dpIdGroup;
    DPID  dpIdPlayer;
} DPMSG_ADDPLAYERTOGROUP, FAR *LPDPMSG_ADDPLAYERTOGROUP;
typedef DPMSG_ADDPLAYERTOGROUP DPMSG_DELETEPLAYERFROMGROUP;

Members

dwType
Identifies the message. This member is DPSYS_DELETEPLAYERFROMGROUP.
dpIdGroup
ID of the group from which the player was removed.
dpIdPlayer
ID of the player that was removed from the group.

See Also

IDirectPlay4::DeletePlayerFromGroup


DPMSG_DESTROYPLAYERORGROUP

Contains information for the DPSYS_DESTROYPLAYERORGROUP system message. DirectPlay generates this message and sends it to each player when a player or group is destroyed in a session.

Syntax

typedef struct{
    DWORD  dwType;
    DWORD  dwPlayerType;
    DPID   dpId;
    LPVOID lpLocalData;
    DWORD  dwLocalDataSize;
    LPVOID lpRemoteData;
    DWORD  dwRemoteDataSize;
    DPNAME dpnName;
    DPID   dpIdParent;
    DWORD  dwFlags;
} DPMSG_DESTROYPLAYERORGROUP, FAR *LPDPMSG_DESTROYPLAYERORGROUP;

Members

dwType
A DWORD that identifies the message. This member is DPSYS_DESTROYPLAYERORGROUP.
dwPlayerType
A DWORD that identifies whether the message applies to a player (DPPLAYERTYPE_PLAYER) or group (DPPLAYERTYPE_GROUP).
dpId
ID of a player or group that has been destroyed.
lpLocalData
Pointer to the local data associated with this player or group.
dwLocalDataSize
Size, in bytes, of the local data.
lpRemoteData
Pointer to the remote data associated with this player or group.
dwRemoteDataSize
Size, in bytes, of the remote data.
dpnName
Structure containing the name of the player or group.
dpIdParent
ID of the parent group if the group being destroyed is a subgroup of the parent group (the group being destroyed was created by a call to IDirectPlay4::CreateGroupInGroup; otherwise, the value is zero.
dwFlags
Player or group flags. One or more of the following values:
DPGROUP_HIDDEN
Set when a hidden group is destroyed.
DPGROUP_STAGINGAREA
Set when a group that is a staging area is destroyed.
DPPLAYER_SERVERPLAYER
Set when the player being destroyed is a server player for client/server communications.
DPPLAYER_SPECTATOR
Set when the player destroyed is a spectator. A spectator player behaves exactly as a normal player except the player is flagged as a spectator.

Remarks

The DirectPlay 5.0 version of this structure added three members to the end, dpnName, dpIdParent, and dwFlags.

See Also

IDirectPlay4::DestroyGroup, IDirectPlay4::DestroyPlayer


DPMSG_GENERIC

This structure is provided for message processing.

Syntax

typedef struct{
    DWORD dwType;
} DPMSG_GENERIC, FAR *LPDPMSG_GENERIC;

Members

dwType
Identifies the system message type.

Remarks

When a system message is received (that is, the value pointed to by the lpidFrom parameter equals DPID_SYSMSG), first cast the unknown message data to the DPMSG_GENERIC type, and then perform further processing based on the value of dwType. After the message type has been determined, the message can cast to one of the known types of system messages for further processing.


DPMSG_HOST

When the current session host exits the session, this message is sent to all the players on the computer that inherits the host duties.

Syntax

typedef DPMSG_GENERIC    DPMSG_HOST;
typedef DPMSG_HOST  FAR *LPDPMSG_HOST;


DPMSG_SECUREMESSAGE

DirectPlay generates this message when it receives a signed or encrypted message from another player.

Syntax

typedef struct {
    DWORD   dwType;
    DWORD   dwFlags;
    DPID    dpIdFrom;
    LPVOID  lpData;
    DWORD   dwDataSize;
} DPMSG_SECUREMESSAGE, FAR *LPDPMSG_SECUREMESSAGE;

Members

dwType
Identifies the system message type. This is DPSYS_SECUREMESSAGE.
dwFlags
Flags indicating how the message was secured by the sender. One of the following values:
DPSEND_SIGNED - the message was signed by the sender and the signature was successfully verified.
DPSEND_ENCRYPTED - the messages was encrypted by the sender and successfully decrypted.
dpIdFrom
The DPID of the player that sent the secure message.
lpData
Pointer to a buffer containing the fully verified message.
dwDataSize
Size of the buffer containing the message.

See Also

IDirectPlay4::Send


DPMSG_SENDCOMPLETE

Sent to the receive queue to inform the application of the completion status of an asynchronous send. This message is generated by default whenever an asynchronous message is sent using the DPSEND_ASYNC flag in IDirectPlay4::SendEx.

Syntax

typedef struct{
    DWORD    dwType;
    DPID     idFrom;
    DPID     idTo;
    DWORD    dwFlags;
    DWORD    dwPriority;
    DWORD    dwTimeout;
    LPVOID   lpContext;
    DWORD    dwMsgID;
    HRESULT  hr;
    DWORD    dwSendTime;
} DPMSG_SENDCOMPLETE, FAR *LPDPMSG_SENDCOMPLETE;

Members

dwType
Value that identifies the message. This member is DPSYS_SENDCOMPLETE.
idFrom
DPID of the player who sent the message.
idTo
DPID of the player the message was sent to.
dwFlags
Flags specified in SendEx when the message was sent.
dwPriority
Priority that the message was sent at.
dwTimeout
Timeout specified when the message was sent (specified in SendEx). Zero indicates the default timeout.
lpContext
lpContext parameter supplied by the application to SendEx.
dwMsgID
dwMsgID returned to the application by DirectPlay through SendEx.
hr
HRESULT of the asynchronous message. Can be one of the following values.
DP_OK – message was successfully sent.
DPERR_ABORTED – message was cancelled while it was being transmitted.
DPERR_CANCELLED – message was cancelled while it was still in the send queue.
DPERR_GENERIC – message could not be sent.
DPERR_TIMEOUT – message timed out and was removed from the send queue.
dwSendTime
The elapsed time, in milliseconds, between the time the message was sent by the application (by calling SendEx) and the time DirectPlay was able to send the message. This includes the time spent in the send queue and the time to hand the message off to the service provider. For guaranteed messages, this also includes the time to acknowledge delivery of the message.

See Also

IDirectPlay4::SendEx


DPMSG_SESSIONLOST

This message is generated by DirectPlay when the connection to all the other players in the session is lost. After the session is lost, messages cannot be sent to remote players, but all data at the time the session was lost is still available. Your applications should try to recover gracefully and exit if this message is received.

Syntax

typedef DPMSG_GENERIC    DPMSG_SESSIONLOST;
typedef DPMSG_SESSIONLOST  FAR  *LPDPMSG_SESSIONLOST;


DPMSG_SETGROUPOWNER

This message is generated by DirectPlay when the owner of a group has changed. Group ownership can be changed by the current owner leaving the session, by a call to IDirectPlay4::SetGroupOwner, or, arbitrarily, by the lobby server in a lobby session.

Syntax

typedef struct{
  DWORD   dwType;
  DPID    idGroup;
  DPID    idNewOwner;
  DPID    idOldOwner;
} DPMSG_SETGROUPOWNER, FAR *LPDPMSG_SETGROUPOWNER;

Members

dwType
Value that identifies the message. This member is DPSYS_SETGROUPOWNER.
idGroup
DPID of the group whose owner changed.
idNewOwner
DPID of the player who is the new owner of the group.
idOldOwner
DPID of the player who was the old owner of the group.

See Also

IDirectPlay4::SetGroupOwner


DPMSG_SETPLAYERORGROUPDATA

Contains information for the DPSYS_SETPLAYERORGROUPDATA system message. DirectPlay generates this message and sends it to each player when the remote data of a player or group changes. This message will not be generated if the DPSESSION_ NODATAMESSAGES flag is specified in the session description.

Syntax

typedef struct {
    DWORD  dwType;
    DWORD  dwPlayerType;
    DPID   dpId;
    LPVOID lpData;
    DWORD  dwDataSize;
} DPMSG_SETPLAYERORGROUPDATA, FAR *LPDPMSG_SETPLAYERORGROUPDATA;

Members

dwType
Identifies the message. This member is always DPSYS_SETPLAYERORGROUPDATA.
dwPlayerType
Identifies whether the message applies to a player (DPPLAYERTYPE_PLAYER) or a group (DPPLAYERTYPE_GROUP).
dpId
ID of the player or group whose data changed.
lpData
Pointer to an application-specific block of data.
dwDataSize
Size of the data contained in the buffer referenced by lpData.

Remarks

It is not necessary for the application to save the data from this message because it can be retrieved at any time using IDirectPlay4::GetPlayerData or IDirectPlay4::GetGroupData.

See Also

IDirectPlay4::GetPlayerData, IDirectPlay4::GetGroupData, IDirectPlay4::SetPlayerData, IDirectPlay4::SetGroupData


DPMSG_SETPLAYERORGROUPNAME

Contains information for the DPSYS_SETPLAYERORGROUPNAME system message. DirectPlay generates this message and sends it to each local player on the computer when the name of a player or group changes. This message will not be generated if the DPSESSION_NODATAMESSAGES flag is specified in the session description.

Syntax

typedef struct {
    DWORD  dwType;
    DWORD  dwPlayerType;
    DPID   dpId;
    DPNAME dpnName;
} DPMSG_SETPLAYERORGROUPNAME, FAR *LPDPMSG_SETPLAYERORGROUPNAME;

Members

dwType
Identifies the message. This member is always DPSYS_SETPLAYERORGROUPNAME.
dwPlayerType
Identifies whether the message applies to a player (DPPLAYERTYPE_PLAYER) or a group (DPPLAYERTYPE_GROUP).
dpId
ID of the player or group whose name changed.
dpnName
Structure containing the new name information for the player or group.

Remarks

It is not necessary for the application to save the dpnName from this message because it can be retrieved at any time using IDirectPlay4::GetPlayerName or IDirectPlay4::GetGroupName.

See Also

IDirectPlay4::GetPlayerName, IDirectPlay4::GetGroupName, IDirectPlay4::SetPlayerName, IDirectPlay4::SetGroupName


DPMSG_SETSESSIONDESC

Contains information for the DPSYS_SETSESSIONDESC system message. Every player will receive this system message when the session description changes.

This messages will not be generated if the DPSESSION_NODATAMESSAGES flag is specified in the session description.

Syntax

typedef struct
{
    DWORD           dwType;
    DPSESSIONDESC2  dpDesc;
} DPMSG_SETSESSIONDESC, FAR *LPDPMSG_SETSESSIONDESC;

Members

dwType
Identifies the message. This member is always DPSYS_SETSESSIONDESC.
dpDesc
Pointer to a DPSESSIONDESC2 structure containing the updated session description.

See Also

IDirectPlay4::GetSessionDesc, IDirectPlay4::SetSessionDesc


DPMSG_STARTSESSION

Contains information for the DPSYS_STARTSESSION system message. The lobby server sends this message to each player in a group when it is time for that player to join an application session.

Syntax

typedef struct {
   DWORD            dwType;
   LPDPLCONNECTION  lpConn;
} DPMSG_STARTSESSION, FAR *LPDPMSG_STARTSESSION;

Members

dwType
Identifies the message. This member is always DPSYS_STARTSESSION.
lpConn
Pointer to a DPLCONNECTION structure that contains all the information needed to launch an application into a session. This structure can be passed into IDirectPlayLobby3::RunApplication (if an external application is to be launched) or passed into IDirectPlayLobby3::SetConnectionSettings and then followed by a call to IDirectPlayLobby3::Connect (to connect the current application to the session).

Remarks

Upon receipt of this message by a stand-alone lobby client, the client must launch the application by calling the IDirectPlayLobby3::RunApplication method with the DPLCONNECTION structure.

Upon receipt of this message by an application with an internal lobby, the application must set the connection settings by calling IDirectPlayLobby3::SetConnectionSettings and then connect to the session using the IDirectPlayLobby3::Connect method.

See Also

IDirectPlay4::StartSession, IDirectPlayLobby3::RunApplication, IDirectPlayLobby3::SetConnectionSettings, IDirectPlayLobby3::Connect


Standard Lobby Messages

Two new system messages, DPLMSG_NEWSESSIONHOST and DPLMSG_SYSTEMMESSAGE, have been added for Microsoft® DirectPlay® 6.0.

To determine whether the lobby that launched your application supports standard lobby messages, it is necessary to send the lobby an initial DPLMSG_GETPROPERTY request and see whether it responds. The property that should be requested is DPLPROPERTY_MessagesSupported.

If the lobby responds with TRUE, then you can assume that it will respond to all further messages. If it responds with FALSE or does not respond at all within a specified timeout, then you can assume that messages are not supported.

If the application supports spectator players, the application should also request DPLPROPERTY_PlayerGuid before creating players in order to determine if they should be created as spectators or not.

The DirectPlay standard lobby messages are:

  • DPLMSG_GENERIC
  • DPLMSG_GETPROPERTY
  • DPLMSG_GETPROPERTYRESPONSE
  • DPLMSG_NEWSESSIONHOST
  • DPLMSG_SETPROPERTY
  • DPLMSG_SETPROPERTYRESPONSE
  • DPLMSG_SYSTEMMESSAGE


DPLMSG_GENERIC

Generic structure of system messages passed between the lobby client and an application.

Syntax

typedef struct {
    DWORD dwType;
} DPLMSG_GENERIC, FAR *LPDPLMSG_GENERIC;

Members

dwType
Identifies what type of system message has been received.

Remarks

When a lobby system message is received (that is, the value pointed to by the lpidFrom parameter equals DPID_SYSMSG), first cast the unknown message data to the DPLMSG_GENERIC type, and then perform further processing based on the value of dwType. After the message type has been determined, the message can cast to one of the known types of lobby system messages for further processing.

See Using Lobby Messages for a list of lobby message types.

See Also

DPLMSG_SYSTEMMESSAGE


DPLMSG_GETPROPERTY

Message sent by an application to the lobby to request the current value of a property. These properties can be information such as the ranking of a player, a bitmap representing a player, or initial configuration information for the game or players that was done inside the lobby.

Syntax

typedef struct {
    DWORD   dwType;
    DWORD   dwRequestID;
    GUID    guidPlayer;
    GUID    guidPropertyTag;
} DPLMSG_GETPROPERTY, FAR *LPDPLMSG_GETPROPERTY;

Members

dwType
Identifies the message. This value is DPLSYS_ GETPROPERTY.
dwRequestID
An application generated ID to identify the request. When the lobby responds, it will be tagged with this request ID. The application can use the request ID to match responses to pending requests.
guidPlayer
GUID identifying the player that this property applies to (if applicable). If the property is not player-specific, this member should be set to GUID_NULL. The GUID for the player or players created by this application can be obtained from the lobby by requesting the DPLPROPERTY_PlayerGuid property.
guidPropertyTag
A GUID identifying the property that is being requested. The property can one of the predefined ones listed in the section DirectPlay Defined Properties or the application/lobby can define its own GUIDs for additional properties.

Remarks

Each property is identified by a GUID (defined by the application developer or the lobby developer). When a request for a property is made, the lobby responds with a DPLMSG_GETPROPERTYRESPONSE message. Even if the lobby cannot supply the information, it should respond with an error indicating the information is unavailable.

The application should not block waiting for a response and should have a way to time-out pending requests that haven't been fulfilled.

See Also

DPLMSG_GETPROPERTYRESPONSE


DPLMSG_GETPROPERTYRESPONSE

Message sent by a lobby to an application in response to a DPLMSG_GETPROPERTY message. The request that is being filled is identified by the dwRequestID parameter.

Syntax

typedef struct {
    DWORD    dwType;
    DWORD    dwRequestID
    GUID     guidPlayer;
    GUID     guidPropertyTag;
    HRESULT  hr;
    DWORD    dwDataSize;
    DWORD    dwPropertyData[1];
} DPLMSG_GETPROPERTYRESPONSE, FAR *LPDPLMSG_GETPROPERTYRESPONSE;

Members

dwType
Identifies the message. This value is DPLSYS_ GETPROPERTYRESPONSE.
dwRequestID
The ID that identifies the DPLMSG_GETPROPERTY message that this message is in response to.
guidPlayer
GUID identifying the player that this property applies to (if applicable). If the property is not player-specific, this member will be set to GUID_NULL. This will be the same as the GUID from the DPLMSG_GETPROPERTY message.
guidPropertyTag
A GUID identifying the property that is being requested. This will be the same as the GUID from the DPLMSG_GETPROPERTY message.
hr
Return code for the get property request. One of the following values:
DP_OK - successfully returned the property.
DPERR_UNKNOWN - the requested property is unknown to the lobby.
DPERR_UNAVAILABLE - the requested property is unavailable.
dwDataSize
The size, in bytes, of the property data.
dwPropertyData
A variable-size buffer that contains the property data. The property tag will define how to interpret this data.

Remarks

A lobby must either respond to all DPLMSG_GETPROPERTY requests or none of them.

When constructing this message, the lobby needs to allocate enough memory to hold the DPLMSG_GETPROPERTYRESPONSE structure and the complete property data. For example, if the property data requires 52 bytes, the lobby will allocate (sizeof(DPLMSG_GETPROPERTYRESPONSE) + 52) bytes and assign it to a DPLMSG_GETPROPERTYRESPONSE pointer.

See Also

DPLMSG_GETPROPERTY


DPLMSG_NEWSESSIONHOST

This message is generated by DirectPlay and sent to the lobby client/provider when the client on the computer becomes the new host of the application session.

Syntax

typedef struct {
    DWORD    dwType;
    GUID     guidInstance;
} DPLMSG_NEWSESSIONHOST, FAR *LPDPLMSG_NEWSESSIONHOST;

Members

dwType
Value that identifies the message. This value is DPLSYS_ NEWSESSIONHOST.
guidInstance
Value that identifies the globally unique identifier (GUID) of this instance of the session.


DPLMSG_SETPROPERTY

Message sent by an application to the lobby to inform it that a property of a specific player or a property of the session has changed. These properties can range from the score or status of a player to the current level of a game or the current status of the session.

Syntax

typedef struct {
    DWORD    dwType;
    DWORD    dwRequestID
    GUID     guidPlayer;
    GUID     guidPropertyTag;
    DWORD    dwDataSize;
    DWORD    dwPropertyData[1];
} DPLMSG_SETPROPERTY, FAR *LPDPLMSG_SETPROPERTY;

Members

dwType
Identifies the message. This value is DPLSYS_ SETPROPERTY.
dwRequestID
A nonzero request ID supplied by the application if it would like confirmation that the data was recognized and set appropriately. If no confirmation is required, set this to DPL_NOCONFIRMATION.
guidPlayer
GUID identifying the player that this property applies to (if applicable). If the property is not player-specific, this member should be set to GUID_NULL. The GUID for the player or players created by this application can be obtained from the lobby by requesting the DPLPROPERTY_PlayerGuid property.
guidPropertyTag
A GUID identifying the property that is being set. The property can be one of the predefined GUIDs listed in the section DirectPlay Defined Properties or the application/lobby can define its own GUIDs for additional properties.
dwDataSize
The size, in bytes, of the property data.
dwPropertyData
A variable size buffer that contains the property data. The property tag will define how to interpret this data.

Remarks

Each property is identified by a GUID (defined by the application developer or the lobby developer), and it is the responsibility of the lobby to maintain a mapping of property GUIDs of the various applications to their descriptions and data types. The lobby server can choose to act on the information or ignore it.

When constructing this message, the application needs to allocate enough memory to hold the DPLMSG_ SETPROPERTY structure and the complete property data. For example, if the property data requires 52 bytes, the application will allocate (sizeof(DPLMSG_SETPROPERTY) + 52) bytes and assign it to a LPDPLMSG_SETPROPERTY pointer.

See Also

DPLMSG_SETPROPERTYRESPONSE


DPLMSG_SETPROPERTYRESPONSE

Message sent by a lobby to an application as confirmation of a DPLMSG_SETPROPERTY message. The message that is being confirmed is identified by the dwRequestID parameter.

Syntax

typedef struct {
    DWORD    dwType;
    DWORD    dwRequestID
    GUID     guidPlayer;
    GUID     guidPropertyTag;
    HRESULT  hr;
} DPLMSG_SETPROPERTYRESPONSE, FAR *LPDPLMSG_SETPROPERTYRESPONSE;

Members

dwType
Identifies the message. This value is DPLSYS_ SETPROPERTYRESPONSE.
dwRequestID
The ID that identifies the DPLMSG_SETPROPERTY message being confirmed.
guidPlayer
GUID identifying the player that this property was set for (if applicable). If the property is not player-specific, this member is GUID_NULL. This must be the same as the GUID from the DPLMSG_SETPROPERTY message.
guidPropertyTag
A GUID identifying the property that was set. This must be the same as the GUID from the DPLMSG_SETPROPERTY message.
hr
Result of the confirmation. One of the following values:
DP_OK - the property was set correctly.
DPERR_ACCESSDENIED - an attempt was made to set a property the lobby will not allow to be changed.
DPERR_UNKNOWN - the property is unknown to the lobby.

See Also

DPLMSG_SETPROPERTY


DPLMSG_SYSTEMMESSAGE

The structure of a system message passed between the lobby and an application.

Syntax

typedef struct {
    DWORD    dwType;
    GUID     guidInstance;
} DPLMSG_SYSTEMMESSAGE, FAR *LPDPLMSG_SYSTEMMESSAGE;

Members

dwType
Identifies what type of system message has been received.
DPLSYS_APPTERMINATED
Indicates the application started by IDirectPlayLobby3::RunApplication has terminated.
DPLSYS_CONNECTIONSETTINGSREAD
Indicates the application started by the IDirectPlayLobby3::RunApplication method has read the connection settings.
DPLSYS_DPLAYCONNECTFAILED
Indicates the application started by IDirectPlayLobby3::RunApplication failed to connect to a session.
DPLSYS_DPLAYCONNECTSUCCEEDED
Indicates the application started by IDirectPlayLobby3::RunApplication has created a session and is ready for other applications to join or has successfully joined a session.
DPLSYS_NEWCONNECTIONSETTINGS
Indicates that a waiting application application was found when a lobby client called RunApplication. The waiting application can now read the connection settings with GetConnectionSettings and join a session using ConnectEx.
guidInstance
GUID identifying the instance of the DirectPlay session that this message corresponds to.


DirectPlay Defined Properties

This section describes the defined properties that can be set and retrieved by applications from a lobby.

When a DPLMSG_GETPROPERTYRESPONSE message is received, its guidPropertyTag field identifies the property and its dwPropertyData field contains the property information. To extract this information, cast the dwPropertyData field to the appropriate value. For example, the following routine retrieves the DPLDATA_PLAYERGUID structure from the given message:

BOOL GetPlayerGuid(LPDPLMSG_GETPROPERTYRESPONSE  lpPropertyResponseMsg,
                       LPDPLDATA_PLAYERGUID lpPlayerGuid)
{
   if (IsEqualGUID(lpPropertyResponseMsg->guidPropertyTag, DPLPROPERTY_PlayerGuid))
   {
      *lpPlayerGuid = *((LPDPLDATA_PLAYERGUID) lpPropertyResponseMsg->dwPropertyData);
      return (TRUE);
   }
   else
   {
      return (FALSE);
   }
}

See the following descriptions of defined properties.

  • DPLPROPERTY_LobbyGuid
  • DPLPROPERTY_MessagesSupported
  • DPLPROPERTY_PlayerGuid
  • DPLPROPERTY_PlayerScore


DPLPROPERTY_LobbyGuid

A GUID used to identify the lobby software. If an application was designed to interoperate with a specific lobby using custom messages, this property can be used to identify the lobby.

However, an application should attempt to use standard messages whenever possible to be able to interoperate with as many lobbies as possible.

For this property, the dwPropertyData field of the DPLMSG_GETPROPERTYRESPONSE structure will contain the following:

GUID  guidLobby;


DPLPROPERTY_MessagesSupported

A Boolean value indicating whether the lobby supports standard messages. An application can request this property from the lobby to determine if it supports standard messages. If the lobby does not respond to this message, or if it responds with FALSE, the application should assume that it does not support standard lobby messages and should not send any further messages. If the lobby returns TRUE, the application should freely send standard messages to the lobby and query for further properties of the lobby.

For this property, the dwPropertyData field of the DPLMSG_GETPROPERTYRESPONSE structure will contain the following:

BOOL  fMessagesSupported;


DPLPROPERTY_PlayerGuid

A GUID used to uniquely identify the application's local players. Any further DPLMSG_SETPROPERTY or DPLMSG_GETPROPERTY messages that require a player GUID will need to use this value to communicate with the lobby.

An application can manipulate properties for remote players on another computer. The application only needs to obtain the player GUID from the remote player (not from the lobby).

If an application supports spectator players, it should request this property before creating any players in order to determine what flags (if any) to use when creating the players; for example, DPPLAYER_SPECTATOR and DPPLAYER_SERVERPLAYER.

For this property, the dwPropertyData field of the DPLMSG_GETPROPERTYRESPONSE structure will contain the following:

typedef struct {
    GUID  guidPlayer;
    DWORD dwPlayerFlags;
} DPLDATA_PLAYERGUID, FAR *LPDPLDATA_PLAYERGUID;


DPLPROPERTY_PlayerScore

A generic structure that can be used by an application to report a composite score value to the lobby. The guidPlayer GUID of the player the score applies to must be provided when setting or getting this property. This structure can handle an arbitrary list of long integer values that collectively represent the score of a player. The application must allocate enough memory to hold all the scores. For example, if the score was passed as N integers, the application must allocate ( sizeof(DPLDATA_PLAYERSCORE) + N*sizeof(LONG) ) bytes and cast the pointer to LPDPLDATA_PLAYERSCORE.

For this property, the dwPropertyData field of the DPLMSG_GETPROPERTYRESPONSE structure will contain the following:

typedef struct {
    DWORD   dwScoreCount;
    LONG    Score[1];
} DPLDATA_PLAYERSCORE, FAR *LPDPLDATA_PLAYERSCORE;


Return Values

Errors are represented by negative values and cannot be combined. This table lists the values that can be returned by all IDirectPlay4 interface and IDirectPlayLobby3 interface methods. For a list of the error values each method can return, see the individual method descriptions.

Many of the DirectPlay samples include a GetDirectPlayErrStr function that converts HRESULT values to string names for the DirectPlay errors. Developers can copy this code into their own applications for diagnostic traces or error reports.

CLASS_E_NOAGGREGATION
A non-NULL value was passed for the pUnkOuter parameter in DirectPlayCreate, DirectPlayLobbyCreate, or IDirectPlayLobby3::Connect.
DP_OK
The request completed successfully.
DPERR_ACCESSDENIED
The session is full, or an incorrect password was supplied.
DPERR_ACTIVEPLAYERS
The requested operation cannot be performed because there are existing active players.
DPERR_ALREADYINITIALIZED
This object is already initialized.
DPERR_APPNOTSTARTED
The application has not been started yet.
DPERR_AUTHENTICATIONFAILED
The password or credentials supplied could not be authenticated.
DPERR_BUFFERTOOLARGE
The data buffer is too large to store.
DPERR_BUFFERTOOSMALL
The supplied buffer is not large enough to contain the requested data.
DPERR_BUSY
A message cannot be sent because the transmission medium is busy.
DPERR_CANCELFAILED
The message could not be canceled, possibly because it is a group message that has already been to sent to one or more members of the group.
DPERR_CANNOTCREATESERVER
The server cannot be created for the new session.
DPERR_CANTADDPLAYER
The player cannot be added to the session.
DPERR_CANTCREATEGROUP
A new group cannot be created.
DPERR_CANTCREATEPLAYER
A new player cannot be created.
DPERR_CANTCREATEPROCESS
Cannot start the application.
DPERR_CANTCREATESESSION
A new session cannot be created.
DPERR_CANTLOADCAPI
No credentials were supplied and the CryptoAPI package (CAPI) to use for cryptography services cannot be loaded.
DPERR_CANTLOADSECURITYPACKAGE
The software security package cannot be loaded.
DPERR_CANTLOADSSPI
No credentials were supplied, and the Security Support Provider Interface (SSPI) that will prompt for credentials cannot be loaded.
DPERR_CAPSNOTAVAILABLEYET
The capabilities of the DirectPlay object have not been determined yet. This error will occur if the DirectPlay object is implemented on a connectivity solution that requires polling to determine available bandwidth and latency.
DPERR_CONNECTING
The method is in the process of connecting to the network. The application should keep using the method until it returns DP_OK, indicating successful completion, or until it returns a different error.
DPERR_CONNECTIONLOST
The service provider connection was reset while data was being sent.
DPERR_ENCRYPTIONFAILED
The requested information could not be digitally encrypted. Encryption is used for message privacy. This error is only relevant in a secure session.
DPERR_ENCRYPTIONNOTSUPPORTED
The type of encryption requested in the DPSECURITYDESC structure is not available. This error is only relevant in a secure session.
DPERR_EXCEPTION
An exception occurred when processing the request.
DPERR_GENERIC
An undefined error condition occurred.
DPERR_INVALIDFLAGS
The flags passed to this method are invalid.
DPERR_INVALIDGROUP
The group ID is not recognized as a valid group ID for this game session.
DPERR_INVALIDINTERFACE
The interface parameter is invalid.
DPERR_INVALIDOBJECT
The DirectPlay object pointer is invalid.
DPERR_INVALIDPARAMS
One or more of the parameters passed to the method are invalid.
DPERR_INVALIDPASSWORD
An invalid password was supplied when attempting to join a session that requires a password.
DPERR_INVALIDPLAYER
The player ID is not recognized as a valid player ID for this game session.
DPERR_INVALIDPRIORITY
The specified priority is not within the range of allowed priorities, which is inclusively 0-65535.
DPERR_LOGONDENIED
The session could not be opened because credentials are required, and either no credentials were supplied, or the credentials were invalid.
DPERR_NOCAPS
The communication link that DirectPlay is attempting to use is not capable of this function.
DPERR_NOCONNECTION
No communication link was established.
DPERR_NOINTERFACE
The interface is not supported.
DPERR_NOMESSAGES
There are no messages in the receive queue.
DPERR_NONAMESERVERFOUND
No name server (host) could be found or created. A host must exist to create a player.
DPERR_NONEWPLAYERS
The session is not accepting any new players.
DPERR_NOPLAYERS
There are no active players in the session.
DPERR_NOSESSIONS
There are no existing sessions for this game.
DPERR_NOTLOBBIED
Returned by the IDirectPlayLobby3::Connect method if the application was not started by using the IDirectPlayLobby3::RunApplication method, or if there is no DPLCONNECTION structure currently initialized for this DirectPlayLobby object.
DPERR_NOTLOGGEDIN
An action cannot be performed because a player or client application is not logged in. Returned by the IDirectPlay4::Send method when the client application tries to send a secure message without being logged in.
DPERR_OUTOFMEMORY
There is insufficient memory to perform the requested operation.
DPERR_PENDING
Not an error, this return indicates that an asynchronous send has reached the point where it is successfully queued. See SendEx for more information.
DPERR_PLAYERLOST
A player has lost the connection to the session.
DPERR_SENDTOOBIG
The message being sent by the IDirectPlay4::Send method is too large.
DPERR_SESSIONLOST
The connection to the session has been lost.
DPERR_SIGNFAILED
The requested information could not be digitally signed. Digital signatures are used to establish the authenticity of messages.
DPERR_TIMEOUT
The operation could not be completed in the specified time.
DPERR_UNAVAILABLE
The requested function is not available at this time.
DPERR_UNINITIALIZED
The requested object has not been initialized.
DPERR_UNKNOWNAPPLICATION
An unknown application was specified.
DPERR_UNKNOWNMESSAGE
The message ID isn't valid. Returned from IDirectPlay4::CancelMessage if the ID of the message to be cancelled is invalid.
DPERR_UNSUPPORTED
The function or feature is not available in this implementation or on this service provider. Returned from IDirectPlay4::GetGroupConnectionSettings and IDirectPlay4::SetGroupConnectionSettings if they are called from a session that is not a lobby session. Returned from IDirectPlay4::SendEx if the priority or timeout is set, and these are not supported by the service provider and DirectPlay protocol is not on. Returned from IDirectPlay4::GetMessageQueue if you check the send queue and this is not supported by the service provider and DirectPlay protocol is not on.
DPERR_USERCANCEL
Can be returned in two ways. 1) The user canceled the connection process during a call to the IDirectPlay4::Open method. 2) The user clicked Cancel in one of the DirectPlay service provider dialog boxes during a call to IDirectPlay4::EnumSessions.
E_UNKNOWN
Usually indicates a catastrophic failure of some sort; for example, the service provider cannot initialize correctly or a protocol such as IPX is not installed correctly on the machine.


Further Reading

Accessing COM
A section in the Microsoft® DirectX® 6.0 documentation, under the heading "Introducing DirectX 6," within the topic "DirectX and the Component Object Model." This topic describes how COM implements DirectX objects and interfaces.
IUnknown Interface
All COM interfaces are derived from the IUnknown interface. This interface provides control of the object's lifetime and the ability to navigate multiple interfaces. IUnknown has three methods: AddRef, which increments the object's reference count by 1 when an interface or another application binds itself to the object; QueryInterface, which queries the object about the features it supports by requesting pointers to a specific interface; and Release, which decrements the object's reference count by 1. When the count reaches 0, the object is deallocated. See also AddRef and QueryInterface
IUnknown::AddRef and IUnknown::Release
These IUnknown methods maintain an object's reference count. For example, if you create a DirectPlay object (with CoCreateInstance, for example), the object's reference count is set to 1. Every time a function returns a pointer to an interface for that object, the function must call AddRef through that pointer to increment the reference count. You must match each AddRef call with a call to Release. Before the pointer can be destroyed, you must call Release through that pointer. After an object's reference count reaches 0, the object is destroyed and all interfaces to it become invalid.
IUnknown::QueryInterface
This IUnknown method determines whether an object supports a specific interface. If an object supports the interface, QueryInterface returns a pointer to that interface. You then can use the methods contained in that interface to communicate with the object. If QueryInterface successfully returns a pointer to an interface, it implicitly calls AddRef to increment the reference count, so your application must call Release to decrement the reference count before destroying the pointer to the interface.


Quick Reference Information (QuickInfo)

Many topics that introduce the syntax of an API element contain quick reference information. The format is as follows:

QuickInfo

Windows NT: Requires version 3.1 or later.
Windows: Requires Windows 95 or later.
Windows CE: Requires version 1.0 or later.
Header: Declared in winuser.h.
Import Library: Use user32.lib.
Unicode: Implemented as Unicode and ANSI versions on Windows NT.

The first line indicates the versions of Windows NT on which an element is supported. This information may include required service packs, option packs, or components such as Internet Explorer. If an element is not supported, the line reads "Windows NT: Unsupported."

The second line indicates whether an element is supported on Windows 95 or Windows 98. This information may include required OEM service releases, redistributables, or components such as Internet Explorer. If an element is not supported, the line reads "Windows: Unsupported."

The third line indicates the versions of Windows CE on which an element is supported. If an element is not supported, the line reads "Windows CE: Unsupported."

The fourth line indicates the file that defines an element. This value can be an .h file, .idl file, or .odl file. If the header file is supplied by the user, the line reads "Header: User-defined."

The fifth line indicates the file used to resolve calls to a function or member. This value can be a .lib file, .dll file, or .tlb file. If the import library is supplied by the user, the line reads "Import Library: User-defined." For element types that do not require an import library, this line is omitted.

The sixth line indicates whether an element exists as both a Unicode (W) version and an ANSI (A) version. If Unicode support is not available, this line is omitted.


CopyRight

NOTICE SPECIFIC TO SOFTWARE AVAILABLE ON THIS SITE

Any software that is made available to download from this server ("Software") is the copyrighted work of Microsoft Corporation and/or its suppliers. Use of the Software is governed by the terms of the end user license agreement, if any, which accompanies or is included with the Software ("License Agreement") . An end user will be unable to install any Software that is accompanied by or includes a License Agreement, unless he or she first agrees to the License Agreement terms.

The Software is made available for downloading solely for use by end users according to the License Agreement. Any reproduction or redistribution of the Software not in accordance with the License Agreement is expressly prohibited by law, and may result in severe civil and criminal penalties. Violators will be prosecuted to the maximum extent possible.

WITHOUT LIMITING THE FOREGOING, COPYING OR REPRODUCTION OF THE SOFTWARE TO ANY OTHER SERVER OR LOCATION FOR FURTHER REPRODUCTION OR REDISTRIBUTION IS EXPRESSLY PROHIBITED.

THE SOFTWARE IS WARRANTED, IF AT ALL, ONLY ACCORDING TO THE TERMS OF THE LICENSE AGREEMENT. EXCEPT AS WARRANTED IN THE LICENSE AGREEMENT, MICROSOFT CORPORATION HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS WITH REGARD TO THE SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES AND CONDITIONS OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT.

RESTRICTED RIGHTS LEGEND. Any Software which is downloaded from this Server for or on behalf of the United States of America, its agencies and/or instrumentalities ("U.S. Government"), is provided with Restricted Rights. Use , duplication, or disclosure by the U.S. Government is subject to restrictions as set forth in subparagraph (c)(1)(ii) of the Rights in Technical Data and Computer Software clause at DFARS 252.227-7013 or subparagraphs (c)(1) and (2) of the Commercial Computer Software - Restricted Rights at 48 CFR 52.227-19, as applicable. Manufacturer is Microsoft Corporation, One Microsoft Way, Redmond, WA 98052-6399.

NOTICE SPECIFIC TO DOCUMENTS AVAILABLE ON THIS SITE

Permission to use Documents (such as white papers, press releases, datasheets and FAQs) from this server ("Server") is granted, provided that (1) the below copyright notice appears in all copies and that both the copyright notice and this permission notice appear, (2) use of such Documents from this Server is for informational and non-commercial or personal use only and will not be copied or posted on any network computer or broadcast in any media, and (3) no modifications of any Documents are made. Use for any other purpose is expressly prohibited by law, and may result in severe civil and criminal penalties. Violators will be prosecuted to the maximum extent possible.

Documents specified above do not include the design or layout of the Microsoft .com Web site or any other Microsoft owned, operated, licensed or controlled site. Elements of Microsoft Web sites are protected by trade dress and other laws and may not be copied or imitated in whole or in part. No logo, graphic , sound or image from any Microsoft Web site may be copied or retransmitted unless expressly permitted by Microsoft.

MICROSOFT AND/OR ITS RESPECTIVE SUPPLIERS MAKE NO REPRESENTATIONS ABOUT THE SUITABILITY OF THE INFORMATION CONTAINED IN THE DOCUMENTS AND RELATED GRAPHICS PUBLISHED ON THIS SERVER FOR ANY PURPOSE. ALL SUCH DOCUMENTS AND RELATED GRAPHICS ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT AND/OR ITS RESPECTIVE SUPPLIERS HEREBY DISCLAIM ALL WARRANTIES AND CONDITIONS WITH REGARD TO THIS INFORMATION, INCLUDING ALL IMPLIED WARRANTIES AND CONDITIONS OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL MICROSOFT AND/OR ITS RESPECTIVE SUPPLIERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF INFORMATION AVAILABLE FROM THIS SERVER.

THE DOCUMENTS AND RELATED GRAPHICS PUBLISHED ON THIS SERVER COULD INCLUDE TECHNICAL INACCURACIES OR TYPOGRAPHICAL ERRORS. CHANGES ARE PERIODICALLY ADDED TO THE INFORMATION HEREIN. MICROSOFT AND/OR ITS RESPECTIVE SUPPLIERS MAY MAKE IMPROVEMENTS AND/OR CHANGES IN THE PRODUCT(S) AND/OR THE PROGRAM(S) DESCRIBED HEREIN AT ANY TIME.

NOTICES REGARDING SOFTWARE, DOCUMENTS AND SERVICES AVAILABLE ON THIS SITE.

IN NO EVENT SHALL MICROSOFT AND/OR ITS RESPECTIVE SUPPLIERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT , NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF SOFTWARE, DOCUMENTS, PROVISION OF OR FAILURE TO PROVIDE SERVICES, OR INFORMATION AVAILABLE FROM THIS SERVER.

LINKS TO THIRD PARTY SITES

THE LINKS IN THIS AREA WILL LET YOU LEAVE MICROSOFT'S SITE. THE LINKED SITES ARE NOT UNDER THE CONTROL OF MICROSOFT AND MICROSOFT IS NOT RESPONSIBLE FOR THE CONTENTS OF ANY LINKED SITE OR ANY LINK CONTAINED IN A LINKED SITE. MICROSOFT IS PROVIDING THESE LINKS TO YOU ONLY AS A CONVENIENCE, AND THE INCLUSION OF ANY LINK DOES NOT IMPLY ENDORSEMENT BY MICROSOFT OF THE SITE.

COPYRIGHT NOTICE. Copyright © 1998 Microsoft and/or its suppliers, One Microsoft Way, Redmond, Washington 98052-6399 U.S.A. All rights reserved.

TRADEMARKS. Microsoft, Windows, Windows NT, MSN, The Microsoft Network and/or other Microsoft products referenced herein are either trademarks or registered trademarks of Microsoft. Other product and company names mentioned herein may be the trademarks of their respective owners.

The names of companies, products, people, characters and/or data mentioned herein are fictitious and are in no way intended to represent any real individual, company, product or event, unless otherwise noted.

Any rights not expressly granted herein are reserved.

Contact Microsoft with questions or problems with this service.
**

** ** © 1998 Microsoft Corporation. All rights reserved. Terms of Use.


A

ambient
A light source that illuminates everything in a scene, regardless of the orientation, position, and surface characteristics of the objects in the scene. Because this illuminates a scene with equal strength everywhere, the position and orientation of the frame it is attached to are inconsequential. Multiple ambient light sources are combined within a scene.
array object
A group of objects organized into an array. Array objects make it simpler to apply operations to the entire group. The Component Object Model (COM) interfaces that enable you to work with array objects contain the GetElement and GetSize methods. These methods retrieve a pointer to an element in the array and the size of the array, respectively.


B

back buffer
A nonvisible surface that bitmaps and other images can be drawn to while the primary surface displays the currently visible image.
back clipping plane
The far boundary of a viewing frustum beyond which objects are not rendered. See also front clipping plane.


C

camera
A Direct3DRMFrame object used by the viewport to define the viewing position and direction. The viewport renders only what is visible along the positive z-axis of the camera frame, with the up direction being in the direction of the positive y-axis.


D

decal
A texture that is rendered directly as a visual. Decals are rendered into a viewport-aligned rectangle.
directional
A light source that is attached to a frame but appears to illuminate all objects with equal intensity, as if it were at an infinite distance from the objects. Directional light has orientation but no position, and it is commonly used to simulate distant light sources, such as the sun.


E

emissive property
The material property that determines whether a material emits light. The emissive property of a material is one of two properties that determines how the material reflects light. See also specular property.
enable frame
The frame to which a light applies.


F

front clipping plane
The near boundary of a viewing frustum. Any object closer to the camera than the front clipping plane is not rendered. The height of the front clipping plane defines the field of view. See also back clipping plane.


M

mipmap
A sequence of textures, each of which is a progressively lower-resolution, prefiltered representation of the same image. A higher-resolution image is used when a visible object is close to the viewer. As the object moves farther away (and gets smaller), lower-resolution images are used.
model coordinates
Coordinates that are relative to a child frame. See also world coordinates.


P

parallel point
A light source that illuminates objects with parallel light. The light's orientation is taken from the position of the parallel-point light source. For example, two meshes on both sides of a parallel point light source are lit on the side that faces the position of the source.
penumbra
The outer, dimly lit section of a spotlight's cone of light. The penumbra surrounds the umbra and merges with the surrounding deep shadow. See also umbra, and spotlight.
point
A light source that radiates equally in all directions from its origin.
power
In the specular property of a material, the value that determines the sharpness of specular highlights. A value of 5 gives a metallic appearance, and higher values give a more plastic appearance.


R

reference count
The manner in which a Component Object Model (COM) object controls its lifetime. When an object is created, its reference count is set to 1. When a pointer is assigned to point to one of the object's interfaces, the object's reference count is incremented. When the interface connection is destroyed, the reference count is decremented. The object is destroyed when the reference count reaches 0. All pointers to interfaces on that object are then invalid. See IUnknown Interface for more information.
root frame
A frame in Direct3D that has no parent frame. A frame at the top of a hierarchy of frames. The root frame contains the entire set of objects that make up a scene.


S

specular property
The material property that determines how a point of light on a shiny object corresponds to the reflected light source. The specular property of a material is one of two properties that determines how a material reflects light. See also emissive property.
spotlight
A light source that emits a cone of light. Only objects within the cone are illuminated. The cone produces light of two degrees of intensity with a central brightly lit section (the umbra) that acts as a point source, and a surrounding dimly lit section (the penumbra) that merges with the surrounding deep shadow.


T

texture blending
The technique of combining the colors of a texture with the colors of the surface to which the texture is applied.


U

umbra
The central brightly lit section of a cone of light. The umbra can act as a point source. See also penumbra and spotlight.


V

vertex split
A vertex split adds a new vertex near an existing vertex and adds two new faces. Thus, a complex mesh can be built from a simple mesh and a sequence of vertex split records that increasingly refine the mesh. This allows meshes to be progressively downloaded from remote sites.
viewing frustum
A 3-D volume in a scene positioned relative to the viewport's camera. Objects within the frustum are visible. For perspective viewing, the viewing frustum is the volume of an imaginary pyramid that is between the front clipping plane and the back clipping plane. For orthographic viewing, the viewing frustum is cuboid.


W

world coordinates
Coordinates that are relative to the root frame. See also model coordinates.


GLOSSARY HEAD

A B C D E F G H I J K L M N O P Q R S T U V W X Y Z


IDirect3DRMFrame3 Methods A to M

This section contains the reference pages for the methods of the IDirect3DRMFrame3 interface that begin with the letters A through M.

IDirect3DRMFrame3::AddChild

IDirect3DRMFrame3

Adds a child frame to a frame hierarchy.

Syntax

HRESULT AddChild(
  LPDIRECT3DRMFRAME3 lpD3DRMFrameChild
  );

Parameters

lpD3DRMFrameChild
Address of the Direct3DRMFrame object that will be added as a child.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

Remarks

If the frame being added as a child already has a parent, this method removes it from its previous parent before adding it to the new parent.

To preserve an object's transformation, use the IDirect3DRMFrame3::GetTransform method to retrieve the object's transformation before using the AddChild method. Then reapply the transformation after the frame is added.

See Also

Hierarchies

IDirect3DRMFrame3::AddLight

IDirect3DRMFrame3

Adds a light to a frame.

Syntax

HRESULT AddLight(
  LPDIRECT3DRMLIGHT lpD3DRMLight
  );

Parameters

lpD3DRMLight
Address of a variable that represents the Direct3DRMLight object to be added to the frame.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

IDirect3DRMFrame3::AddMoveCallback

IDirect3DRMFrame3

Adds a callback function for special movement processing. The callback is called when the frame is moved or updated.

Syntax

HRESULT AddMoveCallback(
  D3DRMFRAME3MOVECALLBACK d3drmFMC,
  VOID * lpArg,
  DWORD dwFlags
  );

Parameters

d3drmFMC
Application-defined D3DRMFRAME3MOVECALLBACK callback function.
lpArg
Application-defined data to be passed to the callback function.
dwFlags
One of the following values:
D3DRMCALLBACK_PREORDER — The default value. When IDirect3DRMFrame3::Move traverses the hierarchy, callbacks for a frame are used before any child frames are traversed.
D3DRMCALLBACK_POSTORDER — When IDirect3DRMFrame3::Move traverses the hierarchy, callbacks for a frame are used after the child frames are traversed.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

Remarks

This method replaces IDirect3DRMFrame2::AddMoveCallback2. Multiple callbacks on an individual frame are used in the order that the callbacks were created.

See Also

IDirect3DRMFrame3::Move, IDirect3DRMFrame3::DeleteMoveCallback

IDirect3DRMFrame3::AddRotation

IDirect3DRMFrame3

Adds a rotation about (rvX, rvY, rvZ) by the number of radians specified in rvTheta.

Syntax

HRESULT AddRotation(
  D3DRMCOMBINETYPE rctCombine,
  D3DVALUE rvX,
  D3DVALUE rvY,
  D3DVALUE rvZ,
  D3DVALUE rvTheta
  );

Parameters

rctCombine
A member of the D3DRMCOMBINETYPE enumerated type that specifies how to combine the new rotation with any current frame transformation.
rvX, rvY, and rvZ
Axis about which to rotate.
rvTheta
Angle of rotation, in radians.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

Remarks

The specified rotation changes the matrix only for the frame identified by this IDirect3DRMFrame3 interface. This method changes the objects in the frame only once, unlike IDirect3DRMFrame3::SetRotation, which changes the matrix with every render tick.

See Also

3-D Transformations, IDirect3DRMFrame3::SetRotation

IDirect3DRMFrame3::AddScale

IDirect3DRMFrame3

Scales a frame's local transformation by (rvX, rvY, rvZ).

Syntax

HRESULT AddScale(
  D3DRMCOMBINETYPE rctCombine,
  D3DVALUE rvX,
  D3DVALUE rvY,
  D3DVALUE rvZ
  );

Parameters

rctCombine
Member of the D3DRMCOMBINETYPE enumerated type that specifies how to combine the new scale with any current frame transformation.
rvX, rvY, and rvZ
Scale factors in the x-, y-, and z-directions.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

Remarks

The specified transformation only changes the matrix for the frame identified by the IDirect3DRMFrame3 interface.

See Also

3-D Transformations

IDirect3DRMFrame3::AddTransform

IDirect3DRMFrame3

Transforms the local coordinates of the frame by the affine transformation specified by rctCombine and rmMatrix.

Syntax

HRESULT AddTransform(
  D3DRMCOMBINETYPE rctCombine,
  D3DRMMATRIX4D rmMatrix
  );

Parameters

rctCombine
Member of the D3DRMCOMBINETYPE enumerated type that specifies how to combine the new transformation with any current transformation.
rmMatrix
Member of the D3DRMMATRIX4D array that defines the transformation matrix to be combined.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

Remarks

Although a 4×4 matrix is given, the last column must be the transpose of [0 0 0 1] for the transformation to be affine.

The specified transformation changes the matrix only for the frame identified by this IDirect3DRMFrame3 interface.

See Also

3-D Transformations

IDirect3DRMFrame3::AddTranslation

IDirect3DRMFrame3

Adds a translation by (rvX, rvY, rvZ) to a frame's local coordinate system.

Syntax

HRESULT AddTranslation(
  D3DRMCOMBINETYPE rctCombine,
  D3DVALUE rvX,
  D3DVALUE rvY,
  D3DVALUE rvZ
  );

Parameters

rctCombine
Member of the D3DRMCOMBINETYPE enumerated type that specifies how to combine the new translation with any current translation.
rvX, rvY, and rvZ
Definitions of the position changes in the x-, y-, and z-directions.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

Remarks

The specified translation changes the matrix only for the frame identified by this IDirect3DRMFrame3 interface.

See Also

3-D Transformations

IDirect3DRMFrame3::AddVisual

IDirect3DRMFrame3

Adds a visual object to a frame.

Syntax

HRESULT AddVisual(
  LPUNKNOWN lpD3DRMVisual
  );

Parameters

lpD3DRMVisual
Pointer to a variable that represents the visual object to be added to the frame.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

Remarks

Visual objects include meshes, progressive meshes, textures, shadows, user visuals, and 3-D DirectX Transform objects. When a visual object is added to a frame, it becomes visible if the frame is in view. The frame references the visual object.

IDirect3DRMFrame3::DeleteChild

IDirect3DRMFrame3

Removes a frame from the hierarchy. If the frame is not referenced, it is destroyed along with any child frames, lights, and meshes.

Syntax

HRESULT DeleteChild(
  LPDIRECT3DRMFRAME3 lpChild
  );

Parameters

lpChild
Address of the Direct3DRMFrame object to be used as the child.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

See Also

Hierarchies

IDirect3DRMFrame3::DeleteLight

IDirect3DRMFrame3

Removes a light from a frame, destroying the light if it is no longer referenced. When a light is removed from a frame, the light no longer affects meshes in the scene its frame was in.

Syntax

HRESULT DeleteLight(
  LPDIRECT3DRMLIGHT lpD3DRMLight
  );

Parameters

lpD3DRMLight
Address of a variable that represents the Direct3DRMLight object to be removed.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

IDirect3DRMFrame3::DeleteMoveCallback

IDirect3DRMFrame3

Removes a frame-move callback function previously added with AddMoveCallback.

Syntax

HRESULT DeleteMoveCallback(
  D3DRMFRAME3MOVECALLBACK d3drmFMC,
  VOID * lpArg
  );

Parameters

d3drmFMC
Application-defined D3DRMFRAME3MOVECALLBACK callback function.
lpArg
Application-defined data that was passed to the callback function.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

See Also

IDirect3DRMFrame3::AddMoveCallback, IDirect3DRMFrame3::Move

IDirect3DRMFrame3::DeleteVisual

IDirect3DRMFrame3

Removes a visual object from a frame, destroying it if it is no longer referenced.

Syntax

HRESULT DeleteVisual(
  LPUNKNOWN lpD3DRMVisual
  );

Parameters

lpD3DRMVisual
Address of a variable that represents the Direct3DRMVisual object to be removed.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

IDirect3DRMFrame3::GetAxes

IDirect3DRMFrame3

Retrieves the vectors that are aligned with the direction (rvDx, rvDy, rvDz) and up (rvUx, rvUy, rvUz) vectors supplied to the IDirect3DRMFrame3::SetOrientation method.

Syntax

HRESULT GetAxes(
  LPD3DVECTOR dir,
  LPD3DVECTOR up
  );

Parameters

dir
The z-axis for the frame. Default is (0,0,1).
up
The y-axis for the frame. Default is (0,1,0).

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

Remarks

This method along with IDirect3DRMFrame3::SetAxes helps support both left-handed and right-handed coordinate systems. SetAxes allows you to specify that the negative z-axis represents the front of the object.

See Also

IDirect3DRMFrame3::SetAxes, IDirect3DRMFrame3::GetInheritAxes, IDirect3DRMFrame3::SetInheritAxes

IDirect3DRMFrame3::GetBox

IDirect3DRMFrame3

Retrieves the bounding box containing a DIRECT3DRMFRAME2 object. The bounding box gives the minimum and maximum model coordinates in each dimension.

Syntax

HRESULT GetBox(
  D3DRMBOX * lpD3DRMBox
  );

Parameters

lpD3DRMBox
Address of a D3DRMBOX structure that will be filled with the bounding box coordinates.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. Returns D3DRMERR_BOXNOTSET unless a valid bounding box has already been set on the frame. For a list of other possible return codes, see Direct3D Retained Mode Return Values.

Remarks

This method supports a bounding box on a frame for hierarchical culling. A valid bounding box must be set on the frame with IDirect3DRMFrame3::SetBox. For a bounding box to be enabled, the IDirect3DRMFrame3::SetBoxEnable method must be used to set the enable flag to TRUE. By default, the box-enable flag is FALSE. There is no default bounding box.

See Also

IDirect3DRMFrame3::SetBox, IDirect3DRMFrame3::SetBoxEnable, IDirect3DRMFrame3::GetBoxEnable

IDirect3DRMFrame3::GetBoxEnable

IDirect3DRMFrame3

Retrieves the flag that determines whether a bounding box is enabled for this Direct3DRMFrame3 object.

Syntax

BOOL GetBoxEnable( );

Return Value

Returns TRUE if a bounding box is enabled, or FALSE if it is not enabled.

Remarks

For a bounding box to be enabled, the IDirect3DRMFrame3::SetBoxEnable flag must be used to set the enable flag to TRUE. By default, the box enable flag is FALSE.

See Also

IDirect3DRMFrame3::SetBoxEnable IDirect3DRMFrame3::GetBox, IDirect3DRMFrame3::SetBox

IDirect3DRMFrame3::GetChildren

IDirect3DRMFrame3

Retrieves a list of child frames in the form of a Direct3DRMFrameArray object.

Syntax

HRESULT GetChildren(
  LPDIRECT3DRMFRAMEARRAY* lplpChildren
  );

Parameters

lplpChildren
Address of a pointer to be initialized with a valid Direct3DRMFrameArray pointer if the call succeeds.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

See Also

DIRECT3DRMFRAMEARRAY, Hierarchies

IDirect3DRMFrame3::GetColor

IDirect3DRMFrame3

Retrieves the color of the frame.

Syntax

D3DCOLOR GetColor( );

Return Value

Returns the color of the Direct3DRMFrame2 object. By default, the color is white.

See Also

IDirect3DRMFrame3::SetColor

IDirect3DRMFrame3::GetHierarchyBox

IDirect3DRMFrame3

Calculates a bounding box to contain all the geometry in the hierarchy rooted in this Direct3DRMFrame3 object.

Syntax

HRESULT GetHierarchyBox(
  D3DRMBOX * lpD3DRMBox
  );

Parameters

lpD3DRMBox
Address of a D3DRMBOX structure that will be filled with the bounding box coordinates.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

See Also

IDirect3DRMFrame3::GetBox, IDirect3DRMFrame3::SetBox, IDirect3DRMFrame3::SetBoxEnable, IDirect3DRMFrame3::GetBoxEnable

IDirect3DRMFrame3::GetInheritAxes

IDirect3DRMFrame3

Retrieves the flag that indicates whether the axes for the frame are inherited from the parent frame.

Syntax

BOOL GetInheritAxes( );

Return Value

Returns TRUE if the frame inherits axes (the default) and FALSE if the frame does not inherit axes.

Remarks

By default, the axes are inherited from the parent. If a frame is set to inherit from a parent and there is no parent, the frame acts as if it inherits from a parent with the default axes (direction=(0,0,1) and up=(0,1,0)).

This method and the IDirect3DRMFrame3::SetInheritAxes method allow a single policy for axes to be set at the root of the hierarchy.

See Also

IDirect3DRMFrame3::SetInheritAxes, IDirect3DRMFrame3::GetAxes, IDirect3DRMFrame3::SetAxes

IDirect3DRMFrame3::GetLights

IDirect3DRMFrame3

Retrieves a list of lights in the frame in the form of a Direct3DRMLightArray object.

Syntax

HRESULT GetLights(
  LPDIRECT3DRMLIGHTARRAY* lplpLights
  );

Parameters

lplpLights
Address of a pointer to be initialized with a valid Direct3DRMLightArray pointer if the call succeeds.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

See Also

IDirect3DRMLightArray

IDirect3DRMFrame3::GetMaterial

IDirect3DRMFrame3

Retrieves the material of the Direct3DRMFrame2 object.

Syntax

HRESULT GetMaterial(
  LPDIRECT3DRMMATERIAL2 *lplpMaterial
  );

Parameters

lplpMaterial
Address of a variable that will be filled with a pointer to the Direct3DRMMaterial object that is applied to the frame. By default, the material is NULL.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

See Also

IDirect3DRMFrame3::SetMaterial

IDirect3DRMFrame3::GetMaterialMode

IDirect3DRMFrame3

Retrieves the material mode of the frame.

Syntax

D3DRMMATERIALMODE GetMaterialMode( );

Return Value

Returns a member of the D3DRMMATERIALMODE enumerated type that specifies the current material mode. By default, the mode is D3DRMMATERIAL_FROMMESH.

See Also

IDirect3DRMFrame3::SetMaterialMode

IDirect3DRMFrame3::GetMaterialOverride

IDirect3DRMFrame3

Retrieves the current per-attribute override settings for material attributes.

Syntax

HRESULT GetMaterialOverride(
  LPD3DRMMATERIALOVERRIDE lpdmOverride);

Parameters

lpdmOverride
Pointer to a D3DRMMATERIALOVERRIDE structure that describes the properties to be overridden.

Return Value

Returns one of the following values:
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DD_OK

Remarks

This method was introduced with DirectX version 6.0.

If a texture exists in the override, its reference count has been incremented (with AddRef) before being passed back, and you need to release the texture when you exit. Therefore, if you apply a texture override, remember to release it.

See Also

SetMaterialOverride

IDirect3DRMFrame3::GetOrientation

IDirect3DRMFrame3

Retrieves the orientation of a frame relative to the given reference frame.

Syntax

HRESULT GetOrientation(
  LPDIRECT3DRMFRAME lpRef,
  LPD3DVECTOR lprvDir,
  LPD3DVECTOR lprvUp
  );

Parameters

lpRef
Address of a variable that represents the Direct3DRMFrame object to be used as the reference.
lprvDir and lprvUp
Addresses of D3DVECTOR structures that will be filled with the normalized directions of the frame's z-axis and y-axis, respectively. The default orientation of a frame has a direction vector of [0, 0, 1] and an up vector of [0, 1, 0].

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

See Also

IDirect3DRMFrame3::SetOrientation

IDirect3DRMFrame3::GetParent

IDirect3DRMFrame3

Retrieves the parent frame of the current frame.

Syntax

HRESULT GetParent(
  LPDIRECT3DRMRAME3 * lplpParent
  );

Parameters

lplpParent
Address of a pointer that will be filled with the pointer to the Direct3DRMFrame object representing the frame's parent. If the current frame is the root, this pointer will be NULL when the method returns.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

IDirect3DRMFrame3::GetPosition

IDirect3DRMFrame3

Retrieves the position of a frame relative to the given reference frame, that is, it retrieves the distance of the frame from the reference. The distance is stored in the lprvPos parameter as a vector rather than as a linear measure.

Syntax

HRESULT GetPosition(
  LPDIRECT3DRMFRAME3 lpRef,
  LPD3DVECTOR lprvPos
  );

Parameters

lpRef
Address of a variable that represents the Direct3DRMFrame object to be used as the reference.
lprvPos
Address of a D3DVECTOR structure that will be filled with the frame's position.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

See Also

IDirect3DRMFrame3::SetPosition

IDirect3DRMFrame3::GetRotation

IDirect3DRMFrame3

Retrieves the rotation of the frame relative to the given reference frame.

Syntax

HRESULT GetRotation(
  LPDIRECT3DRMFRAME3 lpRef,
  LPD3DVECTOR lprvAxis,
  LPD3DVALUE lprvTheta
  );

Parameters

lpRef
Address of a variable that represents the Direct3DRMFrame object to be used as the reference.
lprvAxis
Address of a D3DVECTOR structure that will be filled with the frame's axis of rotation.
lprvTheta
Address of a variable that will be the frame's rotation, in radians.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

See Also

IDirect3DRMFrame3::SetRotation, Transformations

IDirect3DRMFrame3::GetScene

IDirect3DRMFrame3

Retrieves the root frame of the hierarchy containing the given frame.

Syntax

HRESULT GetScene(
  LPDIRECT3DRMFRAME3 lplpRoot
  );

Parameters

lplpRoot
Address of the pointer that will be filled with the pointer to the Direct3DRMFrame object representing the scene's root frame.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

IDirect3DRMFrame3::GetSceneBackground

IDirect3DRMFrame3

Retrieves the background color of a scene.

Syntax

D3DCOLOR GetSceneBackground( );

Return Value

Returns the color.

IDirect3DRMFrame3::GetSceneBackgroundDepth

IDirect3DRMFrame3

Retrieves the current background-depth buffer for the scene.

Syntax

HRESULT GetSceneBackgroundDepth(
  LPDIRECTDRAWSURFACE * lplpDDSurface
  );

Parameters

lplpDDSurface
Address of a pointer that will be initialized with the address of a DirectDraw surface representing the current background-depth buffer.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

See Also

IDirect3DRMFrame3::SetSceneBackgroundDepth

IDirect3DRMFrame3::GetSceneFogColor

IDirect3DRMFrame3

Retrieves the fog color of a scene.

Syntax

D3DCOLOR GetSceneFogColor( );

Return Value

Returns the fog color. By default, the color is white.

IDirect3DRMFrame3::GetSceneFogEnable

IDirect3DRMFrame3

Retrieves whether fog is currently enabled for this scene.

Syntax

BOOL GetSceneFogEnable( );

Return Value

Returns TRUE if fog is enabled, and FALSE otherwise. By default, this flag is FALSE.

IDirect3DRMFrame3::GetSceneFogMethod

IDirect3DRMFrame3

Retrieves the current fogging method.

Syntax

HRESULT GetSceneFogMethod(
  LPDWORD lpdwFlags);

Parameters

lpdwFlags
Pointer to a DWORD that receives the current fog method. Note that these flags are mutually exclusive. The currently defined flags are:
D3DRMFOGMETHOD_ANY
Indicates that Direct3DRM should choose an applicable method.
D3DRMFOGMETHOD_VERTEX
Use vertex fog.
D3DRMFOGMETHOD_TABLE
Use table fog.

Return Value

Returns one of the following values:
D3DRMERR_BADVALUE
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DD_OK

Remarks

The default behavior for Direct3DRMFrame objects created by the IDirect3DRM3 interface is D3DRMFOGMETHOD_ANY and the fog method will be chosen based on the capabilities of the device. If the device supports both vertex- and table-based fog then vertex fogging will be used. If the application requests table fog, but table fog is not available, vertex fog will be used. The default behavior for Direct3DRMFrame objects created with an IDirect3DRM or IDirect3DRM2 interface is D3DRMFOGMETHOD_VERTEX.

This method was introduced with DirectX version 6.0.

IDirect3DRMFrame3::GetSceneFogMode

IDirect3DRMFrame3

Retrieves the current fog mode for this scene.

Syntax

D3DRMFOGMODE GetSceneFogMode( );

Return Value

Returns a member of the D3DRMFOGMODE enumerated type that specifies the current fog mode.

IDirect3DRMFrame3::GetSceneFogParams

IDirect3DRMFrame3

Retrieves the current fog parameters for this scene.

Syntax

HRESULT GetSceneFogParams(
  D3DVALUE * lprvStart,
  D3DVALUE * lprvEnd,
  D3DVALUE * lprvDensity
  );

Parameters

lprvStart, lprvEnd, and lprvDensity
Addresses of variables that will be the fog start, end, and density values.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

IDirect3DRMFrame3::GetSortMode

IDirect3DRMFrame3

Retrieves the sorting mode used to process child frames.

Syntax

D3DRMSORTMODE GetSortMode( );

Return Value

Returns the member of the D3DRMSORTMODE enumerated type that specifies the sorting mode. The default value is D3DRMSORT_FROMPARENT.

See Also

IDirect3DRMFrame3::SetSortMode

IDirect3DRMFrame3::GetTexture

IDirect3DRMFrame3

Retrieves the texture of the given frame.

Syntax

HRESULT GetTexture(
  LPDIRECT3DRMTEXTURE3* lplpTexture
  );

Parameters

lplpTexture
Address of the pointer that will be filled with the address of the Direct3DRMTexture object representing the frame's texture. By default, the texture is NULL.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

See Also

IDirect3DRMFrame3::SetTexture

IDirect3DRMFrame3::GetTransform

IDirect3DRMFrame3

Retrieves the current-world transformation of the frame as a 4×4 affine matrix.

Syntax

HRESULT GetTransform(
  LPDIRECT3DRMFRAME lpRefFrame,
  D3DRMMATRIX4D rmMatrix);

Parameters

lpRefFrame
Frame that serves as the root of the scene for the purposes of this call. If this argument is NULL, the current root frame (as returned by GetScene) is used.
rmMatrix
D3DRMMATRIX4D array that receives the frame's transformation. Because this is an array, this value is an address.

Return Value

Returns one of the following values:
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DD_OK

Remarks

This method was introduced with DirectX version 6.0. This method extends IDirect3DRMFrame::GetTransform by adding the lpRefFrame parameter.

See Also

3-D Transformations

IDirect3DRMFrame3::GetTraversalOptions

IDirect3DRMFrame3

Retrieves the traversal status of the current frame.

Syntax

HRESULT GetTraversalOptions(
  LPDWORD lpdwFlags);

Parameters

lpdwFlags
Pointer to a DWORD that will be filled in with the current enable status. The currently defined flags are:
D3DRMFRAME_RENDERENABLE
Indicates render this frame or any children of this frame.
D3DRMFRAME_PICKENABLE
Indicates pick any visuals in this frame or any children of this frame.
By default, dwFlags is D3DRMFRAME_RENDERENABLE | D3DRMFRAME_PICKENABLE, and the frame is enabled for both rendering and picking.

Return Value

Returns one of the following values:
D3DRMERR_BADVALUE
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DD_OK

Remarks

This method was introduced with DirectX version 6.0.

IDirect3DRMFrame3::GetVelocity

IDirect3DRMFrame3

Retrieves the velocity of the frame relative to the given reference frame. Velocity is specified as units per tick. See IDirect3DRM3::Tick for more information.

Syntax

HRESULT GetVelocity(
  LPDIRECT3DRMFRAME3 lpRef,
  LPD3DVECTOR lprvVel,
  BOOL fRotVel
  );

Parameters

lpRef
Address of a variable that represents the Direct3DRMFrame object to be used as the reference.
lprvVel
Address of a D3DVECTOR structure that will be filled with the frame's velocity.
fRotVel
Flag specifying whether the rotational velocity of the object is taken into account when retrieving the linear velocity. If this parameter is TRUE, the object's rotational velocity is included in the calculation.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

See Also

IDirect3DRMFrame3::SetVelocity

IDirect3DRMFrame3::GetVisuals

IDirect3DRMFrame3

Retrieves a list of visuals in the frame.

Syntax

HRESULT GetVisuals(
  LPDWORD pdwNumVisuals, LPUNKNOWN *ppUnk
  );

Parameters

pdwNumVisuals
Pointer to a DWORD value containing the number of vectors expected to be returned. If ppUnk is NULL, GetVisuals returns the number of visuals contained by the frame. If ppUnk is not NULL, the DWORD value receives the number of visuals actually retrieved.
ppUnk
Pointer to a Direct3DRMVisualArray object containing the array of visuals that will be initialized. Setting this to NULL causes GetVisuals to return the number of visuals contained by the frame. Otherwise, this is a user-allocated array with space for pdwNumVisuals.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

IDirect3DRMFrame3::GetZbufferMode

IDirect3DRMFrame3

Retrieves the z-buffer mode; that is, whether z-buffering is enabled or disabled.

Syntax

D3DRMZBUFFERMODE GetZbufferMode( );

Return Value

Returns one of the members of the D3DRMZBUFFERMODE enumerated type. The default value is D3DRMZBUFFER_FROMPARENT.

See Also

IDirect3DRMFrame3::SetZbufferMode

IDirect3DRMFrame3::InverseTransform

IDirect3DRMFrame3

Transforms the vector in the lprvSrc parameter in world coordinates to model coordinates, and returns the result in the lprvDst parameter.

Syntax

HRESULT InverseTransform(
  D3DVECTOR *lprvDst,
  D3DVECTOR *lprvSrc
  );

Parameters

lprvDst
Address of a D3DVECTOR structure that will be filled with the result of the transformation.
lprvSrc
Address of a D3DVECTOR structure that is the source of the transformation.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

See Also

IDirect3DRMFrame3::Transform, 3-D Transformations

IDirect3DRMFrame3::InverseTransformVectors

IDirect3DRMFrame3

This transforms an array of vectors from world- to model-space.

Syntax

HRESULT InverseTransformVectors
(LPDIRECT3DRMFRAME3 lpRefFrame,
DWORD dwNumVectors,
LPD3DVECTOR	lpDstVectors,
LPD3DVECTOR	lpSrcVectors);

Parameters

lpRefFrame
Frame that is to be used as the root of the scene for the purposes of this call. If this argument is NULL, the current root frame (as would be returned by GetScene) will be used.
dwNumVectors
The number of vectors whose coordinates are to be transformed.
lpDstVectors
Destination of the transformation.
lpSrcVectors
Array of vectors to transform.

Return Value

Returns one of the following values:
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DD_OK

Remarks

This method was introduced with DirectX version 6.0.

IDirect3DRMFrame3::Load

IDirect3DRMFrame3

Loads a Direct3DRMFrame2 object.

Syntax

HRESULT Load(
  LPVOID lpvObjSource,
  LPVOID lpvObjID,
  D3DRMLOADOPTIONS d3drmLOFlags,
  D3DRMLOADTEXTURE3CALLBACK d3drmLoadTextureProc,
  LPVOID lpArgLTP
  );

Parameters

lpvObjSource
Source for the object to be loaded. This source can be a file, resource, memory block, or stream, depending on the source flags specified in the d3drmLOFlags parameter.
lpvObjID
Object name or position to be loaded. The use of this parameter depends on the identifier flags specified in the d3drmLOFlags parameter. If the D3DRMLOAD_BYPOSITION flag is specified, this parameter is a pointer to a DWORD value that gives the object's order in the file. This parameter can be NULL.
d3drmLOFlags
Value of the D3DRMLOADOPTIONS type describing the load options.
d3drmLoadTextureProc
D3DRMLOADTEXTURE3CALLBACK callback function used to load any textures used by the object that require special formatting. This parameter can be NULL.
lpArgLTP
Pointer to application-defined data passed to the D3DRMLOADTEXTURE3CALLBACK callback function.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

Remarks

By default, this method loads the first frame hierarchy in the file specified by the lpvObjSource parameter. The frame that uses this method is used as the parent of the new frame hierarchy. By default, perspective correction is on.

IDirect3DRMFrame3::LookAt

IDirect3DRMFrame3

Faces the frame toward the target frame, relative to the given reference frame, locking the rotation by the given constraints.

Syntax

HRESULT LookAt(
  LPDIRECT3DRMFRAME3 lpTarget,
  LPDIRECT3DRMFRAME3 lpRef,
  D3DRMFRAMECONSTRAINT rfcConstraint
  );

Parameters

lpTarget and lpRef
Addresses of variables that represent the Direct3DRMFrame objects to be used as the target and reference, respectively.
rfcConstraint
Member of the D3DRMFRAMECONSTRAINT enumerated type that specifies the axis of rotation to constrain.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

IDirect3DRMFrame3::Move

IDirect3DRMFrame3

Applies the linear and rotational velocities for all frames in the given hierarchy.

Syntax

HRESULT Move(
  D3DVALUE delta
  );

Parameters

delta
Amount to change the linear and rotational velocity. The change in each component is equal to the velocity of that component multiplied by delta. Although either or both of these velocities can be set relative to any frame, the system automatically converts them to velocities relative to the parent frame for the purpose of applying time deltas.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.


IDirect3DRMFrame3 Methods N to Z

This section contains the reference pages for the methods of the IDirect3DRMFrame3 interface that begin with the letters N through Z.

IDirect3DRMFrame3::RayPick

IDirect3DRMFrame3

Searches the hierarchy starting at this Direct3DRMFrame3 object and calculates the intersections between any visuals and the ray specified by the dvPosition and dvDirection parameters in the coordinate space specified by the lpRefFrame parameter.

Syntax

HRESULT RayPick(
  LPDIRECT3DRMFRAME3 lpRefFrame,
  LPD3DRMRAY ray,
  DWORD dwFlags,
  LPD3DRMPICKED2ARRAY* lplpPicked2Array
  );

Parameters

lpRefFrame
Address of the Direct3DRMFrame3 object that contains the ray.
ray
Pointer to a D3DRMRAY structure that contains two D3DVECTOR structures. The first D3DVECTOR structure is the vector direction of the ray. The second D3DVECTOR structure is the position of the origin of the ray.
dwFlags
Can be one of the following values:
D3DRMRAYPICK_ONLYBOUNDINGBOXES – Only intersections with bounding boxes of the visuals in the hierarchy are returned. Does not check for exact face intersections.
D3DRMRAYPICK_IGNOREFURTHERPRIMITIVES – Only the closest visual that intersects the ray is returned. Ignores visuals farther away than the closest one found so far in a search.
D3DRMRAYPICK_INTERPOLATEUV – Interpolate texture coordinates.
D3DRMRAYPICK_INTERPOLATECOLOR – Interpolate color.
D3DRMRAYPICK_INTERPOLATENORMAL – Interpolate normal.
lplpPicked2Array
The address of a pointer to be initialized with a valid pointer to the IDirect3DRMPicked2Array interface. You then use the IDirect3DRMPicked2Array::GetPick method to retrieve a visual object, an IDirect3DRMFrameArray interface, and a D3DRMPICKDESC2 structure. The array of frames is the path through the hierarchy leading to the visual object that intersected the ray. The D3DRMPICKDESC2 structure contains the face and group identifiers, pick position, horizontal and vertical texture coordinates for the vertex, vertex normal, and color of the intersected objects.

If you specify D3DRMRAYPICK_ONLYBOUNDINGBOXES, the texture, normal, and color data in the D3DRMPICKDESC2 structure will be invalid.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

Remarks

There are two kinds of flags: optimization flags and interpolation flags. Optimization flags allow you to limit the search and therefore make it faster. Interpolation flags specify what to interpolate if a primitive is hit. The three interpolation choices are color, normal, and texture coordinates.

The ray is specified in the reference frame coordinate space (pointed to by lpRefFrame). If the reference frame is NULL, the ray is specified in world coordinates.

IDirect3DRMFrame3::Save

IDirect3DRMFrame3

Saves a Direct3DRMFrame3 object to the specified file.

Syntax

HRESULT Save(
  LPCSTR lpFilename,
  D3DRMXOFFORMAT d3dFormat,
  D3DRMSAVEOPTIONS d3dSaveFlags
  );

Parameters

lpFilename
Address specifying the name of the created file. This file must have a .x file name extension.
d3dFormat
D3DRMXOF_TEXT value from the D3DRMXOFFORMAT enumerated type.
d3dSaveFlags
Value of the D3DRMSAVEOPTIONS type describing the save options.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

IDirect3DRMFrame3::SetAxes

IDirect3DRMFrame3

Sets the vectors that define a coordinate space by which the IDirect3DRMFrame3::SetOrientation vectors are transformed.

Syntax

HRESULT SetAxes(
  D3DVALUE dx,
  D3DVALUE dy,
  D3DVALUE dz,
  D3DVALUE ux,
  D3DVALUE uy,
  D3DVALUE uz
  );

Parameters

dx, dy, dz
The z-axis for the frame. Default is (0,0,1).
ux, uy, uz
The y-axis for the frame. Default is (0,1,0).

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

Remarks

This method helps support both left-handed and right-handed coordinate systems. This method also allows you to specify that the negative z-axis represents the front of the object.

The IDirect3DRMFrame3::SetOrientation direction (rvDx, rvDy, rvDz) and up (rvUx, rvUy, rvUz) vectors are transformed according to the value of the SetAxes vectors.

The axes are inherited by child frames as specified in IDirect3DRMFrame3::SetInheritAxes.

See Also

IDirect3DRMFrame3::GetAxes, IDirect3DRMFrame3::GetInheritAxes, IDirect3DRMFrame3::SetInheritAxes

IDirect3DRMFrame3::SetBox

IDirect3DRMFrame3

Sets the box to be used in bounding-box testing. In order for the bounding box to be valid, its minimum x must be less than or equal to its maximum x, minimum y must be less than or equal to its maximum y, and minimum z must be less than or equal to its maximum z.

Syntax

HRESULT SetBox(
  D3DRMBOX * lpD3DRMBox
  );

Parameters

lpD3DRMBox
Address of a D3DRMBOX structure that contains the bounding-box coordinates.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

Remarks

This method supports a bounding box on a frame for hierarchical culling. For a bounding box to be enabled, the IDirect3DRMFrame3::SetBoxEnable method must be used to set the enable flag to TRUE. By default, the box-enable flag is FALSE.

See Also

IDirect3DRMFrame3::GetBox, IDirect3DRMFrame3::SetBoxEnable, IDirect3DRMFrame3::GetBoxEnable

IDirect3DRMFrame3::SetBoxEnable

IDirect3DRMFrame3

Enables or disables bounding-box testing for this Direct3DRMFrame3 object. Bounding-box testing cannot be enabled unless a valid bounding box has already been set on the frame.

Syntax

HRESULT SetBoxEnable(
  BOOL bEnableFlag
  );

Parameters

bEnableFlag
Flag specifying whether bounding boxes are enabled or not. TRUE to enable a bounding box. FALSE if a bounding box is not enabled. Default is FALSE.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

Remarks

For a bounding box to be enabled, this method must be used to set the enable flag to TRUE. By default, the box-enable flag is FALSE.

Bounding-box testing is performed as follows: At render time, the bounding box is transformed into model space and checked for intersection with the viewing frustum. If the entire box is outside of the viewing frustum, none of the visuals in the frame, or in any child frame, are rendered. Otherwise, rendering continues as normal.

Enabling bounding-box testing with a box of {0,0,0,0} completely prevents a frame from being rendered.

See Also

IDirect3DRMFrame3::GetBoxEnable, IDirect3DRMFrame3::GetBox, IDirect3DRMFrame3::SetBox

IDirect3DRMFrame3::SetColor

IDirect3DRMFrame3

Sets the color of the frame. This color is used for meshes in the frame when the D3DRMMATERIALMODE enumerated type is D3DRMMATERIAL_FROMFRAME.

Syntax

HRESULT SetColor(
  D3DCOLOR rcColor
  );

Parameters

rcColor
New color for the frame. Be sure to set the alpha component as well as the red, green, and blue color components or your objects might not be visible. The RGBA_MAKE DirectX macro allows you to specify these values.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

Remarks

This method is also used to add a color key to a DIRECT3DRMFRAMEINTERPOLATOR object. By default, the color is white.

See Also

IDirect3DRMFrame3::GetColor, IDirect3DRMFrame3::SetMaterialMode

IDirect3DRMFrame3::SetColorRGB

IDirect3DRMFrame3

Sets the color of the frame. This color is used for meshes in the frame when the D3DRMMATERIALMODE enumerated type is D3DRMMATERIAL_FROMFRAME.

Syntax

HRESULT SetColorRGB(
  D3DVALUE rvRed,
  D3DVALUE rvGreen,
  D3DVALUE rvBlue
  );

Parameters

rvRed, rvGreen, and rvBlue
New color for the frame. Each component of the color should be in the range 0.0 to 1.0.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

Remarks

This method is also used to add an RGB color key to a DIRECT3DRMFRAMEINTERPOLATOR object.

See Also

IDirect3DRMFrame3::SetMaterialMode

IDirect3DRMFrame3::SetInheritAxes

IDirect3DRMFrame3

Specifies whether the axes for the frame are inherited from the parent frame.

Syntax

HRESULT SetInheritAxes(
  BOOL inherit_from_parent
  );

Parameters

inherit_from_parent
Flag indicating whether the frame should inherit axes from its parent. If TRUE, the frame inherits axes (the default). If FALSE, the frame does not inherit axes.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

Remarks

By default, the axes are inherited from the parent. If a frame is set to inherit from the parent, and there is no parent, the frame acts as if it inherits from a parent with the default axes (direction=(0,0,1) and up=(0,1,0)). This method allows a single policy for axes to be set at the root of the hierarchy.

See Also

IDirect3DRMFrame3::GetInheritAxes, IDirect3DRMFrame3::GetAxes, IDirect3DRMFrame3::SetAxes

IDirect3DRMFrame3::SetMaterial

IDirect3DRMFrame3

Sets the material of the Direct3DRMFrame2 object.

Syntax

HRESULT SetMaterial(
  LPDIRECT3DRMMATERIAL2 *lplpMaterial
  );

Parameters

lplpMaterial
Address of the Direct3DRMMaterial object that will be applied to the frame.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

See Also

IDirect3DRMFrame3::GetMaterial

IDirect3DRMFrame3::SetMaterialMode

IDirect3DRMFrame3

Sets the material mode for a frame. The material mode determines the source of material information for visuals rendered with the frame.

Syntax

HRESULT SetMaterialMode(
  D3DRMMATERIALMODE rmmMode
  );

Parameters

rmmMode
One of the members of the D3DRMMATERIALMODE enumerated type. By default, the mode is D3DRMMATERIAL_FROMMESH.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

See Also

IDirect3DRMFrame3::GetMaterialMode

IDirect3DRMFrame3::SetMaterialOverride

IDirect3DRMFrame3

Enables you to set specific material attributes. For example, this method enables you to override only the emissive property of materials.

Syntax

HRESULT SetMaterialOverride(
  LPD3DRMMATERIALOVERRIDE lpdmOverride);

Parameters

lpdmOverride
Pointer to a D3DRMMATERIALOVERRIDE structure that describes the properties to be overridden.

Return Value

Returns one of the following values:
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DD_OK

Remarks

The override always overrides everything down the hierarchy. If you override the emissive property in one frame, any attempts to override the same property farther down the hierarchy will be ignored. This override also takes precedence over standard frame overrides, as well as material properties on specific meshes. Overrides such as SetMaterial and SetTexture have no effect on the behavior of this method.

This method was introduced with DirectX version 6.0.

See Also

GetMaterialOverride

IDirect3DRMFrame3::SetOrientation

IDirect3DRMFrame3

Aligns a frame so that its z-direction points along the direction vector [rvDx, rvDy, rvDz] and its y-direction aligns with the vector [rvUx, rvUy, rvUz].

Syntax

HRESULT SetOrientation(
  LPDIRECT3DRMFRAME3 lpRef,
  D3DVALUE rvDx,
  D3DVALUE rvDy,
  D3DVALUE rvDz,
  D3DVALUE rvUx,
  D3DVALUE rvUy,
  D3DVALUE rvUz
  );

Parameters

lpRef
Address of a variable that represents the Direct3DRMFrame object to be used as the reference.
rvDx, rvDy, and rvDz
New z-axis for the frame. Each component of the vector should be in the range -1.0 to 1.0.
rvUx, rvUy, and rvUz
New y-axis for the frame. Each component of the vector should be in the range -1.0 to 1.0.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

Remarks

The default orientation of a frame has a direction vector of [0, 0, 1] and an up vector of [0, 1, 0].

If [rvUx, rvUy, rvUz] is parallel to [rvDx, rvDy, rvDz], the D3DRMERR_BADVALUE error value is returned; otherwise, the [rvUx, rvUy, rvUz] vector passed is projected onto the plane that is perpendicular to [rvDx, rvDy, rvDz].

This method is also used to add an orientation key to a Direct3DRMFrameInterpolator object.

Prior to DirectX version 6.0, SetOrientation did not respect scale and shear. This was fixed in DirectX version 6.0.

The following code fragment calls SetOrientation to set the default orientation. It assumes the camera and scene frames have already been created using the IDirect3DRM3::CreateFrame method.

LPDIRECT3DRMFRAME3 camera;
LPDIRECT3DRMFRAME3 scene;

if (FAILED(camera->SetOrientation(scene, D3DVAL(0), D3DVAL(0), D3DVAL(1),
                                  D3DVAL(0), D3DVAL(1), D3DVAL(0)))
{
    // error
}

See Also

IDirect3DRMFrame3::GetOrientation

IDirect3DRMFrame3::SetPosition

IDirect3DRMFrame3

Sets the position of a frame relative to the frame of reference. It places the frame a distance of [rvX, rvY, rvZ] from the reference. When a child frame is created within a parent, it is placed at [0, 0, 0] in the parent frame.

Syntax

HRESULT SetPosition(
  LPDIRECT3DRMFRAME3 lpRef,
  D3DVALUE rvX,
  D3DVALUE rvY,
  D3DVALUE rvZ
  );

Parameters

lpRef
Address of a variable that represents the Direct3DRMFrame object to be used as the reference.
rvX, rvY, and rvZ
New position for the frame. Position has no units. Use the viewing frustrum to choose reasonable numbers. For more information, see Viewports.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

Remarks

This method is also used to add a position key to a Direct3DRMFrameInterpolator object.

The following code fragment calls SetPosition. It assumes the camera and scene frames have already been created using the IDirect3DRM3::CreateFrame method.

LPDIRECT3DRMFRAME3 camera;
LPDIRECT3DRMFRAME3 scene;

if (FAILED(camera->SetPosition(scene, D3DVAL(0), D3DVAL(0), -D3DVAL(10)))
{
    // error
}

See Also

IDirect3DRMFrame3::GetPosition

IDirect3DRMFrame3::SetQuaternion

IDirect3DRMFrame3

Sets a frame's orientation relative to a reference frame using a unit quaternion.

Syntax

HRESULT SetQuaternion(
  LPDIRECT3DRMFRAME3 lpRef,
  D3DRMQUATERNION *quat
  )

Parameters

lpRef
Address of a variable that represents the Direct3DRMFrame2 object to be used as the reference.
quat
A D3DRMQUATERNION structure that holds the unit quaternion.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

Remarks

A quaternion is a four-valued vector that can be used to represent any rotation and that has properties that are useful when interpolating between orientations. A quaternion is a unit quaternion if s**2 + x**2 + y**2 + z**2 = 1.

The function D3DRMQuaternionFromRotation can be used to generate unit quaternions from arbitrary rotation values.

The SetQuaternion method is supported by FrameInterpolators. See Interpolators for more information about interpolators.

IDirect3DRMFrame3::SetRotation

IDirect3DRMFrame3

Sets a frame rotating by the given angle around the given vector at each call to the IDirect3DRM3::Tick or IDirect3DRMFrame3::Move method. The direction vector [rvX, rvY, rvZ] is defined in the reference frame.

Syntax

HRESULT SetRotation(
  LPDIRECT3DRMFRAME3 lpRef,
  D3DVALUE rvX,
  D3DVALUE rvY,
  D3DVALUE rvZ,
  D3DVALUE rvTheta
  );

Parameters

lpRef
Address of a variable that represents the Direct3DRMFrame object to be used as the reference.
rvX, rvY, and rvZ
Vector about which rotation occurs. Valid values are in the range -1.0 to 1.0.
rvTheta
Rotation angle, in radians. The larger the angle, the faster an object rotates. The IDirect3DRMFrame3::Move and IDirect3DRM3::Tick methods scale this value.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

Remarks

The specified rotation changes the matrix with every render tick, unlike the IDirect3DRMFrame3::AddRotation method, which changes the objects in the frame only once.

The following code fragment calls SetRotation. It assumes the child and scene frames have already been created using the IDirect3DRM3::CreateFrame method.

LPDIRECT3DRMFRAME3 child;
LPDIRECT3DRMFRAME3 scene;

if (FAILED(child->SetRotation(scene, D3DVAL(0), D3DVAL(1), D3DVAL(1), D3DVAL(0.02)))
{
    // error
}

See Also

IDirect3DRMFrame3::AddRotation, IDirect3DRMFrame3::GetRotation

IDirect3DRMFrame3::SetSceneBackground

IDirect3DRMFrame3

Sets the background color of a scene.

Syntax

HRESULT SetSceneBackground(
  D3DCOLOR rcColor
  );

Parameters

rcColor
New color for the background.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

Remarks

This method is also used to add a background color key to a Direct3DRMFrameInterpolator object.

IDirect3DRMFrame3::SetSceneBackgroundDepth

IDirect3DRMFrame3

Specifies a background-depth buffer for a scene.

Syntax

HRESULT SetSceneBackgroundDepth(
  LPDIRECTDRAWSURFACE lpImage
  );

Parameters

lpImage
Address of a DirectDraw surface that will store the new background depth for the scene.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

Remarks

The image must have a depth of 16 bits per pixel. If the image and viewport sizes are different, the image is scaled first. For best performance when animating the background-depth buffer, the image should be the same size as the viewport. This enables the depth buffer to be updated directly from the image memory without incurring extra overhead.

See Also

IDirect3DRMFrame3::GetSceneBackgroundDepth

IDirect3DRMFrame3::SetSceneBackgroundImage

IDirect3DRMFrame3

This method is obsolete and should not be used. It does not have the same behavior it did in DirectX version 5 because of changes in rasterizers. Rather than use this method you should do a blit (bit block transfer) to the screen for your background.

Syntax

HRESULT SetSceneBackgroundImage(
  LPDIRECT3DRMTEXTURE3 lpTexture
  );

Parameters

lpTexture
Address of a Direct3DRMTexture object that will contain the new background scene.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

Remarks

This method is obsolete. It does not have the same behavior it did in DirectX version 5.

IDirect3DRMFrame3::SetSceneBackgroundRGB

IDirect3DRMFrame3

Sets the background color of a scene.

Syntax

HRESULT SetSceneBackgroundRGB(
  D3DVALUE rvRed,
  D3DVALUE rvGreen,
  D3DVALUE rvBlue
  );

Parameters

rvRed, rvGreen, and rvBlue
New color for the background. Each component of the color should be in the range 0.0 to 1.0.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

Remarks

This method is also used to add a background RGB color key to a Direct3DRMFrameInterpolator object.

IDirect3DRMFrame3::SetSceneFogColor

IDirect3DRMFrame3

Sets the fog color of a scene.

Syntax

HRESULT SetSceneFogColor(
  D3DCOLOR rcColor
  );

Parameters

rcColor
New color for the fog.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

Remarks

This method is also used to add a fog color key to a Direct3DRMRFrameInterpolator object. By default, the color is white.

IDirect3DRMFrame3::SetSceneFogEnable

IDirect3DRMFrame3

Sets the fog-enable state.

Syntax

HRESULT SetSceneFogEnable(
  BOOL bEnable
  );

Parameters

bEnable
New fog-enable state.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

Remarks

By default, fog is not enabled.

IDirect3DRMFrame3::SetSceneFogMethod

IDirect3DRMFrame3

Specifies whether fogging is to be performed via vertex fog or table fog.

Syntax

HRESULT SetSceneFogMethod(
  DWORD dwFlags);

Parameters

dwFlags
The currently defined flags are:
D3DRMFOGMETHOD_ANY
Indicates that Direct3DRM should choose an applicable method.
D3DRMFOGMETHOD_VERTEX
Use vertex fog.
D3DRMFOGMETHOD_TABLE
Use table fog.

Return Value

Returns one of the following values:
D3DRMERR_BADVALUE
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DD_OK

Remarks

The default behavior for Direct3DRMFrame objects created by the IDirect3DRM3 interface is D3DRMFOGMETHOD_ANY and the fog method will be chosen based on the capabilities of the device. If the device supports both vertex- and table-based fog then vertex fogging will be used. If the application requests table fog, but table fog is not available, vertex fog will be used. The default behavior for Direct3DRMFrame objects created with an IDirect3DRM or IDirect3DRM2 interface is D3DRMFOGMETHOD_VERTEX.

Remarks

This method was introduced with DirectX version 6.0.

IDirect3DRMFrame3::SetSceneFogMode

IDirect3DRMFrame3

Sets the fog mode.

Syntax

HRESULT SetSceneFogMode(
  D3DRMFOGMODE rfMode
  );

Parameters

rfMode
One of the members of the D3DRMFOGMODE enumerated type, specifying the new fog mode.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

See Also

IDirect3DRMFrame3::SetSceneFogParams

IDirect3DRMFrame3::SetSceneFogParams

IDirect3DRMFrame3

Sets the current fog parameters for this scene.

Syntax

HRESULT SetSceneFogParams(
  D3DVALUE rvStart,
  D3DVALUE rvEnd,
  D3DVALUE rvDensity
  );

Parameters

rvStart and rvEnd
Fog start and end points for linear fog mode. These settings determine the distance from the camera at which fog effects first become visible, and the distance at which fog reaches its maximum density.
rvDensity
Fog density for the exponential fog modes. This value should be in the range 0 through 1.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

Remarks

This method is also used to add a fog parameters key to a Direct3DRMRFrameInterpolator object.

See Also

D3DRMFOGMODE, IDirect3DRMFrame3::SetSceneFogMode

IDirect3DRMFrame3::SetSortMode

IDirect3DRMFrame3

Sets the sorting mode used to process child frames. You can use this method to change the properties of hidden-surface-removal algorithms.

Syntax

HRESULT SetSortMode(
  D3DRMSORTMODE d3drmSM
  );

Parameters

d3drmSM
One of the members of the D3DRMSORTMODE enumerated type, specifying the sorting mode. The default value is D3DRMSORT_FROMPARENT.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

See Also

IDirect3DRMFrame3::GetSortMode

IDirect3DRMFrame3::SetTexture

IDirect3DRMFrame3

Sets the texture of the frame.

Syntax

HRESULT SetTexture(
  LPDIRECT3DRMTEXTURE3 lpD3DRMTexture
  );

Parameters

lpD3DRMTexture
Address of a variable that represents the Direct3DRMTexture object to be used.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

Remarks

The texture is used for meshes in the frame when the D3DRMMATERIALMODE enumerated type is D3DRMMATERIAL_FROMFRAME. To disable the frame's texture, use a NULL texture.

See Also

IDirect3DRMFrame3::GetTexture, IDirect3DRMFrame3::SetMaterialMode

IDirect3DRMFrame3::SetTraversalOptions

IDirect3DRMFrame3

Specifies whether this frame is traversed during rendering and picking. In other words, using this API without a value of D3DRMFRAME_RENDERENABLE effectively switches the frame off for rendering. By default, the frame is enabled for rendering and picking.

Syntax

HRESULT SetTraversalOptions
(DWORD dwFlags);

Parameters

dwFlags
The currently defined flags are:
D3DRMFRAME_RENDERENABLE
Indicates render this frame or any children of this frame.
D3DRMFRAME_PICKENABLE
Indicates pick any visuals in this frame or any children of this frame.

Return Value

Returns one of the following values:
D3DRMERR_BADVALUE
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DD_OK

Remarks

This method was introduced with DirectX version 6.0.

IDirect3DRMFrame3::SetVelocity

IDirect3DRMFrame3

Sets the velocity of the given frame relative to the reference frame. The frame will be moved by the vector [rvX, rvY, rvZ] with respect to the reference frame at each successive call to the IDirect3DRM3::Tick or IDirect3DRMFrame3::Move method.

Syntax

HRESULT SetVelocity(
  LPDIRECT3DRMFRAME3 lpRef,
  D3DVALUE rvX,
  D3DVALUE rvY,
  D3DVALUE rvZ,
  BOOL fRotVel
  );

Parameters

lpRef
Address of a variable that represents the Direct3DRMFrame object to be used as the reference.
rvX, rvY, and rvZ
New velocity for the frame. Rotational velocity has no units and can be any value. The IDirect3DRMFrame3::Move and IDirect3DRM3::Tick methods scale this value.
fRotVel
Flag specifying whether the rotational velocity of the object is taken into account when setting the linear velocity. If TRUE, the object's rotational velocity is included in the calculation.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

See Also

IDirect3DRMFrame3::GetVelocity

IDirect3DRMFrame3::SetZbufferMode

IDirect3DRMFrame3

Sets the z-buffer mode; that is, whether z-buffering is enabled or disabled.

Syntax

HRESULT SetZbufferMode(
  D3DRMZBUFFERMODE d3drmZBM
  );

Parameters

d3drmZBM
One of the members of the D3DRMZBUFFERMODE enumerated type, specifying the z-buffer mode. The default value is D3DRMZBUFFER_FROMPARENT.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

See Also

IDirect3DRMFrame3::GetZbufferMode

IDirect3DRMFrame3::Transform

IDirect3DRMFrame3

Transforms the vector in the lpd3dVSrc parameter in model coordinates to world coordinates, returning the result in the lpd3dVDst parameter.

Syntax

HRESULT Transform(
  D3DVECTOR *lpd3dVDst,
  D3DVECTOR *lpd3dVSrc
  );

Parameters

lpd3dVDst
Address of a D3DVECTOR structure that will be filled with the result of the transformation operation.
lpd3dVSrc
Address of a D3DVECTOR structure that is the source of the transformation operation.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

See Also

IDirect3DRMFrame3::InverseTransform, 3-D Transformations

IDirect3DRMFrame3::TransformVectors

IDirect3DRMFrame3

Transforms an array of vectors from model- to world-space.

Syntax

HRESULT TransformVectors(
  LPDIRECT3DRMFRAME3 lpRefFrame,
  DWORD dwNumVectors,
  LPD3DVECTOR lpDstVectors,
  LPD3DVECTOR lpSrcVectors);

Parameters

lpRefFrame
Frame that is to be used as the root of the scene for the purposes of this call. If this argument is NULL, the current root frame (as would be returned by GetScene) will be used.
dwNumVectors
The number of vectors to be transformed.
lpDstVectors
Destination of the transformation.
lpSrcVectors
Array of vectors to transform.

Return Value

Returns one of the following values:
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DD_OK

Remarks

This method was introduced with DirectX version 6.0.


IDirect3DRMMeshBuilder3

IDirect3DRMMeshBuilder3 Methods A to M

This section contains the reference pages for the methods of the IDirect3DRMMeshBuilder3 interface that begin with the letters A through M.

IDirect3DRMMeshBuilder3::AddFace

IDirect3DRMMeshBuilder3

Adds a face to a Direct3DRMMeshBuilder3 object.

Syntax

HRESULT AddFace(
  LPDirect3DRMFace2 lpD3DRMFace
  );

Parameters

lpD3DRMFace
Pointer to the address of the face being added.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

Remarks

Any one face can exist in only one mesh at a time.

IDirect3DRMMeshBuilder3::AddFaces

IDirect3DRMMeshBuilder3

Adds faces to a Direct3DRMMeshBuilder3 object.

Syntax

HRESULT AddFaces(
  DWORD dwVertexCount,
  D3DVECTOR * lpD3DVertices,
  DWORD normalCount,
  D3DVECTOR *lpNormals,
  DWORD *lpFaceData,
  LPDirect3DRMFaceArray* lplpD3DRMFaceArray
  );

Parameters

dwVertexCount
Number of vertices.
lpD3DVertices
Base address of an array of D3DVECTOR structures that store the vertex positions.
normalCount
Number of normals.
lpNormals
Base address of an array of D3DVECTOR structures that store the normal positions.
lpFaceData
For each face, this parameter should contain a vertex count followed by the indexes into the vertices array. If normalCount is not zero, this parameter should contain a vertex count followed by pairs of indexes, with the first index of each pair indexing into the array of vertices, and the second indexing into the array of normals. The list of indexes must terminate with a zero.
lplpD3DRMFaceArray
Address of a pointer to an IDirect3DRMFaceArray interface that will be filled with a pointer to the newly created faces.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

IDirect3DRMMeshBuilder3::AddFacesIndexed

IDirect3DRMMeshBuilder3

Enables a number of faces to be created on the meshbuilder that use pre-existing vertices and normals (optional).

Syntax

IDirect3DRMMeshBuilder3::AddFacesIndexed(
  DWORD dwFlags,
  DWORD *lpdwvIndices,
  DWORD *lpdwIndexFirst,
  DWORD *lpdwCount);

Parameters

dwFlags
Flag value that specifies how normal indexes should be handled. Must be either 0 or D3DRMADDFACES_VERTICESONLY. If the value is 0, indexes of pre-existing normals must be specified in the lpdwvIndices parameter. Otherwise, the normal with the corresponding index will be used automatically for each vertex.
lpdwvIndices
Pointer to a contiguous array of unsigned integer tuples that specify the following for each face.
  • Number of vertices n, where n is greater than or equal to 3
  • Vertex indexes
  • Normal indexes (optional)

The following table shows the relationship between the value for the dwFlags parameter and the required face tuple format for the lpdwvIndices parameter.
dwFlags | Required face tuple format
0 | {<n>, <vIndex0>, <nIndex0>,...,<vIndexn-1>, <nIndexn-1>}
D3DRMADDFACES_VERTICESONLY | {<n>, <vIndex0>,...,<vIndexn-1>}

The vIndex and nIndex values are required to index into previously existing vertices and normals within the meshbuilder. The array of tuples should be terminated with the value 0.

lpdwIndexFirst
Optional pointer to a DWORD that, if supplied, is filled with the index of the first new face added to the meshbuilder. Subsequent faces have contiguous indexes. Faces are added in the order in which they are specified in the lpdwvIndices parameter.
lpdwCount
Optional pointer to a DWORD that, if supplied, is filled with the number of faces added to the meshbuilder.

Return Value

Returns one of the following values:
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DD_OK

Remarks

This method was introduced with DirectX version 6.0.

IDirect3DRMMeshBuilder3::AddFrame

IDirect3DRMMeshBuilder3

Adds the contents of a frame to a Direct3DRMMeshBuilder3 object.

Syntax

HRESULT AddFrame(
  LPDIRECT3DRMFRAME3 lpD3DRMFrame
  );

Parameters

lpD3DRMFrame
Pointer to the address of the frame whose contents are being added.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

Remarks

This method adds a copy of all the mesh and meshbuilder faces from the specified frame hierarchy (which may be a sub-branch of a larger frame hierarchy) to the Direct3DRMMeshBuilder3 object. The frame tree is specified by passing the root frame. Faces are added with the position and orientation of their containing frame factored in. Transforms of the specified root frame are ignored, even if the root frame has a parent.

The source frame is not modified or referenced by this operation.

IDirect3DRMMeshBuilder3::AddMesh

IDirect3DRMMeshBuilder3

Adds a mesh to a Direct3DRMMeshBuilder3 object.

Syntax

HRESULT AddMesh(
  LPDIRECT3DRMMESH lpD3DRMMesh
  );

Parameters

lpD3DRMMesh
Pointer to the address of the mesh being added.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

IDirect3DRMMeshBuilder3::AddMeshBuilder

IDirect3DRMMeshBuilder3

Adds the contents of a Direct3DRMMeshBuilder3 object to a Direct3DRMMeshBuilder3 object. All sub-meshbuilders underneath the source Direct3DRMMeshBuilder3 object and the faces they contain are duplicated beneath the target Direct3DRMMeshBuilder3 object.

Syntax

HRESULT
AddMeshBuilder(
  LPDIRECT3DRMMESHBUILDER3 lpD3DRMMeshBuild
  DWORD dwFlags);
  );

Parameters

lpD3DRMMeshBuild
Pointer to the Direct3DRMMeshBuilder3 object whose contents are being added.
dwFlags

One of the following defined flags:

D3DRMADDMESHBUILDER_FLATTENSUBMESHES
Causes the submesh objects to not be duplicated. Their faces are still copied, but only to the top-level of the destination meshbuilder.
D3DRMADDMESHBUILDER_NOSUBMESHES
Causes sub-meshbuilders to be ignored.
D3DRMADDMESHBUILDER_DONTCOPYAPPDATA
By default, AddMeshBuilder3 copies the application data of source meshbuilders to the destination. Specifiying D3DRMADDMESHBUILDER_DONTCOPYAPPDATA prevents this from occurring.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

Remarks

The source Direct3DRMMeshBuilder3 object is not modified or referenced by this operation.

IDirect3DRMMeshBuilder3::AddNormal

IDirect3DRMMeshBuilder3

Adds a normal to a Direct3DRMMeshBuilder3 object.

Syntax

int AddNormal(
  D3DVALUE x,
  D3DVALUE y,
  D3DVALUE z
  );

Parameters

x, y, and z
The x-, y-, and z-components of the direction of the new normal.

Return Value

Returns the index of the normal.

IDirect3DRMMeshBuilder3::AddTriangles

IDirect3DRMMeshBuilder3

Enables the application to add new triangles (as opposed to general polygons) to the IDirect3DRMMeshBuilder3 object, and in the process, to implicitly create new faces. This method provides flexiblility to the application in describing the triangles. The triangles are described by a set of vertices. Each vertex must have a position, but may optionally have none or any of the following: normal, texture coordinates, or color. The vertex also has a type that describes whether this new vertex describes a list, strip, or fan. A flag also indicates whether this triangle is to be added to the face of the previous triangle, or whether a new face is to be created.

Syntax

HRESULT AddTriangles(
  DWORD dwFlags,
  DWORD dwFormat,
  DWORD dwVertexCount,
  LPVOID lpData);

Parameters

dwFlags
Must be zero.
dwFormat
Logical combination of values describing the format of the vertex data. If all valid values are included, the vertex data is described by the following Element structure.
struct Element
{
    DWORD     dwType;
    D3DVECTOR dvPosition;
    D3DVECTOR dvNormal;
    D3DCOLOR  dcColor;
    D3DVALUE  tu;
    D3DVALUE  tv;
};

Valid values include a logical combination of any of the following values, which indicate which members of the Element structure to include in the description for each element. The dvPosition member is always present.

D3DRMFVF_TYPE
Include the dwType structure member. If the dwType structure member is present, it must include one of the following:
D3DRMVERTEX_LIST
Starts a new list or is a member of a previously started list. If the previous vertex (or the vertex previous to that) was not marked with this flag, the following vertices must be marked with this flag until at least one triangle is formed.
D3DRMVERTEX_STRIP
Forms a new triangle in strip format with the previous two vertices.
D3DRMVERTEX_FAN
Forms a new triangle with the previous vertex and the first vertex in the fan.
D3DRMFVF_NORMAL
Include the dvNormal structure member.
D3DRMFVF_COLOR
Include the dcColor structure member.
D3DRMFVF_TEXTURECOORDS
Include the tu and tv structure members.
dwVertexCount
Vertex number.
lpvData
Pointer to the data described by dwFormat.

Return Value

Returns one of the following values:
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DD_OK

Remarks

This method was introduced with DirectX version 6.0.

The following example shows the appropriate dwType flag for each vertex in the diagram.
Vertex Number | dwType Flag
0 | D3DRMVERTEX_STRIP
1 | D3DRMVERTEX_STRIP
2 | D3DRMVERTEX_STRIP
3 | D3DRMVERTEX_STRIP
4 | D3DRMVERTEX_STRIP
5 | D3DRMVERTEX_FAN
6 | D3DRMVERTEX_FAN
7 | D3DRMVERTEX_FAN
8 | D3DRMVERTEX_FAN
9 | D3DRMVERTEX_LIST
10 | D3DRMVERTEX_LIST
11 | D3DRMVERTEX_LIST
12 | D3DRMVERTEX_LIST
13 | D3DRMVERTEX_LIST
14 | D3DRMVERTEX_LIST

IDirect3DRMMeshBuilder3::AddVertex

IDirect3DRMMeshBuilder3

Adds a vertex to a Direct3DRMMeshBuilder3 object.

Syntax

int AddVertex(
  D3DVALUE x,
  D3DVALUE y,
  D3DVALUE z
  );

Parameters

x, y, and z
X-, y-, and z-components of the position of the new vertex.

Return Value

Returns the index of the vertex.

IDirect3DRMMeshBuilder3::CreateFace

IDirect3DRMMeshBuilder3

Creates a new face with no vertices and adds it to a Direct3DRMMeshBuilder3 object.

Syntax

HRESULT CreateFace(
  LPDirect3DRMFace2* lplpD3DRMFace2
  );

Parameters

lplpD3DRMFace2
Address of a pointer to an IDirect3DRMFace2 interface that will be filled with a pointer to the face that was created.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

IDirect3DRMMeshBuilder3::CreateMesh

IDirect3DRMMeshBuilder3

Creates a new mesh from a Direct3DRMMeshBuilder3 object.

Syntax

HRESULT CreateMesh(
  LPDIRECT3DRMMESH* lplpD3DRMMesh
  );

Parameters

lplpD3DRMMesh
Address that will be filled with a pointer to an IDirect3DRMMesh interface.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

IDirect3DRMMeshBuilder3::CreateSubMesh

IDirect3DRMMeshBuilder3

Creates a new submesh for the current Direct3DRMMeshBuilder3 object. A submesh is similar to a meshbuilder object in that it supports the IDirect3DRMMeshBuilder3 interface, and can itself have submeshes. The difference between submeshes and meshbuilders is that all submeshes share the vertices and normals with the greatest ancestor in the chain of submeshes. Meshbuilders do not share vertices and normals.

Syntax

HRESULT CreateSubMesh(
  LPUNKNOWN * lplpUnk);

Parameters

lplpUnk
Address to receive a pointer to the IUnknown interface of the new submesh. You can use QueryInterface on the IUnknown interface to query for IDirect3DRMMeshBuilder3 support.

Return Value

Returns one of the following values:
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DD_OK

Remarks

This method was introduced with DirectX version 6.0.

See Also

DeleteSubMesh, GetSubMeshes, GetParentMesh

IDirect3DRMMeshBuilder3::DeleteFace

IDirect3DRMMeshBuilder3

Deletes a face from the IDirect3DRMMeshBuilder3 object.

Syntax

HRESULT DeleteFace
(LPDirect3DRMFace2 lpFace);

Parameters

lpFace
Pointer to the interface of a Direct3DRMFace2 object to remove from the Direct3DRMMeshBuilder3 object.

Return Value

Returns one of the following values:
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DD_OK

Remarks

This method was introduced with DirectX version 6.0.

IDirect3DRMMeshBuilder3::DeleteNormals

IDirect3DRMMeshBuilder3

Deletes an inclusive range of normals. Note that if any of the normals are currently in use by a face, an error is returned.

Syntax

HRESULT DeleteNormals
(DWORD dwFirstIndex,
DWORD dwCount);

Parameters

dwFirstIndex
Index of the first normal to delete.
dwCount
Count of vertices to delete.

Return Value

Returns one of the following values:
D3DRMERR_ENTRYINUSE
D3DRMERR_OUTOFRANGE
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DD_OK

Remarks

This method was introduced with DirectX version 6.0.

IDirect3DRMMeshBuilder3::DeleteSubMesh

IDirect3DRMMeshBuilder3

Deletes a submesh. The submesh must be an immediate child of the current Direct3DRMMeshBuilder3 object.

Syntax

HRESULT DeleteSubMesh(
  LPUNKNOWN lplpUnk);

Parameters

lplpUnk
Pointer to the IUnknown interface of the submesh to delete.

Return Value

Returns one of the following values:
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DD_OK

Remarks

This method was introduced with DirectX version 6.0.

See Also

CreateSubMesh, GetSubMeshes and GetParentMesh

IDirect3DRMMeshBuilder3::DeleteVertices

IDirect3DRMMeshBuilder3

Deletes an inclusive range of vertices. Note that if any of the vertices are currently in use by a face, an error is returned.

Syntax

HRESULT DeleteVertices
(DWORD dwFirstIndex,
DWORD dwCount);

Parameters

dwFirstIndex
Index of the first vertex to delete.
dwCount
Count of the vertices to delete.

Return Value

Returns one of the following values:
D3DRMERR_ENTRYINUSE
D3DRMERR_OUTOFRANGE
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DD_OK

Remarks

This method was introduced with DirectX version 6.0.

IDirect3DRMMeshBuilder3::Empty

IDirect3DRMMeshBuilder3

Removes all faces, vertices, and normals from the Direct3DRMMeshBuilder3 object.

Syntax

HRESULT Empty
(DWORD dwFlags);

Parameters

dwFlags
Flags; must be zero.

Return Value

Returns one of the following values:
D3DRMERR_OUTOFRANGE
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DD_OK

Remarks

This method was introduced with DirectX version 6.0.

IDirect3DRMMeshBuilder3::Enable

IDirect3DRMMeshBuilder3

Specifies whether this Direct3DRMMeshBuilder3 object should be enabled or disabled for rendering and picking.

Syntax

HRESULT Enable(
  DWORD dwFlags);

Parameters

dwFlags

The currently defined flags are:

D3DRMADDMESHBUILDER_RENDERENABLE
Rendering is enabled on this Direct3DRMMeshBuilder3 object. This setting is the default.
D3DRMADDMESHBUILDER_PICKENABLE
Picking is enabled on this Direct3DRMMeshBuilder3 object. This setting is the default.

Return Value

Returns one of the following values:
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DD_OK

Remarks

This method was introduced with DirectX version 6.0.

See Also

GetEnable

IDirect3DRMMeshBuilder3::GenerateNormals

IDirect3DRMMeshBuilder3

Processes the Direct3DRMMeshBuilder3 object and generates normals for each vertex in a mesh by averaging the face normals for each face that shares the vertex. New normals are generated if the faces sharing a vertex have an angle between them greater than the crease angle.

Syntax

HRESULT GenerateNormals(
  D3DVALUE dvCreaseAngle,
  DWORD dwFlags
  );

Parameters

dvCreaseAngle
The least angle in radians that faces can have between them and have a new normal generated.
dwFlags
One of the following values.
D3DRMGENERATENORMALS_PRECOMPACT (dwFlags = 1)
Specifies that the algorithm should attempt to compact mesh vertices before it generates normals. See comments below.
D3DRMGENERATENORMALS_USECREASEANGLE (dwFlags = 2)
Specifies that the dvCreaseAngle parameter should be used. Otherwise, the crease angle is ignored.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

Remarks

This method replaces IDirect3DRMMeshBuilder2::GenerateNormals2. If you specify the D3DRMGENERATENORMALS_PRECOMPACT flag, the precompact pass searches all the vertices in the mesh and merges any that are the same. This is a good way of compacting a mesh that has been loaded. Some meshes have multiple vertices if they have multiple normals at that vertex. This is not necessary in Direct3D Retained Mode. Specifying this flag is the way to get rid of the multiple vertices.

After compacting, the normals are generated. The edges between faces are examined, and if the angle the faces make at the edge is less than the crease angle, the face normals are averaged to generate the vertex normal. If the angle is greater than the crease angle, a new normal is generated. Note that a new vertex is not generated.

IDirect3DRMMeshBuilder3::GetBox

IDirect3DRMMeshBuilder3

Retrieves the bounding box containing a Direct3DRMMeshBuilder3 object. The bounding box gives the minimum and maximum model coordinates in each dimension.

Syntax

HRESULT GetBox(
  D3DRMBOX *lpD3DRMBox
  );

Parameters

lpD3DRMBox
Address of a D3DRMBOX structure that will be filled with the bounding box coordinates.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

IDirect3DRMMeshBuilder3::GetColorSource

IDirect3DRMMeshBuilder3

Retrieves the color source of a Direct3DRMMeshBuilder3 object. The color source can be either a face or a vertex.

Syntax

D3DRMCOLORSOURCE GetColorSource( );

Return Value

Returns a member of the D3DRMCOLORSOURCE enumerated type.

See Also

IDirect3DRMMeshBuilder3::SetColorSource

IDirect3DRMMeshBuilder3::GetEnable

IDirect3DRMMeshBuilder3

Retrieves a value that indicates whether this Direct3DRMMeshBuilder3 object should be enabled or disabled.

Syntax

HRESULT GetEnable(
  LPDWORD lpdwFlags);

Parameters

lpdwFlags
Pointer to receive a flag indicating the current enable status of this Direct3DRMMeshBuilder3 object. The currently defined flags are:
D3DRMADDMESHBUILDER_PICKENABLE
Picking is enabled on this Direct3DRMMeshBuilder3 object. This flag is set by default.
D3DRMADDMESHBUILDER_RENDERENABLE
Rendering is enabled on this Direct3DRMMeshBuilder3 object. This flag is set by default.

Return Value

Returns one of the following values:
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DD_OK

Remarks

This method was introduced with DirectX version 6.0.

See Also

Enable

IDirect3DRMMeshBuilder3::GetFace

IDirect3DRMMeshBuilder3

Retrieves a single face of a Direct3DRMMeshBuilder3 object.

Syntax

HRESULT GetFace(
  DWORD dwIndex,
  LPDirect3DRMFace2* lplpD3DRMFace2
  );

Parameters

dwIndex
The index of the mesh face to be retrieved. The face must already be part of a Direct3DRMMeshBuilder3 object.
lplpD3DRMFace2
Address of a pointer to an IDirect3DRMFace2 interface that is filled with an address of the face.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

IDirect3DRMMeshBuilder3::GetFaceCount

IDirect3DRMMeshBuilder3

Retrieves the number of faces in a Direct3DRMMeshBuilder3 object.

Syntax

int GetFaceCount( );

Return Value

Returns the number of faces.

IDirect3DRMMeshBuilder3::GetFaces

IDirect3DRMMeshBuilder3

Retrieves the faces of a Direct3DRMMeshBuilder3 object.

Syntax

HRESULT GetFaces(
  LPDirect3DRMFaceArray* lplpD3DRMFaceArray
  );

Parameters

lplpD3DRMFaceArray
Address of a pointer to an IDirect3DRMFaceArray interface that is filled with an address of the faces.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

IDirect3DRMMeshBuilder3::GetGeometry

IDirect3DRMMeshBuilder3

Retrieves the vertices, normals, and face data for a Direct3DRMMeshBuilder3 object.

Syntax

HRESULT GetGeometry(
  DWORD *vcount,
  D3DVECTOR *vertices,
  DWORD *ncount,
  D3DVECTOR *normals,
  DWORD *face_data_size,
  DWORD *face_data
  );

Parameters

vcount
Address of a variable that will contain the number of vertices.
vertices
Address of an array of D3DVECTOR structures that will contain the vertices for the Direct3DRMMeshBuilder3 object. If this parameter is NULL, the method returns the number of vertices in the vcount parameter.
ncount
Address of a variable that will contain the number of normals.
normals
Address of an array of D3DVECTOR structures that will contain the normals for the Direct3DRMMeshBuilder3 object. If this parameter is NULL, the method returns the number of normals in the ncount parameter.
face_data_size
Address of a variable that specifies the size of the buffer pointed to by the face_data parameter. The size is given in units of DWORD values. This parameter cannot be NULL.
face_data
Address of the face data for the Direct3DRMMeshBuilder3 object. This data is in the same format as specified in the IDirect3DRMMeshBuilder3::AddFaces method except that it is null-terminated. If this parameter is NULL, the method returns the required size of the face-data buffer in the face_data_size parameter.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

Remarks

This method was introduced with DirectX version 6.0. The IDirect3DRMMeshBuilder and IDirect3DRMMeshBuilder2 interfaces provided this functionality through the GetVertices method. The old method was renamed to GetGeometry with the IDirect3DRMMeshBuilder3 interface to better describe what this method does and to avoid conflicts with the new GetVertices method.

IDirect3DRMMeshBuilder3::GetNormal

IDirect3DRMMeshBuilder3

Retrieves a normal vector.

Syntax

HRESULT GetNormal
(DWORD dwIndex,
LPD3DVECTOR lpVector);

Parameters

dwIndex
Index of the normal to return.
lpVector
Pointer to a D3DVECTOR structure that will be filled in with the x-, y-, and z-coordinates of the normal.

Return Value

Returns one of the following values:
D3DRMERR_OUTOFRANGE
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DD_OK

Remarks

This method was introduced with DirectX version 6.0.

IDirect3DRMMeshBuilder3::GetNormalCount

IDirect3DRMMeshBuilder3

Returns the number of normals in the Direct3DRMMeshBuilder3 object.

Syntax

DWORD GetNormalCount(void);

Return Value

Returns one of the following values:
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DD_OK

Remarks

This method was introduced with DirectX version 6.0.

See Also

GetNormals and SetNormals

IDirect3DRMMeshBuilder3::GetNormals

IDirect3DRMMeshBuilder3

Retrieves an array of normals that have previously been defined in the Direct3DRMMeshBuilder3 object.

Syntax

HRESULT GetNormals(
  DWORD dwFirst,
  LPDWORD lpdwCount,
  LPD3DVECTOR lpdvVector);

Parameters

dwFirst
Index of the first normal to be returned.
lpdwCount
Pointer to a DWORD containing the number of normals expected to be returned. If lpdvVector is NULL, this parameter receives the number of normals available, starting from the index given in dwFirst. If lpdvVector is not NULL, this parameter contains the number of normals actually retrieved. To ensure that you receive all the available normals, starting from dwFirst, call this method with lpdvVector set to NULL, then use the value returned in lpdwCount to size the array in lpdvVector, and call the method again.
lpdvVector
Pointer to an array of vectors to receive the normal data.

Return Value

Returns one of the following values:
D3DRMERR_OUTOFRANGE
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DD_OK

Remarks

This method was introduced with DirectX version 6.0.

See Also

GetNormalCount and SetNormals

IDirect3DRMMeshBuilder3::GetParentMesh

IDirect3DRMMeshBuilder3

Retrieves a parent mesh of this Direct3DRMMeshBuilder3 object. If the current mesh is not a submesh, this method retrieves a pointer to its own IUnknown interface.

Syntax

HRESULT GetParentMesh(
  DWORD dwFlags,
  LPUNKNOWN * lplpUnk);

Parameters

dwFlags
Flag value that defines which Direct3DRMMeshBuilder3 object to retrieve. The currently defined flags are:
D3DRMMESHBUILDER_DIRECTPARENT
This Direct3DRMMeshBuilder3 object's direct parent.
D3DRMMESHBUILDER_ROOTMESH
The final parent of this Direct3DRMMeshBuilder3 object that has no parent.
lplpUnk
Address of a pointer to receive the parent's IUnknown interface.

Return Value

Returns one of the following values:
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DD_OK

Remarks

This method was introduced with DirectX version 6.0.

See Also

GetSubMeshes

IDirect3DRMMeshBuilder3::GetPerspective

IDirect3DRMMeshBuilder3

Determines whether perspective correction is on for a Direct3DRMMeshBuilder3 object.

Syntax

BOOL GetPerspective( );

Return Value

Returns TRUE if perspective correction is on, or FALSE otherwise.

IDirect3DRMMeshBuilder3::GetQuality

IDirect3DRMMeshBuilder3

Retrieves the rendering quality of a Direct3DRMMeshBuilder3 object.

Syntax

D3DRMRENDERQUALITY GetQuality( );

Return Value

Returns a member of the D3DRMRENDERQUALITY enumerated type that specifies the rendering quality of the mesh.

See Also

IDirect3DRMMeshBuilder3::SetQuality

IDirect3DRMMeshBuilder3::GetSubMeshes

IDirect3DRMMeshBuilder3

Retrieves a list of the submeshes that this Direct3DRMMeshBuilder3 object contains.

Syntax

HRESULT GetSubMeshes(
  LPDWCOUNT lpdwCount,
  LPUNKNOWN lpUnk);

Parameters

lpdwCount
Pointer to a DWORD value containing the number of IUnknown interface pointers expected to be returned. If lpUnk is NULL, the value pointed to by lpdwCount receives the number of pointers available. Otherwise, the value pointed to by lpdwCount receives the number of IUnknown pointers actually retrieved.
lpUnk
Array of IUnknown pointers to child submeshes

Return Value

Returns one of the following values:
D3DRMERR_OUTOFRANGE
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DD_OK

Remarks

This method was introduced with DirectX version 6.0.

See Also

GetParentMesh

IDirect3DRMMeshBuilder3::GetTextureCoordinates

IDirect3DRMMeshBuilder3

Retrieves the texture coordinates of a specified vertex in a Direct3DRMMeshBuilder3 object.

Syntax

HRESULT GetTextureCoordinates(
  DWORD index,
  D3DVALUE *lpU,
  D3DVALUE *lpV
  );

Parameters

index
Index of the vertex.
lpU and lpV
Addresses of variables that will be filled with the texture coordinates of the vertex when the method returns.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

See Also

IDirect3DRMMeshBuilder3::SetTextureCoordinates

IDirect3DRMMeshBuilder3::GetVertex

IDirect3DRMMeshBuilder3

Retrieves a vertex vector.

Syntax

HRESULT GetVertex
(DWORD dwIndex,
LPD3DVECTOR lpVector);

Parameters

dwIndex
Index of the vertex to return.
lpVector
Pointer to a D3DVECTOR structure that will be filled in with the x-, y-, and z-coordinates of the vertex.

Return Value

Returns one of the following values:
D3DRMERR_OUTOFRANGE
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DD_OK

Remarks

This method was introduced with DirectX version 6.0.

IDirect3DRMMeshBuilder3::GetVertexColor

IDirect3DRMMeshBuilder3

Retrieves the color of a specified vertex in a Direct3DRMMeshBuilder3 object.

Syntax

D3DCOLOR GetVertexColor(
  DWORD index
  );

Parameters

index
Index of the vertex.

Return Value

Returns the color.

See Also

IDirect3DRMMeshBuilder3::SetVertexColor

IDirect3DRMMeshBuilder3::GetVertexCount

IDirect3DRMMeshBuilder3

Retrieves the number of vertices in a Direct3DRMMeshBuilder3 object.

Syntax

int GetVertexCount( );

Return Value

Returns the number of vertices.

IDirect3DRMMeshBuilder3::GetVertices

IDirect3DRMMeshBuilder3

Retrieves an array of vertices that previously have been defined in the Direct3DRMMeshBuilder3 object.

Syntax

HRESULT GetVertices(
  DWORD dwFirst,
  LPDWORD lpdwCount,
  LPD3DVECTOR lpdvVector);

Parameters

dwFirst
Index of the first vertex to be returned.
lpdwCount
Pointer to a DWORD value containing the number of vectors expected to be returned. If lpdvVector is NULL, the DWORD value receives the number of vertices available from the given offset. Otherwise, the DWORD value receives the number of vectors actually retrieved.
lpdvVector
Pointer to an array of vectors that will be initialized with the vertex data.

Return Value

Returns one of the following values:
D3DRMERR_OUTOFRANGE
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DD_OK

Remarks

This method was introduced with DirectX version 6.0 and is different from the GetVertices method that the old IDirect3DRMMeshBuilder and IDirect3DRMMeshBuilder2 interfaces provide. For IDirect3DRMMeshBuilder3, the older method has been renamed to GetGeometry, which better describes its function.

See Also

SetVertices and GetGeometry

IDirect3DRMMeshBuilder3::Load

IDirect3DRMMeshBuilder3

Loads a Direct3DRMMeshBuilder3 object.

Syntax

HRESULT Load(
  LPVOID lpvObjSource,
  LPVOID lpvObjID,
  D3DRMLOADOPTIONS d3drmLOFlags,
  D3DRMLOADTEXTURE3CALLBACK d3drmLoadTextureProc,
  LPVOID lpvArg
  );

Parameters

lpvObjSource
Source for the object to be loaded. This source can be a file, resource, memory block, or stream, depending on the source flags specified in the d3drmLOFlags parameter.
lpvObjID
Object name or position to be loaded. The use of this parameter depends on the identifier flags specified in the d3drmLOFlags parameter. If the D3DRMLOAD_BYPOSITION flag is specified, this parameter is a pointer to a DWORD value that gives the object's order in the file. This parameter can be NULL.
d3drmLOFlags
Value of the D3DRMLOADOPTIONS type describing the load options.
d3drmLoadTextureProc
A D3DRMLOADTEXTURE3CALLBACK callback function used to load any textures used by an object that require special formatting. This parameter can be NULL.
lpvArg
Address of application-defined data passed to the D3DRMLOADTEXTURE3CALLBACK callback function.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

Remarks

By default, this method loads the first mesh from the source specified in the lpvObjSource parameter.

This method respects the right-handed and left-handed geometry options as set by IDirect3DRM3::SetOptions.

You can load more than one object into a MeshBuilder by calling its load method multiple times.


IDirect3DRMMeshBuilder3

IDirect3DRMMeshBuilder3 Methods N to Z

This section contains the reference pages for the methods of the IDirect3DRMMeshBuilder3 interface that begin with the letters N through Z.

IDirect3DRMMeshBuilder3::Optimize

IDirect3DRMMeshBuilder3

Optimizes the MeshBuilder object for the current device. Note that this may be an expensive operation.

Syntax

HRESULT Optimize
(DWORD dwFlags);

Parameters

dwFlags
Must be zero.

Return Value

Returns one of the following values:
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DD_OK

Remarks

This method was introduced with DirectX version 6.0.

IDirect3DRMMeshBuilder3::ReserveSpace

IDirect3DRMMeshBuilder3

Reserves space within a Direct3DRMMeshBuilder3 object for the specified number of vertices, normals, and faces. This allows the system to use memory more efficiently.

Syntax

HRESULT ReserveSpace(
  DWORD vertexCount,
  DWORD normalCount,
  DWORD faceCount
  );

Parameters

vertexCount, normalCount, and faceCount
Number of vertices, normals, and faces to allocate space for.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

IDirect3DRMMeshBuilder3::Save

IDirect3DRMMeshBuilder3

Saves a Direct3DRMMeshBuilder3 object.

Syntax

HRESULT Save(
  const char * lpFilename,
  D3DRMXOFFORMAT d3drmXOFFormat,
  D3DRMSAVEOPTIONS d3drmSOContents
  );

Parameters

lpFilename
Address specifying the name of the created file. This file must have a .x file name extension.
d3drmXOFFormat
The D3DRMXOF_TEXT value from the D3DRMXOFFORMAT enumerated type.
d3drmSOContents
Value of the D3DRMSAVEOPTIONS type describing the save options.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

IDirect3DRMMeshBuilder3::Scale

IDirect3DRMMeshBuilder3

Scales a Direct3DRMMeshBuilder3 object by the given scaling factors, parallel to the x-, y-, and z-axes in model coordinates.

Syntax

HRESULT Scale(
  D3DVALUE sx,
  D3DVALUE sy,
  D3DVALUE sz
  );

Parameters

sx, sy, and sz
Scaling factors that are applied along the x-, y-, and z-axes.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

IDirect3DRMMeshBuilder3::SetColor

IDirect3DRMMeshBuilder3

Sets all the faces of a Direct3DRMMeshBuilder3 object to a given color.

Syntax

HRESULT SetColor(
  D3DCOLOR color
  );

Parameters

color
Color of the faces. Be sure to set the alpha component as well as the red, green, and blue color components or your objects might not be visible. The RGBA_MAKE DirectX macro allows you to specify these values.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

IDirect3DRMMeshBuilder3::SetColorRGB

IDirect3DRMMeshBuilder3

Sets all the faces of a Direct3DRMMeshBuilder3 object to a given color.

Syntax

HRESULT SetColorRGB(
  D3DVALUE red,
  D3DVALUE green,
  D3DVALUE blue
  );

Parameters

red, green, and blue
Red, green, and blue components of the color.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

IDirect3DRMMeshBuilder3::SetColorSource

IDirect3DRMMeshBuilder3

Sets the color source of a Direct3DRMMeshBuilder3 object.

Syntax

HRESULT SetColorSource(
  D3DRMCOLORSOURCE source
  );

Parameters

source
Member of the D3DRMCOLORSOURCE enumerated type that specifies the new color source to use.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

See Also

IDirect3DRMMeshBuilder3::GetColorSource

IDirect3DRMMeshBuilder3::SetMaterial

IDirect3DRMMeshBuilder3

Sets the material of all the faces of a Direct3DRMMeshBuilder3 object.

Syntax

HRESULT SetMaterial(
  LPDIRECT3DRMMATERIAL2 lpIDirect3DRMmaterial
  );

Parameters

lpIDirect3DRMmaterial
Address of IDirect3DRMMaterial2 interface for the Direct3DRMMeshBuilder3 object.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

IDirect3DRMMeshBuilder3::SetNormal

IDirect3DRMMeshBuilder3

Sets the normal vector of a specified vertex in a Direct3DRMMeshBuilder3 object.

Syntax

HRESULT SetNormal(
  DWORD index,
  D3DVALUE x,
  D3DVALUE y,
  D3DVALUE z
  );

Parameters

index
Index of the normal to be set.
x, y, and z
The x-, y-, and z-components of the vector to assign to the specified normal.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

IDirect3DRMMeshBuilder3::SetNormals

IDirect3DRMMeshBuilder3

Sets the normals that previously have been defined in the Direct3DRMMeshBuilder3 object.

Syntax

HRESULT SetNormals(
  DWORD dwFirst,
  DWORD dwCount,
  LPD3DVECTOR lpdvVector);

Parameters

dwFirst
Index of the first normal to be modified.
dwCount
Number of normals to be modified.
lpdvVector
Array of vectors describing the new normal data.

Return Value

Returns one of the following values:
D3DRMERR_OUTOFRANGE
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DD_OK

Remarks

This method was introduced with DirectX version 6.0.

See Also

GetNormals

IDirect3DRMMeshBuilder3::SetPerspective

IDirect3DRMMeshBuilder3

Enables or disables perspective-correct texture-mapping for a Direct3DRMMeshBuilder3 object.

Syntax

HRESULT SetPerspective(
  BOOL perspective
  );

Parameters

perspective
Specify TRUE if the mesh should be texture-mapped with perspective correction, or FALSE otherwise.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

IDirect3DRMMeshBuilder3::SetQuality

IDirect3DRMMeshBuilder3

Sets the rendering quality of a Direct3DRMMeshBuilder3 object.

Syntax

HRESULT SetQuality(
  D3DRMRENDERQUALITY quality
  );

Parameters

quality
Member of the D3DRMRENDERQUALITY enumerated type that specifies the new rendering quality to use.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

Remarks

An object's quality has three components: shade mode (flat or Gouraud; Phong shading is not yet implemented and will default to Gouraud shading), lighting type (on or off), and fill mode (point, wireframe, or solid).

You can set the quality of a device with IDirect3DRMDevice3::SetQuality. By default it is D3DRMRENDER_FLAT (flat shading, lights on, and solid fill).

You can set the quality of a Direct3DRMMeshBuilder3 object with the SetQuality method. By default, a Direct3DRMMeshBuilder3 object's quality is D3DRMRENDER_GOURAUD (Gouraud shading, lights on, and solid fill).

Tip: Gouraud shading performs better than Phong shading on progressive mesh objects that change their level of detail often or quickly.

Direct3D Retained Mode renders an object at the lowest quality setting based on the device and object's current setting for each individual component. For example, if the object's current quality setting is D3DRMRENDER_GOURAUD, and the device is D3DRMRENDER_FLAT then the object will be rendered with flat shading, solid fill and lights on.

If the object's current quality setting is D3DRMSHADE_GOURAUD|D3DRMLIGHT_OFF|D3DRMFILL_WIREFRAME and the device's quality setting is D3DRMSHADE_FLAT|D3DRMLIGHT_ON|D3DRMFILL_POINT, then the object will be rendered with flat shading, lights off, and point fill mode.

These rules apply to Direct3DRMMeshBuilder3 objects and Direct3DRMProgressiveMesh objects. However, Direct3DRMMesh objects do not follow these rules. Mesh objects ignore the device's quality settings and use the group quality setting (which defaults to D3DRMRENDER_GOURAUD).

See Also

IDirect3DRMMeshBuilder3::GetQuality

IDirect3DRMMeshBuilder3::SetTexture

IDirect3DRMMeshBuilder3

Sets the texture of all the faces of a Direct3DRMMeshBuilder3 object.

Syntax

HRESULT SetTexture(
  LPDIRECT3DRMTEXTURE3 lpD3DRMTexture
  );

Parameters

lpD3DRMTexture
Address of the required Direct3DRMTexture object.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

IDirect3DRMMeshBuilder3::SetTextureCoordinates

IDirect3DRMMeshBuilder3

Sets the texture coordinates of a specified vertex in a Direct3DRMMeshBuilder3 object.

Syntax

HRESULT SetTextureCoordinates(
  DWORD index,
  D3DVALUE u,
  D3DVALUE v
  );

Parameters

index
Index of the vertex to be set.
u and v
Texture coordinates to assign to the specified mesh vertex.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

See Also

IDirect3DRMMeshBuilder3::GetTextureCoordinates

IDirect3DRMMeshBuilder3::SetTextureTopology

IDirect3DRMMeshBuilder3

Sets the texture topology of a Direct3DRMMeshBuilder3 object.

Syntax

HRESULT SetTextureTopology(
  BOOL cylU,
  BOOL cylV
  );

Parameters

cylU and cylV
Specify TRUE for either or both of these parameters if you want the texture to have a cylindrical topology in the u- and v-dimensions, respectively; otherwise, specify FALSE.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

Remarks

The texture topology flags, cylU and cylV, control the settings of the Direct3D Immediate Mode render states D3DRENDERSTATE_WRAPU and D3DRENDERSTATE_WRAPV. When a wrap flag is TRUE, the rasterizer will cross from one edge of the texture to the opposite edge (toroidal mapping) if it is the shorter path between two texture coordinates. Consider a triangle that has v coordinates ranging from 0.1 and 0.9 along one edge. If WRAPV is FALSE, nearly the full length of the texture will be rendered along the triangle. If WRAPV is TRUE, a sliver from the top of the texture and one from the bottom will be rendered. Additionally, when a wrap flag is TRUE, only the fractional part of a texture coordinate is considered for values greater than 1.0, which means textures will not be tiled across a face when wrap is TRUE.

Controlling the wrapping behavior is necessary for proper interpretation of texture coordinates. If you have a single texture wrapped across many faces, set the cylU and cylV parameters to TRUE. If a model has one texture per face or you want multiple copies of the texture to be tiled across a single face by using texture coordinates greater than 1, set cylU and cylV to FALSE.

Several interfaces expose a SetTextureTopology method. IDirect3DRMMeshBuilder3::SetTextureTopology updates the topology on all component faces, overriding any settings made by IDirect3DRMFace2::SetTextureTopology. By default, IDirect3DRMFrame3::SetTextureTopology reads from the mesh because the default material mode is D3DRMMATERIAL_FROMMESH. If the material mode is not D3DRMMATERIAL_FROMMESH, IDirect3DRMFrame3::SetTextureTopology overrides settings made by IDirect3DRMMeshBuilder3::SetTextureTopology.

IDirect3DRMMeshBuilder3::SetVertex

IDirect3DRMMeshBuilder3

Sets the position of a specified vertex in a Direct3DRMMeshBuilder3 object.

Syntax

HRESULT SetVertex(
  DWORD index,
  D3DVALUE x,
  D3DVALUE y,
  D3DVALUE z
  );

Parameters

index
Index of the vertex to be set.
x, y, and z
The x-, y-, and z-components of the position to assign to the specified vertex.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

IDirect3DRMMeshBuilder3::SetVertexColor

IDirect3DRMMeshBuilder3

Sets the color of a specified vertex in a Direct3DRMMeshBuilder3 object.

Syntax

HRESULT SetVertexColor(
  DWORD index,
  D3DCOLOR color
  );

Parameters

index
Index of the vertex to be set.
color
Color to assign to the specified vertex.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

See Also

IDirect3DRMMeshBuilder3::GetVertexColor

IDirect3DRMMeshBuilder3::SetVertexColorRGB

IDirect3DRMMeshBuilder3

Sets the color of a specified vertex in a Direct3DRMMeshBuilder3 object.

Syntax

HRESULT SetVertexColorRGB(
  DWORD index,
  D3DVALUE red,
  D3DVALUE green,
  D3DVALUE blue
  );

Parameters

index
Index of the vertex to be set.
red, green, and blue
Red, green, and blue components of the color to assign to the specified vertex.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.

IDirect3DRMMeshBuilder3::SetVertices

IDirect3DRMMeshBuilder3

Sets the vertices that previously have been defined in the Direct3DRMMeshBuilder3 object.

Syntax

HRESULT SetVertices(
  DWORD dwFirst,
  DWORD dwCount,
  LPD3DVECTOR lpdvVector);

Parameters

dwFirst
Index of the first vertex to be modified.
dwCount
Number of vertices to modify.
lpdvVector
Array of vectors describing the new vertex data.

Return Value

Returns one of the following values:
D3DRMERR_OUTOFRANGE
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DD_OK

Remarks

This method was introduced with DirectX version 6.0.

See Also

GetVertices

IDirect3DRMMeshBuilder3::Translate

IDirect3DRMMeshBuilder3

Adds the specified offsets to the vertex positions of a Direct3DRMMeshBuilder3 object.

Syntax

HRESULT Translate(
  D3DVALUE tx,
  D3DVALUE ty,
  D3DVALUE tz
  );

Parameters

tx, ty, and tz
Offsets that are added to the x-, y-, and z-coordinates, respectively, of each vertex position.

Return Value

Returns D3DRM_OK if successful, or an error otherwise. For a list of possible errors, see Direct3D Retained Mode Return Values.


C

client/server session
A DirectPlay session in which only the server stores the session's complete state, and each client has only a subset of the session's state. Each client has only the information that is relevant to that computer and receives that information from the server. When one computer changes something, it propagates the change to the server. The server then determines which clients it must inform of the change. Also see peer-to-peer session.


D

DirectPlay Address
A data format that DirectPlay uses to pass addressing information between lobby servers, applications, DirectPlay, and service providers. A DirectPlay Address is a sequence of variable-length data chunks tagged with a globally unique identifier (GUID) that supplies all the address information needed by DirectPlay. Examples of address information are: the network address of a server, the network address of a player, the e-mail name of a player, and the network address of a session.
DirectPlay defined property
A property that can be set and retrieved by applications from a lobby. When a DPLMSG_GETPROPERTYRESPONSE message is received, its guidPropertyTag field identifies the property, and its dwPropertyData field contains the property information.


G

group
A logical collection of players. DirectPlay supports groups within a session. By creating a group of players, an application can send a single message to the group, and all the players in the group will receive the message. A group is the means by which a network's multicast capabilities are exposed to the application.

Groups can be used as a general means to organize players in a session. A player can belong to more than one group. DirectPlay provides methods for administering groups and their membership.


H

host
In DirectPlay, a virtual player whose ID is DPID_SYSMSG. The host manages system messages and messages sent to all players in a session.


I

IPX service provider
A service provider that uses Winsock to communicate over a local area network (LAN) using the Internet Packet Exchange (IPX) protocol. The service provider only supports nonguaranteed messaging. A single computer can host only one DirectPlay session using IPX.


L

latency
The time in milliseconds it takes for a small packet to reach a given destination. You can use IDirectPlay4::GetCaps to retrieve the latency of the service provider. The dwlatency member of the DPCAPS structure represents the service provider's estimate of typical net latency; for example, the latency on the Internet is typically about 500 ms.
lobby client
An application that has joined a lobby session. Joining a lobby session gives the client application access to all the information on the lobby server, and enables the user to interact with other users on the lobby server. The lobby client uses lobby management routines to locate and join sessions.
lobby-aware application
An application that, at a minimum, supports being launched from a lobby.
lobby provider
A client component (DLL) supplied by the developer of a lobby server. It implements communications functions with the lobby server as requested by DirectPlay. The DirectX Software Development Kit (SDK) installs a lobby provider for use with the test lobby server (LSERVER.EXE) that is included with the SDK.
lobby server
A common place on a network that (at a minimum) tracks DirectPlay application sessions in progress and also tracks users that are connected to the server. The lobby server coordinates all the information about the users connected to a specific application. Users can navigate around the lobby server to find areas of interest. At any location on the lobby server, the user can chat with other users, join sessions that are in progress, or gather a group of players to start a new session.
lobby session
A connection to a lobby server where clients and the server have not been specifically written to interoperate.


N

nagling
An algorithm that causes the TCP/IP service provider to buffer small data packets into larger ones before sending. Nagling prevents a TCP/IP server from transmitting many very small packets by requiring the server either to wait until it has accumulated enough small data packets to combine them into a single large packet, or until it has received an acknowledgment of the prior packet. Nagling can reduce message overhead (and decrease required bandwidth), but also causes a delay before small data packets are sent (increasing latency). You can turn off nagling by setting the DPSESSION_OPTIMIZELATENCY flag in the DPSESSIONDESC2 structure.

© 1998 Microsoft Corporation. All rights reserved. Terms of Use.


P

peer-to-peer session
A DirectPlay session in which the session's complete state is replicated on all the computers in the session. The session description data—the list of players and groups, and the names and remote data associated with each session — are duplicated on every computer. When one computer changes something, it is immediately propagated to all the other computers. This is DirectPlay's default mode of communications. Also see client/server session.


S

secure session
A session in which all the users have been authenticated against a database of known users before being allowed to join a session. In a secure session, all DirectPlay system messages are digitally signed to verify the identity of the sender. Certain system messages that carry sensitive information are encrypted. System messages that originate from one player and need to be broadcast to all the other players in the session are first sent to the server. The server then puts its signature on the message and forwards the message to all the other computers in the session. Player to player messages are not signed by default and are not routed through the server.
service provider
A dynamic-link library (DLL) used by DirectPlay to communicate over a network. The service provider contains all the network-specific code required to send and receive messages. Online services and network operators can supply service providers to use specialized hardware, protocols, communications media, and network resources. Microsoft includes four generic service providers with DirectPlay: head-to-head modem (TAPI), serial connection, Internet TCP/IP (using Winsock), and IPX (also using Winsock).
session
An instance of several applications on remote machines communicating with each other. Before an application can start communicating with other computers, it must be part of a session. An application can enumerate all the existing sessions on a network and join one of them, or it can create a new session and wait for other computers to join it. Once the application is part of a session, it can create a player and exchange messages with all the other players in the session.
system message
A message from the player ID DPID_SYSMSG. All system messages begin with a double-word value. You can cast the buffer returned by the IDirectPlay4::Receive method to a generic message (DPMSG_GENERIC) and switch on this DWORD value. The DWORD value is equal to one of the messages with a DPSYS_ prefix, for example, DPSYS_SESSIONLOST. After the application has determined which system message it is, the buffer should be cast to the appropriate structure (beginning with the DPMSG_ prefix), for example, DPMSG_SESSIONLOST, to read the data.


T

TCP/IP service provider
A service provider that uses Winsock to communicate over the Internet or local area network (LAN) using the TCP/IP protocol. It uses UDP (User Datagram Protocol) packets for nonguaranteed messaging and TCP for guaranteed messaging. A single computer can host multiple DirectPlay sessions using TCP/IP.


U

user authentication
Authentication is used to verify that the user is allowed access to the server by virtue of having been added to the membership database by the administrator of the server. Only users that are part of the membership database are permitted to join the session. User authentication should not be confused with password protection of a session. A password can be added to a session so that only those members who know the password can join a particular session. Authentication requires a server that supports authentication, while any computer can put a password on a session.