Search code examples
c++dllwxwidgetsxuldirect3d

Initializing D3D9 causes a 3rd-party library to stop working


First, the general situation... a 3rd-party library loaded through a DLL does rendering into a HWND. It's simple 2D rendering and is not directly using D3D in a way I can see - a dependency walk on the DLL shows lots of D3DKMT functions like D3DKMTCreateDevice but not regular D3D calls like IDirect3D9::CreateDevice. When I call IDirect3D9::CreateDevice, the 3rd-party rendering goes screwy. It doesn't complain, but simply renders everything as black rectangles. My own rendering works fine.

The specifics... the 3rd-party DLL is Mozilla XULRunner 1.9.x, which is the core of FireFox (not 2.0 which features hardware acceleration), wrapped in the wxWidgets wxWebConnect library. wxWC loads the XUL DLL and provides a web-browser GUI component.

I have a working app using wx & wxWebConnect here, a compiled EXE and the code: http://www.kirix.com/forums/viewtopic.php?f=25&t=911#p2605

Here is my real-life code, it's slightly bound to wxWidgets but not enough to make it hard to read - I get a HWND from a random window simply to initialize D3D but never render to it:

void MyFrame::OnD3DButton( wxCommandEvent &event )
{
    static bool initialized = false;
    static LPDIRECT3D9 mpD3D = NULL;
    static LPDIRECT3DDEVICE9 mpD3DDevice=NULL;
    if(!initialized)
    {
        wxButton *button=wxDynamicCast(event.GetEventObject(), wxButton);
        HWND mHWnd = (HWND)button->GetHandle();
        mpD3D = Direct3DCreate9(D3D_SDK_VERSION);

        D3DPRESENT_PARAMETERS md3dpp;
        ZeroMemory( &md3dpp, sizeof(D3DPRESENT_PARAMETERS) );
        md3dpp.Windowed                 = true;
        md3dpp.SwapEffect               = D3DSWAPEFFECT_DISCARD;
        // triple buffer if VSync is on
        md3dpp.BackBufferCount          = 1;
        md3dpp.EnableAutoDepthStencil   = 0;
        md3dpp.hDeviceWindow            = mHWnd;
        md3dpp.BackBufferWidth          = 0;
        md3dpp.BackBufferHeight         = 0;
        md3dpp.FullScreen_RefreshRateInHz = 0;
        md3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
        md3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
        md3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
        md3dpp.MultiSampleQuality = 0;

        HRESULT hr = mpD3D->CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,mHWnd,
            D3DCREATE_MULTITHREADED|D3DCREATE_MIXED_VERTEXPROCESSING,&md3dpp,&mpD3DDevice);
        if(FAILED(hr))
            wxMessageBox(wxString("mpD3D->CreateDevice() FAILED"));
        else
        {
            wxMessageBox(wxString("mpD3D->CreateDevice() SUCCEEDED"));
            initialized = true;
        }
    }

}

Solution

  • The problem might be that CreateDevice will modify the FPU state unless you pass the flag D3DCREATE_FPU_PRESERVE. It took me a really long time to find this when it bit me.