I apologize if what I'm about to say is wrong and useless. I feel the need to say it just in case it is not as wrong and useless as I fear.
Background:
We have two very difficult (possibly unfixable) ddraw bugs:
http://bugs.winehq.org/show_bug.cgi?id=2082 - DirectDraw games only showing black screen
http://bugs.winehq.org/show_bug.cgi?id=1347 - Screen is wiped/blanked on usage of DirectDraw
Both of these bugs are the result of the fact that Windows (probably even Windows Vista when Aero is disabled, which I believe happens temporarily when an exclusive move ddraw app is active) ddraw can give apps direct access to the screen and X cannot.
Instead of drawing to the screen, Wine draws to the application's window, which it determines based on an argument the application passed to SetCooperativeLevel. In the case of 2082, this window is obscured and no drawing happens even though it would on windows. There is a hack for ddraw that uses hwnd 0 instead (so drawing operations do go to the screen), but it can also break things in situations where an application uses both ddraw and gdi.
1347 is the result of non-fullscreen applications passing hwnd 0 to SetCooperativeLevel and (so I'm told) going through this series of steps: 1. Lock the primary surface, thus mapping the image on the screen to memory. 2. Write to your window. 3. Unlock the primary surface.
On Windows, as long as Aero isn't running, this works out fine. But on Wine, mapping the image on the screen to memory is impossible. Instead, Wine simply gives the app an empty buffer, which the app writes to (but only its own window). It is impossible to determine afterwards which parts of the that buffer were written. When the primary surface is unlocked, Wine draws the image in the buffer to the application's SCL window, which is often (but not always) what the application happened to be drawing.
Stefan mentions the idea of grabbing a screenshot when the surface is locked and writing it back when the surface is unlocked (which he says in one case would cause framerate to drop to less than 1 fps, which I believe).
He thinks 1347 is unfixable. I think that if so, 2082 is also unfixable because even in fullscreen mode we can have problems caused by interactions with ddraw and gdi (using hwnd 0 is not always the right thing even for a fullscreen app).
Now, here's where we get to the crazy uninformed ideas:
What if, instead of picking one hwnd to draw to, ddraw drew to every window owned by an application?
I'm making some assumptions here: it has to be possible to find the space occupied by "every window owned by an application" and draw to it at a reasonable speed. I'm also assuming that no app we want to support will want to draw to windows owned by other programs, especially X programs, even though there's nothing in ddraw that would prevent it.
Well, we'd still theoretically have some problems. What if a program locked/unlocked the primary surface multiple times, once for each of various widgets that it wants to draw? The widgets would flicker. And what if a program has its own window that it wants to draw to with gdi? Its gdi parts would be painted black.
Alright then, what if we had a single clientside buffer per app, the size and depth (as far as the app is concerned) of the screen, that was not synced with the actual contents of the screen but was preserved between locks/unlocks? Any operation in ddraw or gdi that resulted in a draw to the screen would have to first go through this buffer. The lock/unlock sequence would overdraw all the application's windows with the last thing the application drew there.
Ignoring opengl (opengl and ddraw working simultaneously in one process should be extremely rare; maybe some swing apps do it), that should work pretty much perfectly. Sadly I can't even pretend to know enough to say how this affects opengl.
It would require clientside buffers, and it would probably be difficult for current gdi to support. It seems like the sort of thing that would be more reasonable if we had a dib engine. (!)
Also, giving every process a clientside buffer the size of the screen would be wasteful of memory (and optimizing for a rare case; most programs won't even have a primary surface, let along be locking/unlocking it). It may be more reasonable to have one per visible window or even one per X window, which would be manipulated as needed for lock/unlock (not sure about the X window thing because they'd have to be shared between processes.. but perhaps we need that capability anyway? it would also effectively mean we CAN give apps direct access to the screen for virtual desktops and CAN allow ddraw drawing to other Wine processes' windows).