0

I am in the process of teaching myself DirectX development while going through all the tutorials on http://directxtutorial.com/. I have run into a problem that I believe is related to me having multiple monitors.

My display is 1920 x 1080. When my code runs in its current state my primary monitor becomes black with the cursor in the middle. When I set my SCREEN defines at the top of my code to 1920 x 1080 my program runs fine and displays my sprite with the navy background. When I leave the SCREEN defines as 1440 x 900 and disable my second monitor my program runs fine. This is what leads me to believe there is some issue with my second monitor hosing up things.

Any help would be appreciated!

Below is my current code:

    // include the basic windows header files and the Direct3D header file
    #include <windows.h>
    #include <windowsx.h>
    #include <d3d9.h>
    #include <d3dx9.h>

    // define the screen resolution and keyboard macros
    #define SCREEN_WIDTH  1440
    #define SCREEN_HEIGHT 900
    #define KEY_DOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)
    #define KEY_UP(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1)

    // include the Direct3D Library file
    #pragma comment (lib, "d3d9.lib")
    #pragma comment (lib, "d3dx9.lib")

    // global declarations
    LPDIRECT3D9 d3d;    // the pointer to our Direct3D interface
    LPDIRECT3DDEVICE9 d3ddev;    // the pointer to the device class
    LPD3DXSPRITE d3dspt;    // the pointer to our Direct3D Sprite interface
    BOOL stimToggle = TRUE;

    // sprite declarations
    LPDIRECT3DTEXTURE9 sprite;    // the pointer to the sprite

    // function prototypes
    void initD3D(HWND hWnd); // sets up and initializes Direct3D
    void render_frame(void); // renders a single frame
    void cleanD3D(void); // closes Direct3D and releases memory
    void init_input(HWND hWnd);

    // the WindowProc function prototype
    LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);


    // the entry point for any Windows program
    int WINAPI WinMain(HINSTANCE hInstance,
                       HINSTANCE hPrevInstance,
                       LPSTR lpCmdLine,
                       int nCmdShow)
    {
        HWND hWnd;
        WNDCLASSEX wc;

        ZeroMemory(&wc, sizeof(WNDCLASSEX));

        wc.cbSize = sizeof(WNDCLASSEX);
        wc.style = CS_HREDRAW | CS_VREDRAW;
        wc.lpfnWndProc = (WNDPROC)WindowProc;
        wc.hInstance = hInstance;
        wc.hCursor = LoadCursor(NULL, IDC_ARROW);
        wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
        wc.lpszClassName = L"WindowClass1";

        RegisterClassEx(&wc);

        hWnd = CreateWindowEx(NULL,
                              L"WindowClass1",
                              L"Our Direct3D Program",
                              WS_EX_TOPMOST | WS_POPUP,
                              0, 0,
                              SCREEN_WIDTH, SCREEN_HEIGHT,
                              NULL,
                              NULL,
                              hInstance,
                              NULL);

        ShowWindow(hWnd, nCmdShow);

        // set up and initialize Direct3D
        initD3D(hWnd);
        init_input(hWnd);

        // enter the main loop:

        MSG msg;

        while(TRUE)
        {
            //DWORD starting_point = GetTickCount();

            if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
            {
                if (msg.message == WM_QUIT)
                    break;

                TranslateMessage(&msg);
                DispatchMessage(&msg);
            }

            render_frame();

            // check the 'escape' key
            if(KEY_DOWN(VK_ESCAPE))
                PostMessage(hWnd, WM_DESTROY, 0, 0);

            //while ((GetTickCount() - starting_point) < 25);
        }

        // clean up DirectX and COM
        cleanD3D();

        return msg.wParam;
    }


    // this is the main message handler for the program
    LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
        switch(message)
        {
            case WM_DESTROY:
                {
                    PostQuitMessage(0);
                    return 0;
                } break;
            case WM_INPUT:
                {
                    RAWINPUT InputData;

                    UINT DataSize = sizeof(RAWINPUT);
                    GetRawInputData((HRAWINPUT)lParam,
                                    RID_INPUT,
                                    &InputData,
                                    &DataSize,
                                    sizeof(RAWINPUTHEADER));

                    // set the mouse button status
                    if(InputData.data.mouse.usButtonFlags == RI_MOUSE_LEFT_BUTTON_DOWN)
                        stimToggle = FALSE;
                    if(InputData.data.mouse.usButtonFlags == RI_MOUSE_LEFT_BUTTON_UP)
                        stimToggle = TRUE;

                    return 0;
                } break;
        }

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


    // this function initializes and prepares Direct3D for use
    void initD3D(HWND hWnd)
    {
        d3d = Direct3DCreate9(D3D_SDK_VERSION);

        D3DPRESENT_PARAMETERS d3dpp;

        ZeroMemory(&d3dpp, sizeof(d3dpp));
        d3dpp.Windowed = FALSE;
        d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
        d3dpp.hDeviceWindow = hWnd;
        d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
        d3dpp.BackBufferWidth = SCREEN_WIDTH;
        d3dpp.BackBufferHeight = SCREEN_HEIGHT;
        d3dpp.BackBufferCount = 1;
        d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
        d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
        d3dpp.EnableAutoDepthStencil = FALSE;

        // create a device class using this information and the info from the d3dpp stuct
        d3d->CreateDevice(D3DADAPTER_DEFAULT,
                          D3DDEVTYPE_HAL,
                          hWnd,
                          D3DCREATE_SOFTWARE_VERTEXPROCESSING,
                          &d3dpp,
                          &d3ddev);


        D3DXCreateSprite(d3ddev, &d3dspt);    // create the Direct3D Sprite object

        D3DXCreateTextureFromFileEx(d3ddev,    // the device pointer
                                    L"ast_sprite.png",    // the new file name
                                    D3DX_DEFAULT,    // default width
                                    D3DX_DEFAULT,    // default height
                                    D3DX_DEFAULT,    // no mip mapping
                                    NULL,    // regular usage
                                    D3DFMT_A8R8G8B8,    // 32-bit pixels with alpha
                                    D3DPOOL_MANAGED,    // typical memory handling
                                    D3DX_DEFAULT,    // no filtering
                                    D3DX_DEFAULT,    // no mip filtering
                                    D3DCOLOR_XRGB(0, 0, 128),    // the hot-pink color key
                                    NULL,    // no image info struct
                                    NULL,    // not using 256 colors
                                    &sprite);    // load to sprite

        return;
    }


    // this is the function used to render a single frame
    void render_frame(void)
    {
        // clear the window to a deep blue
        d3ddev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 128), 1.0f, 0);

        if(stimToggle)
        {
            d3ddev->BeginScene();    // begins the 3D scene
            d3dspt->Begin(D3DXSPRITE_ALPHABLEND);    // begin sprite drawing

            D3DSURFACE_DESC surfaceDesc;
            sprite->GetLevelDesc(NULL, &surfaceDesc); 

            // draw the sprite
            D3DXVECTOR3 center(surfaceDesc.Width / 2.0f, surfaceDesc.Height / 2.0f, 0.0f);    // center at the upper-left corner
            D3DXVECTOR3 position(SCREEN_WIDTH / 2.0f, SCREEN_HEIGHT / 2.0f, 0.0f);    // position at 50, 50 with no depth
            d3dspt->Draw(sprite, NULL, &center, &position, D3DCOLOR_XRGB(255, 255, 255));

            d3dspt->End();    // end sprite drawing
            d3ddev->EndScene();    // ends the 3D scene
        }

        d3ddev->Present(NULL, NULL, NULL, NULL);

        return;
    }

    // this is the function that initializes the Raw Input API
    void init_input(HWND hWnd)
    {
        RAWINPUTDEVICE Mouse;
        Mouse.usUsage = 0x02;    // register mouse
        Mouse.usUsagePage = 0x01;    // top-level mouse
        Mouse.dwFlags = NULL;    // flags
        Mouse.hwndTarget = hWnd;    // handle to a window

        RegisterRawInputDevices(&Mouse, 1, sizeof(RAWINPUTDEVICE));    // register the device
    }

    // this is the function that cleans up Direct3D and COM
    void cleanD3D(void)
    {
        sprite->Release();
        d3ddev->Release();
        d3d->Release();

        return;
    }

EDIT: Here is my debug information from my Output window.

Direct3D9: (INFO) :======================= Hal SWVP device selected

Direct3D9: (INFO) :HalDevice Driver Style b

Direct3D9: :Subclassing window 00680b0a
Direct3D9: :StartExclusiveMode
Direct3D9: :WM_DISPLAYCHANGE: 1440x900x32
Direct3D9: (ERROR) :Lost due to display uniqueness change
Prototype.exe has triggered a breakpoint.

This is where it triggers the breakpoint. When I click continue, the rest of the below is displayed.

Direct3D9: (INFO) :Using FF to PS converter

Direct3D9: (INFO) :Enabling multi-processor optimizations
Direct3D9: (INFO) :DDI threading started

Direct3D9: (INFO) :Using FF to VS converter in software vertex processing

Direct3D9: (ERROR) :************************************************************
Direct3D9: (ERROR) :ASSERTION FAILED! File s:\gfx_aug09\windows\directx\dxg\inactive\d3d9\d3d\fw\lhbatchfilter.cpp Line 3466: pArgs->Flags.Discard
Direct3D9: (ERROR) :************************************************************
Direct3D9: (ERROR) :************************************************************
Direct3D9: (ERROR) :ASSERTION FAILED! File s:\gfx_aug09\windows\directx\dxg\inactive\d3d9\d3d\fw\lhbatchfilter.cpp Line 3466: pArgs->Flags.Discard
Direct3D9: (ERROR) :************************************************************
Direct3D9: (ERROR) :************************************************************
Direct3D9: (ERROR) :ASSERTION FAILED! File s:\gfx_aug09\windows\directx\dxg\inactive\d3d9\d3d\fw\lhbatchfilter.cpp Line 3466: pArgs->Flags.Discard
Direct3D9: (ERROR) :************************************************************
D3D9 Helper: Warning: Default value for D3DRS_POINTSIZE_MAX is 2.19902e+012f, not 4.16345e-316f.  This is ok.
Direct3D9: :WM_ACTIVATEAPP: BEGIN Activating app pid=00003c58, tid=00005888
Direct3D9: :*** Active state changing
Direct3D9: :WM_ACTIVATEAPP: DONE Activating app pid=00003c58, tid=00005888
Direct3D9: :WM_ACTIVATEAPP: BEGIN Activating app pid=00003c58, tid=00005888
Direct3D9: :*** Already activated
Direct3D9: :WM_ACTIVATEAPP: DONE Activating app pid=00003c58, tid=00005888
Direct3D9: :WM_ACTIVATEAPP: BEGIN Activating app pid=00003c58, tid=00005888
Direct3D9: :*** Already activated
Direct3D9: :WM_ACTIVATEAPP: DONE Activating app pid=00003c58, tid=00005888
Brandon
  • 261
  • 1
  • 7
  • 17

1 Answers1

1
  1. Identify which monitor is primary monitor, by default, DirectX will output to the primary monitor.

  2. Make sure the resolution you set is available for the monitor you are rendering to. if you use an unsupported resolution, DirectX will failed when creating device.

[Edit], use the following code if you don't want to hard-code the screen resolution.

    // Get max display resolution and set it as back buffer size

    D3DDISPLAYMODE displayMode ;
    d3d->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &displayMode) ;

    int width = displayMode.Width;
    int height = displayMode.Height;

    d3dpp.BackBufferWidth = width;
    d3dpp.BackBufferHeight = height;
  1. Turn on debug mode, since you are using DirectX 9.0, this can be simply done by using DirectX control panel, it is C:\Program Files\Microsoft DirectX SDK (June 2010)\Utilities\bin\x86\dxcpl.exe, this might be a different if you install DirectX SDK in another location. with debug mode turn on, you will get lots of helpful information in the output window which will help you to solve most of your problems.

enter image description here

zdd
  • 7,560
  • 8
  • 34
  • 71
  • Thanks for the reply! Are all the resolutions listed on "Screen resolution" from the Windows desktop "supported"? Also by "output window" do you mean my output Windows in MSVS? I tried turning on that debugging but I didn't see anything in VS. Maybe I did it wrong? – Brandon Sep 20 '13 at 03:50
  • 1. Yes, but, you should select the correct monitor in the drop down list. – zdd Sep 20 '13 at 06:23
  • 2. Yes, I mean the Visual Studio output window, you will get the debug output information when you met a error or doing something wrong with your code, for example, if you use an unsupported resolution you will got something like this [Direct3D9: (ERROR) :Display mode is unsupported] – zdd Sep 20 '13 at 06:26
  • 1
    @Brandon see my Edit please. – zdd Sep 20 '13 at 06:30
  • Thanks! I am having some weird results. When I run my code in debug mode as you mention above, it triggers a breakpoint but there is no error information. Here is a screenshot - http://i.imgur.com/yIIWMTK.png If I tell it to just continue ignoring the break, my program opens up just fine and my sprite is displayed on the expected navy background. If I turn DirectX back to "Retail" via the control panel my program goes back to the problematic black screen. Any ideas? Thanks again for your help! This is a learning process for me. – Brandon Sep 20 '13 at 15:56
  • I also verified the primary monitor display modes - http://i.imgur.com/FX2uAb7.png - I tried several beyond the one mentioned in my code above and all have produced the same results. – Brandon Sep 20 '13 at 15:59
  • 1
    @Brandon you should open the output window in your Visual Studio. from the picture I din't see the output window, I only see the call stack window. – zdd Sep 23 '13 at 02:25
  • 1
    @Brandon for the second picture, please note that the number 1 and 2 in your picture does not mean 1 is primary and 2 is secondary, you should check which monitor is primary from your graphics control panel(you can install that when installing the graphics drivers) – zdd Sep 23 '13 at 02:29
  • I will try your suggestions when I get into work tomorrow. For the sake of discussion, both my monitors are identical so which one is "primary" shouldn't matter, correct? – Brandon Sep 23 '13 at 03:27
  • 1
    @Brandon it matters. use the resolution of your primary monitor. – zdd Sep 23 '13 at 07:02
  • See my edits to the original question for my debug info. Any ideas? And just to reiterate it works fine when I set it to my monitors resolution, but my goal is to make my application go fullscreen at 1440 x 900 without issues. – Brandon Sep 23 '13 at 19:35
  • 1
    @Brandon can you also paste the code which you currently used now? I can have a try on my machine later. – zdd Sep 24 '13 at 02:03
  • The code above in my initial question provides the error information I pasted below it. Thanks! – Brandon Sep 24 '13 at 14:06