Hi,
One of our remaining fundamental d3d problems is the slowness of
IDirectDrawSurface7::GetDC(and d3d9). This call allows performing gdi
operations on surfaces. Currently this is handled through downloading the
opengl surface, performing the gdi operation, and uploading it again. This is
slow, especially on render targets. On textures this is rarely used, and
wined3d can better cache the texture.
Most applications use it to render text text on the back buffer. Applications
I have are the d3d7 sdk demos, Empire Earth, Prince of Persia 3D, Age of
Empires 2. Sometimes it is also used to load textures with a BitBlt.
I have discussed two ways of solving this issue with alexandre. One was to
tell the X server to perform the calls in opengl(EXT_texture_from_pixmap
looked promissing), the other one was writing an opengl gdi driver in
wined3d. The X server approach failed because there is just no API to get
that handled, and EXT_texture_from_pixmap explicitly doesn't do that job, and
even if there is a hacky way driver support will be bad. So I spent the last
days to check how an implementation in wined3d would work - and here it is.
So far this driver handles only ExtTextOutW, and I only successfully used it
with the directx sdk samples. ExtTextOut uses a Helper device context(normal
gdi) to get the glyphs with GetGlyphOutline, loads it into an opengl
texture(GL_ALPHA) and records 256 display lists to draw textured quads. So
far no unicode support, no custom pens, but custom fonts work. Attached are 2
screenshots of a dx7 sdk demo with classic getdc and the opengl driver(radeon
M9, 1.6 ghz pentium M, 512 mb ram). There seems to be some parameter missing,
the text is slightly displaced. Tex.gif is the created font texture(warning,
white text on transparent background)
One problem of this approach is that the driver has to handle everything.
However, I keep a DIB section of the size of the surface, and if I encounter
some unsupported call I can print a FIXME, download from gl and call the dib
section to do the job. After ReleaseDC the surface code has to upload it
again. Its the slow old behavior, so we don't gain anything for unsupported
calls, but its no loss either. So far most forward functions are missing, so
the DIB driver refuses to initialize itself - Edit CreateDC in
dlls/wined3d/gdi.c to activate it. ExtTextOut has an example how the
forwarding looks like.
A big problem I still have are operations that involve 2 device contexts.
Prince of Persia 3D(good test case for custom fonts) calls StretchBlit
from/to my gl dc. So in X11drv one of the physdevs is a WineD3DSurfaceImpl *
instead of a WINEX11DRV_PHSYDEV * - not good. So far I haven't found a way to
let x11drv access my surface data, or enforce that my function is called,
fetch the hdc from the x11 phsydev and call my fallback dc, or request the
device's content from x11drv and handle the blit myself.