| <chapter id="ddraw"> | |
| <title>Outline of DirectDraw Architecture</title> | |
| <para> | |
| This is an outline of the architecture. Many details are | |
| skipped, but hopefully this is useful. | |
| </para> | |
| <sect1 id="ddinheritance"> | |
| <title>DirectDraw inheritance tree</title> | |
| <programlisting> | |
| Main | |
| | | |
| User | |
| |-----------\ | |
| XVidMode DGA2 | |
| </programlisting> | |
| <para> | |
| 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. | |
| </para> | |
| <para> | |
| User provides for DirectDraw capabilities based on drawing to a | |
| Wine window. It uses the User DirectDrawSurface implementation | |
| for primary and backbuffer surfaces. | |
| </para> | |
| <para> | |
| XVidMode attempt to use the XFree86 VidMode extension to set the | |
| display resolution to match the parameters to SetDisplayMode. | |
| </para> | |
| <para> | |
| 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. | |
| </para> | |
| </sect1> | |
| <sect1 id="ddsurfaceinheritance"> | |
| <title>DirectDrawSurface inheritance tree</title> | |
| <programlisting> | |
| Main | |
| |--------------\ | |
| | | | |
| DIB Fake Z-Buffer | |
| | | |
| |------\---------\ | |
| | | | | |
| User DGA2 DIBTexture | |
| </programlisting> | |
| <para> | |
| 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. | |
| </para> | |
| <para> | |
| DIB stores the surface data in a DIB section. It is used by the Main | |
| DirectDraw driver to create off-screen surfaces. | |
| </para> | |
| <para> | |
| 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. | |
| </para> | |
| <para> | |
| DGA2 surfaces claims an appropriate section of framebuffer space and | |
| lets DIB build its DIB section on top of it. | |
| </para> | |
| <para> | |
| 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. | |
| </para> | |
| <para> | |
| (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.) | |
| </para> | |
| </sect1> | |
| <sect1 id="interfacethunks"> | |
| <title>Interface Thunks</title> | |
| <para> | |
| 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. | |
| </para> | |
| <para> | |
| 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. | |
| </para> | |
| <para> | |
| Interface thunks for Direct3D are more complicated since the paradigm | |
| changed between versions. | |
| </para> | |
| </sect1> | |
| <sect1 id="logicalobjectlayout"> | |
| <title>Logical Object Layout</title> | |
| <para> | |
| 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. | |
| </para> | |
| <para> | |
| For example, the DIBTexture DirectDrawSurface implementation looks | |
| like this: | |
| </para> | |
| <programlisting> | |
| 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; | |
| </programlisting> | |
| <para> | |
| So the DIBTexture surface class is derived from the DIB surface | |
| class and it adds one piece of data, a union. | |
| </para> | |
| <para> | |
| Main does not have a Part structure. Its fields are stored in | |
| IDirectDrawImpl/IDirectDrawSurfaceImpl. | |
| </para> | |
| <para> | |
| To access private data, one says | |
| </para> | |
| <programlisting> | |
| DIBTexture_DirectDrawSurfaceImpl* priv = This->private; | |
| do_something_with(priv->dibtexture.data); | |
| </programlisting> | |
| </sect1> | |
| <sect1 id="creatingobject"> | |
| <title>Creating Objects</title> | |
| <para> | |
| 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. | |
| </para> | |
| <para> | |
| Each class's Construct function calls the base class's Construct, | |
| then does the necessary initialization. | |
| </para> | |
| <para> | |
| 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. | |
| </para> | |
| </sect1> | |
| </chapter> | |
| <!-- Keep this comment at the end of the file | |
| Local variables: | |
| mode: sgml | |
| sgml-parent-document:("wine-devel.sgml" "set" "book" "chapter" "") | |
| End: | |
| --> |