(→Creating Objects: fix markup) |
(add categories) |
||
Line 79: | Line 79: | ||
For example, creating a primary surface with the user ddraw driver calls <code>User_DirectDrawSurface_Create</code> which allocates memory for the object and calls <code>User_DirectDrawSurface_Construct</code> to initialize it. This calls <code>DIB_DirectDrawSurface_Construct</code> which calls <code>Main_DirectDrawSurface_Construct</code>. | For example, creating a primary surface with the user ddraw driver calls <code>User_DirectDrawSurface_Create</code> which allocates memory for the object and calls <code>User_DirectDrawSurface_Construct</code> to initialize it. This calls <code>DIB_DirectDrawSurface_Construct</code> which calls <code>Main_DirectDrawSurface_Construct</code>. | ||
[[Category:Documentation]][[Category:Development]] |
Latest revision as of 19:00, 8 February 2016
__NUMBEREDHEADINGS__ This is an outline of the architecture. Many details are skipped, but hopefully this is useful.
DirectDraw inheritance tree
Main | User |-----------\ XVidMode DGA2
Most of the DirectDraw functionality is implemented in a common base class. Derived classes are responsible for providing display mode methods (EnumDisplayModes
, SetDisplayMode
, RestoreDisplayMode
), GetCaps
, GetDeviceIdentifier
and internal functions called to create primary and backbuffer surfaces.
User
provides for DirectDraw capabilities based on drawing to a Wine window. It uses the User
DirectDrawSurface implementation for primary and backbuffer surfaces.
XVidMode
attempt to use the XFree86 VidMode extension to set the display resolution to match the parameters to SetDisplayMode
.
DGA2
attempt to use the XFree86 DGA 2.x extension to set the display resolution and direct access to the framebuffer, if the full-screen-exclusive cooperative level is used. If not, it just uses the User
implementation.
DirectDrawSurface inheritance tree
Main |--------------\ | | DIB Fake Z-Buffer | |------\---------\ | | | User DGA2 DIBTexture
Main
provides a very simple base class that does not implement any of the image-related functions. Therefore it does not place any constraints on how the surface data is stored.
DIB
stores the surface data in a DIB section. It is used by the Main
DirectDraw driver to create off-screen surfaces.
User
implements primary and backbuffer surfaces for the User DirectDraw driver. If it is a primary surface, it will attempt to keep itself synchronized to the window.
DGA2
surfaces claims an appropriate section of framebuffer space and lets DIB
build its DIB section on top of it.
Fake Z-Buffer
surfaces are used by Direct3D to indicate that a primary surface has an associated z-buffer. For a first implementation, it doesn't need to store any image data since it is just a placeholder.
(Actually 3D programs will rarely use Lock
or GetDC
on primary surfaces, backbuffers or z-buffers so we may want to arrange for lazy allocation of the DIB sections.)
Interface Thunks
Only the most recent version of an interface needs to be implemented. Other versions are handled by having thunks convert their parameters and call the root version.
Not all interface versions have thunks. Some versions could be combined because their parameters were compatible. For example if a structure changes but the structure has a dwSize
field, methods using that structure are compatible, as long as the implementation remembers to take the dwSize
into account.
Interface thunks for Direct3D are more complicated since the paradigm changed between versions.
Logical Object Layout
The objects are split into the generic part (essentially the fields for Main
) and a private part. This is necessary because some objects can be created with CoCreateInstance
, then initialized later. Only at initialization time do we know which class to use. Each class except Main
declares a Part
structure and adds that to its Impl.
For example, the DIBTexture
DirectDrawSurface implementation looks like this:
struct DIBTexture_DirectDrawSurfaceImpl_Part
{
union DIBTexture_data data; /*declared in the real header*/
};
typedef struct
{
struct DIB_DirectDrawSurfaceImpl_Part dib;
struct DIBTexture_DirectDrawSurfaceImpl_Part dibtexture;
} DIBTexture_DirectDrawSurfaceImpl;
So the DIBTexture
surface class is derived from the DIB
surface class and it adds one piece of data, a union.
Main
does not have a Part
structure. Its fields are stored in IDirectDrawImpl
/IDirectDrawSurfaceImpl
.
To access private data, one says
DIBTexture_DirectDrawSurfaceImpl* priv = This->private; do_something_with(priv->dibtexture.data);
Creating Objects
Classes have two methods relevant to object creation, Create
and Construct
. To create a new object, the Create
method of the class is called. It allocates enough memory for IDirectDrawImpl
or IDirectDrawSurfaceImpl
as well as the private data for derived classes and then calls Construct.
Each class Construct
method calls the base class Construct
, then does the necessary initialization.
For example, creating a primary surface with the user ddraw driver calls User_DirectDrawSurface_Create
which allocates memory for the object and calls User_DirectDrawSurface_Construct
to initialize it. This calls DIB_DirectDrawSurface_Construct
which calls Main_DirectDrawSurface_Construct
.