| <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: |
| --> |