D3dCreateSurfaceEx Handles and Flip

DirectDraw surface structures are designed to represent conceptual surfaces, not necessarily specific locations in video memory. The main usage of this abstraction is in a primary flipping chain, where the application uses one constant surface object to represent the back buffer, even though the back buffer may be moving around in video memory as a result of the DdFlip function.

The DdFlip function takes a ring of surfaces, and sequentially reassigns their video memory pointers around this ring. In the particular case of two surface objects, the process is reduced to trading their video memory pointers. In addition, the DirectDraw runtime also rotates the D3dCreateSurfaceEx handles associated with each surface, and the driver-owned contents of the dwReserved1 members of each surface. This behavior has some interesting consequences for a DirectX 7.0 driver, and effectively rules out the embedding of pointers to DirectDraw surface structures inside the driver's own surface structures.

Consider two surface objects, A and B, that have associated handles HA and HB, and fpVidMem (a member of the DD_SURFACE_GLOBAL structure) values of FA and FB. Further, suppose that the application is using surface structure A to refer to the back buffer of a flipping chain. At DdFlip time, the handles and both fpVidMem values are swapped, so that surface A has HB and FB, and surface B has HA and FA. The application now tries to draw to the back buffer, surface A, which should represent the video memory at FB (because the application initiated a call to DdFlip).

A drawing command is issued to the driver, which looks up the handle associated with that surface (which is now HB, not HA). What would happen if the driver merely stores a pointer to the DirectDraw surface structure? The driver looks up HB, then follows the stored pointer to surface B, which now has an fpVidMem value of FA. Drawing begins on the video memory at FA. This is not what the application is expecting. If, on the other hand, the driver stores surface data in its own structures, rather than following a pointer to the DirectDraw surface structure, then HB still resolves to FB, and drawing occurs on the correct surface. This latter case is the way the current DDI is implemented.