135 lines
4.6 KiB
Plaintext
135 lines
4.6 KiB
Plaintext
|
This is an outline of the architecture. Many details are
|
|||
|
skipped, but hopefully this is useful.
|
|||
|
|
|||
|
By Andrew Lewycky <andrew@transgaming.com>
|
|||
|
(with updates by Ove K<>ven <ovek@transgaming.com>)
|
|||
|
|
|||
|
|
|||
|
* 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 functions (Enum, Set, Restore), GetCaps, GetDevice identifier
|
|||
|
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 initialisation 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 functions relevant to object creation, Create and
|
|||
|
Construct. To create a new object, the class' Create function 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's Construct function calls the base class's 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.
|