Alexandre Julliard | d6c0f9f | 2001-01-04 22:44:55 +0000 | [diff] [blame] | 1 | This is an outline of the architecture. Many details are |
| 2 | skipped, but hopefully this is useful. |
| 3 | |
| 4 | By Andrew Lewycky <andrew@transgaming.com> |
| 5 | (with updates by Ove Kåven <ovek@transgaming.com>) |
| 6 | |
| 7 | |
| 8 | * DirectDraw inheritance tree |
| 9 | |
| 10 | Main |
| 11 | | |
| 12 | User |
| 13 | |-----------\ |
| 14 | XVidMode DGA2 |
| 15 | |
| 16 | Most of the DirectDraw functionality is implemented in a common base |
| 17 | class. Derived classes are responsible for providing display |
| 18 | mode functions (Enum, Set, Restore), GetCaps, GetDevice identifier |
| 19 | and internal functions called to create primary and backbuffer |
| 20 | surfaces. |
| 21 | |
| 22 | User provides for DirectDraw capabilities based on drawing to a |
| 23 | Wine window. It uses the User DirectDrawSurface implementation |
| 24 | for primary and backbuffer surfaces. |
| 25 | |
| 26 | XVidMode attempt to use the XFree86 VidMode extension to set the |
| 27 | display resolution to match the parameters to SetDisplayMode. |
| 28 | |
| 29 | DGA2 attempt to use the XFree86 DGA 2.x extension to set the |
| 30 | display resolution and direct access to the framebuffer, if the |
| 31 | full-screen-exclusive cooperative level is used. If not, it just |
| 32 | uses the User implementation. |
| 33 | |
| 34 | |
| 35 | * DirectDrawSurface inheritance tree |
| 36 | |
| 37 | Main |
| 38 | |--------------\ |
| 39 | | | |
| 40 | DIB Fake Z-Buffer |
| 41 | | |
| 42 | |------\---------\ |
| 43 | | | | |
| 44 | User DGA2 DIBTexture |
| 45 | |
| 46 | Main provides a very simple base class that does not implement any of |
| 47 | the image-related functions. Therefore it does not place any |
| 48 | constraints on how the surface data is stored. |
| 49 | |
| 50 | DIB stores the surface data in a DIB section. It is used by the Main |
| 51 | DirectDraw driver to create off-screen surfaces. |
| 52 | |
| 53 | User implements primary and backbuffer surfaces for the User DirectDraw |
| 54 | driver. If it is a primary surface, it will attempt to keep itself |
| 55 | synchronized to the window. |
| 56 | |
| 57 | DGA2 surfaces claims an appropriate section of framebuffer space and |
| 58 | lets DIB build its DIB section on top of it. |
| 59 | |
| 60 | Fake Z-Buffer surfaces are used by Direct3D to indicate that a primary |
| 61 | surface has an associated z-buffer. For a first implementation, it |
| 62 | doesn't need to store any image data since it is just a placeholder. |
| 63 | |
| 64 | (Actually 3D programs will rarely use Lock or GetDC on primary |
| 65 | surfaces, backbuffers or z-buffers so we may want to arrange for |
| 66 | lazy allocation of the DIB sections.) |
| 67 | |
| 68 | |
| 69 | * Interface Thunks |
| 70 | |
| 71 | Only the most recent version of an interface needs to be implemented. |
| 72 | Other versions are handled by having thunks convert their parameters |
| 73 | and call the root version. |
| 74 | |
| 75 | Not all interface versions have thunks. Some versions could be combined |
| 76 | because their parameters were compatible. For example if a structure |
| 77 | changes but the structure has a dwSize field, methods using that structure |
| 78 | are compatible, as long as the implementation remembers to take the dwSize |
| 79 | into account. |
| 80 | |
| 81 | Interface thunks for Direct3D are more complicated since the paradigm |
| 82 | changed between versions. |
| 83 | |
| 84 | |
| 85 | * Logical Object Layout |
| 86 | |
| 87 | The objects are split into the generic part (essentially the fields for |
| 88 | Main) and a private part. This is necessary because some objects |
| 89 | can be created with CoCreateInstance, then Initialized later. Only |
| 90 | at initialisation time do we know which class to use. Each class |
| 91 | except Main declares a Part structure and adds that to its Impl. |
| 92 | |
| 93 | For example, the DIBTexture DirectDrawSurface implementation looks |
| 94 | like this: |
| 95 | |
| 96 | struct DIBTexture_DirectDrawSurfaceImpl_Part |
| 97 | { |
| 98 | union DIBTexture_data data; /*declared in the real header*/ |
| 99 | }; |
| 100 | |
| 101 | typedef struct |
| 102 | { |
| 103 | struct DIB_DirectDrawSurfaceImpl_Part dib; |
| 104 | struct DIBTexture_DirectDrawSurfaceImpl_Part dibtexture; |
| 105 | } DIBTexture_DirectDrawSurfaceImpl; |
| 106 | |
| 107 | So the DIBTexture surface class is derived from the DIB surface |
| 108 | class and it adds one piece of data, a union. |
| 109 | |
| 110 | Main does not have a Part structure. Its fields are stored in |
| 111 | IDirectDrawImpl/IDirectDrawSurfaceImpl. |
| 112 | |
| 113 | To access private data, one says |
| 114 | |
| 115 | DIBTexture_DirectDrawSurfaceImpl* priv = This->private; |
| 116 | do_something_with(priv->dibtexture.data); |
| 117 | |
| 118 | |
| 119 | * Creating Objects |
| 120 | |
| 121 | Classes have two functions relevant to object creation, Create and |
| 122 | Construct. To create a new object, the class' Create function is |
| 123 | called. It allocates enough memory for IDirectDrawImpl or |
| 124 | IDirectDrawSurfaceImpl as well as the private data for derived |
| 125 | classes and then calls Construct. |
| 126 | |
| 127 | Each class's Construct function calls the base class's Construct, |
| 128 | then does the necessary initialization. |
| 129 | |
| 130 | For example, creating a primary surface with the user ddraw driver |
| 131 | calls User_DirectDrawSurface_Create which allocates memory for the |
| 132 | object and calls User_DirectDrawSurface_Construct to initialize it. |
| 133 | This calls DIB_DirectDrawSurface_Construct which calls |
| 134 | Main_DirectDrawSurface_Construct. |