Hello,
I am a contractor for a company in the UK. I have developed a 3D module for an oil reservoir visualisation program on Windows that is now required to run on Linux. The Wine port has been very successful (it started a month or so ago), but I'm having a couple of DirectX-related problems. We're using DirectX 9, the LinuxOS is Fedora Core 6, the Wine version is 0.9.32, and we're only using the binary loader, i.e. we're simply running our Windows executable under Wine.
The problems I'm having relate to calling IDirect3DSurface9::GetDC() on an offscreen surface, which doesn't appear to work, and to calling IDirect3DDevice9::CreateStateBlock() with D3DSBBT_ALL, which appears to hang the program. I've had a look in the bug lists, but I didn't see anything relating to these issues. I'd greatly appreciate any information anyone has on these two issues. I'd also appreciate any information on how the DirectX to OpenGL translation is implemented. For example, does Wine use hardware-accelerated OpenGL?
Our program was initially affected by Wine bug 2398, i.e. the bug that causes the OpenGL window to occupy the whole application window. We got round this by first rendering to an offscreen surface, copying the offscreen surface to a bitmap, and then blitting the bitmap to the window. It is of course slower but its acceptable for us and gives us nice MDI behaviour under Wine. However, since we mix DirectX and GDI, we would like to use GetDC() on the offscreen surface. This isn't crucial, but among other things it would allow us to blit the offscreen surface into the bitmap, rather than using IDirect3DSurface9::LockRect() and copying it pixel by pixel as we're doing at the moment.
Thanks,
Robert Fairlie
Am Donnerstag 26 April 2007 12:28 schrieb Robert Fairlie:
Hello,
I am a contractor for a company in the UK. I have developed a 3D module for an oil reservoir visualisation program on Windows that is now required to run on Linux. The Wine port has been very successful (it started a month or so ago), but I'm having a couple of DirectX-related problems. We're using DirectX 9, the LinuxOS is Fedora Core 6, the Wine version is 0.9.32, and we're only using the binary loader, i.e. we're simply running our Windows executable under Wine.
The problems I'm having relate to calling IDirect3DSurface9::GetDC() on an offscreen surface,
Do not use GetDC. This is a bad idea, especially in wine. This call is implemented only very rudimentarily. If you do what you are doing here, the the following happens: Then LockRect is called to download the opengl render target to the DIB secion. On the BitBlt, the DIB section is converted to the X server's color depth, then sent to the X server via shared memory which handles the Blit. The very first call creates a DIB section for the surface, which is destroyed when the surface is destroyed. However, I have never tested it for offscreen surfaces.
The whole issue is a huge PITA though. I think a more efficient way(but still very slow) would be to render to an offscreen surface or the back buffer, then use StretchRect to copy it to a texture and Lock the texture. If possible, do some other work between the stretchrect and the lock, because lock forces a gpu-cpu synchronisation. If you're rendering to the back buffer you should, if possible, render upside down and do an upside down stretch, if you render to an offscreen surface wined3d does the upside down thing for you. Thats because glCopyTexSubImage, which we use for the framebuffer -> texture copy, copies upside down, and unless the app orders an upside down copy we have to copy line by line. Also avoid StretchRect parameters that require the surface to be Stretched(just do a 1:1 copy). The blit the downloaded memory to the window. The mail gain of this is that wined3d knows you're locking the surface read only. If you use GetDC we don't know that and on ReleaseDC we upload the surface from the DIB section back to opengl because it may have been modified.
To answer your question about the general implementation of d3d: Yes, we do use hardware accelerated OpenGL, in fact we just call the opengl implementation that is present on the Linux system. Certain operations can't be mapped directly to opengl, like GetDC. I'm having plans to implement various GDI functions on top of opengl, but those are just plans.
Another *ugly* way may be to render to the back buffer and call glCopyPixels from your program. If you're using d3d in wine you have an opengl context active, so technically you can just do opengl calls. This avoids copying the frame buffer to system memory, but I don't know if glCopyPixels leaves the rest of the window intact. Furthermore you'd have to calculate the correct offset based on wine's bug.
As for the stateblock I have no idea what could go wrong. It would be interesting to follow the call into the wine code and find the line that crashes.
Our program was initially affected by Wine bug 2398, i.e. the bug that causes the OpenGL window to occupy the whole application window.
I forgot to mention this in my first mail, but Roderick Colenbrandner is working on a patch that is supposed to fix the child window issue at its root. Basically it creatses an X11 child window for the opengl target, thus the gl rendering goes where it is supposed to go. It is only targetet at fixing opengl apps for now, but it should be easilly extensible to fix d3d apps too.
The patch works in general, but it has some nasty issues left. Moving windows or gl rendering to grandchildren, or if the X11 child window is supposed to be covered by another window.