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