Lecture time
The main problem is that we must use ExternMFD, and ExternMFD can only draw to its own surface, not to an user-supplied surface. This forces us to copy image data from one surface to the other on display update.
The most basic way to do this is to acquire GDI contexts on both surfaces and call BitBlt(). BitBlt() is slow, but that's only half of the problem. The other half is that BitBlt() invokes some kind of a global mutex, and locks the renderer -- so running it in a separate thread will do no good. So if your call to BitBlt() takes, say 200ms, this means that the renderer is locked for 200ms, which results in a jerking animation once per second.
Strangely enough, speed of BitBlt() seems to depend on circumstances -- in SlaveMFD, a copy between two surfaces is much faster than a copy between a surface and a bitmap in VNCMFD. This is why I said that I am surprised that this add-on works -- in VNCMFD, one refresh would take on the order of 200ms. Of course having a renderer frozen for 200ms results in a visibly jerky animation (to put it mildly). Which is why early versions of VNCMFD were using progressive scan, i.e. copying 1/10th of MFD screen at a time. It appears that this is not needed here, for some reason.
At one point,
csanders made this discovery that (in the inline client) SURFHANDLE is nothing else than a pointer to a DX7 surface objects. (In other words, SURFHANDLE is LPDIRECTDRAWSURFACE7). So you can actually use DX7 calls to manipulate SURFHANDLES. In particular, you can use DX7 blitting which is much faster than BitBlt. Hence WebMFD and VNCMFD got accelerated versions.
So, of course that this add-on can be improved -- I just have to figure out a way how to do fast blitting from LPDIRECTDRAWSURFACE7 to physical display. There's no sense in involving DX7 calls if I have to go through GDI at the end again :rofl: So far, I know that the most obvious thing -- oapiBlt() with MFD display as the target -- does NOT work (at least with 2D cockpit), which is, frankly, puzzling.
To make matters more interesting, BitBlt() under D3D9Client is blazingly fast, and does not require any special tricks.
So there's actually a good chance that you can make a playable "mission control" VC using SlaveMFD as it stands now, provided that you use D3D9Client.
---------- Post added at 06:49 PM ---------- Previous post was at 06:20 PM ----------
And this is why BitBlt() under D3D9Client is faster:
DX7 is still hardware accelerated. What isn't hardware accelerated is getting a GDI surface from DX7. DirectX/GDI interop isn't a common thing, and support for this was dropped from DX7 but continued in DX9.
I suspect an non-hardware accelerated GDI bitblt is the issue. I think it used to be accelerated on XP (at least if it didn't have to do a stretch (i.e. the source and destination resolutions were equal)), but no longer with Vista.
In any case, I discovered the inline client actually gives a pointer to DX7 surface with the "GetSurface" API call. From there one can do a DX7 bitblt, which is accelerated, but I digress.