Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I'm trying to render multiple windows, using DirectX 9 and swap chains, but even though I create 2 windows, I only see the first one that I've created. My RendererDX9 header is this:

#include <d3d9.h>
#include <Windows.h>
#include <vector>

#include "RAT_Renderer.h"

namespace RAT_ENGINE
{
    class RAT_RendererDX9 : public RAT_Renderer
    {
    public:
        RAT_RendererDX9();
        ~RAT_RendererDX9();

        void Init(RAT_WindowManager* argWMan);
        void CleanUp();

        void ShowWin();


    private:
        LPDIRECT3D9           renderInterface; // Used to create the D3DDevice
        LPDIRECT3DDEVICE9     renderDevice;    // Our rendering device
        LPDIRECT3DSWAPCHAIN9* swapChain;       // Swapchain to make multi-window rendering possible
        WNDCLASSEX wc;

        std::vector<HWND> hwindows;

        void Render(int argI);
    };
}

And my .cpp file is this:

#include "RAT_RendererDX9.h"


static LRESULT CALLBACK MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam );


namespace RAT_ENGINE
{
    RAT_RendererDX9::RAT_RendererDX9() : renderInterface(NULL), renderDevice(NULL)
    {
    }

    RAT_RendererDX9::~RAT_RendererDX9()
    {
    }

    void RAT_RendererDX9::Init(RAT_WindowManager* argWMan)
    {   
        wMan = argWMan;
        // Register the window class
        WNDCLASSEX windowClass =
        {
            sizeof( WNDCLASSEX ), CS_CLASSDC, MsgProc, 0, 0,
            GetModuleHandle( NULL ), NULL, NULL, NULL, NULL,
            "foo", NULL
        };

        wc = windowClass;

        RegisterClassEx( &wc );

        for (int i = 0; i< wMan->getWindows().size(); ++i)
        {
            HWND hWnd = CreateWindow( "foo", argWMan->getWindow(i)->getName().c_str(),
                                    WS_OVERLAPPEDWINDOW, argWMan->getWindow(i)->getX(), argWMan->getWindow(i)->getY(), 
                                    argWMan->getWindow(i)->getWidth(), argWMan->getWindow(i)->getHeight(),
                                    NULL, NULL, wc.hInstance, NULL );
            hwindows.push_back(hWnd);
        }

        // Create the D3D object, which is needed to create the D3DDevice.
        renderInterface = (LPDIRECT3D9)Direct3DCreate9( D3D_SDK_VERSION );

        // Set up the structure used to create the D3DDevice. Most parameters are
        // zeroed out. We set Windowed to TRUE, since we want to do D3D in a
        // window, and then set the SwapEffect to "discard", which is the most
        // efficient method of presenting the back buffer to the display.  And 
        // we request a back buffer format that matches the current desktop display 
        // format.
        D3DPRESENT_PARAMETERS deviceConfig;
        ZeroMemory( &deviceConfig, sizeof( deviceConfig ) );
        deviceConfig.Windowed = TRUE;
        deviceConfig.SwapEffect = D3DSWAPEFFECT_DISCARD;
        deviceConfig.BackBufferFormat = D3DFMT_UNKNOWN;
        deviceConfig.BackBufferHeight = 1024;
        deviceConfig.BackBufferWidth = 768;
        deviceConfig.EnableAutoDepthStencil = TRUE;
        deviceConfig.AutoDepthStencilFormat = D3DFMT_D16;

        // Create the Direct3D device. Here we are using the default adapter (most
        // systems only have one, unless they have multiple graphics hardware cards
        // installed) and requesting the HAL (which is saying we want the hardware
        // device rather than a software one). Software vertex processing is 
        // specified since we know it will work on all cards. On cards that support 
        // hardware vertex processing, though, we would see a big performance gain 
        // by specifying hardware vertex processing.
        renderInterface->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwindows[0],
                              D3DCREATE_SOFTWARE_VERTEXPROCESSING,
                              &deviceConfig, &renderDevice );

        this->swapChain = new LPDIRECT3DSWAPCHAIN9[wMan->getWindows().size()];
        this->renderDevice->GetSwapChain(0, &swapChain[0]);

        for (int i = 0; i < wMan->getWindows().size(); ++i)
        {
            renderDevice->CreateAdditionalSwapChain(&deviceConfig, &swapChain[i]);  
        }

        renderDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW); // Set cullmode to counterclockwise culling to save resources
        renderDevice->SetRenderState(D3DRS_AMBIENT, 0xffffffff);   // Turn on ambient lighting
        renderDevice->SetRenderState(D3DRS_ZENABLE, TRUE);         // Turn on the zbuffer
    }

    void RAT_RendererDX9::CleanUp()
    {
        renderDevice->Release();
        renderInterface->Release();
    }

    void RAT_RendererDX9::Render(int argI)
    {
        // Clear the backbuffer to a blue color
        renderDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB( 0, 0, 255 ), 1.0f, 0 );
        LPDIRECT3DSURFACE9 backBuffer = NULL;

        // Set draw target
        this->swapChain[argI]->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &backBuffer);
        this->renderDevice->SetRenderTarget(0, backBuffer);

        // Begin the scene
        renderDevice->BeginScene();

        // End the scene
        renderDevice->EndScene();
        swapChain[argI]->Present(NULL, NULL, hwindows[argI], NULL, 0);
    }   

    void RAT_RendererDX9::ShowWin()
    {
        for (int i = 0; i < wMan->getWindows().size(); ++i)
        {
            ShowWindow( hwindows[i], SW_SHOWDEFAULT );
            UpdateWindow( hwindows[i] );

            // Enter the message loop
            MSG msg;
            while( GetMessage( &msg, NULL, 0, 0 ) )

            {
                if (PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) )
                {
                TranslateMessage( &msg );
                DispatchMessage( &msg );
                }
                else
                {
                    Render(i);
                }
            }
        }
    }
}

LRESULT CALLBACK MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
    switch( msg )
    {
        case WM_DESTROY:
            //CleanUp();
            PostQuitMessage( 0 );
            return 0;

        case WM_PAINT:
            //Render();
            ValidateRect( hWnd, NULL );
            return 0;
    }

    return DefWindowProc( hWnd, msg, wParam, lParam );
}

I've made a sample function to make multiple windows:

void RunSample1()
{
    //Create the window manager.
    RAT_ENGINE::RAT_WindowManager* wMan = new RAT_ENGINE::RAT_WindowManager();

    //Create the render manager.
    RAT_ENGINE::RAT_RenderManager* rMan = new RAT_ENGINE::RAT_RenderManager();

    //Create a window.
    //This is currently needed to initialize the render manager and create a renderer.
    wMan->CreateRATWindow("Sample 1 - 1", 10, 20, 640, 480);
    wMan->CreateRATWindow("Sample 1 - 2", 150, 100, 480, 640);

    //Initialize the render manager.
    rMan->Init(wMan);

    //Show the window.
    rMan->getRenderer()->ShowWin();
}

How do I get the multiple windows to work?

share|improve this question
2  
This question appears to be off-topic because it is about debugging your code for you. –  Anko Sep 17 '13 at 7:38

1 Answer 1

This is documented on MSDN at: "Presenting Multiple Views in Windowed Mode (Direct3D 9)":

The application typically creates one swap chain per view by using the IDirect3DDevice9::CreateAdditionalSwapChain method, and associates each swap chain with a particular window.

What you're missing in your code is the "associates each swap chain with a particular window" part - when you call CreateAdditionalSwapChain you're still using the same present parameters as you used for the original Device and it's implicit swap chain; i.e. all of your swap chains are associated with the same window.

So to fix this you need to set the hDeviceWindow member of your present parameters to the HWND of the window that each swap chain is to be associated with before you call CreateAdditionalSwapChain.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.