Thread: Hardware acceleration on a secondary monitor

  1. #1
    Registered User
    Join Date
    Apr 2005
    Posts
    13

    Hardware acceleration on a secondary monitor

    Hi,

    I have been having performance problems with Direct3D when it comes to having rendering performed in a window created in a secondary monitor. It looks like I cannot get full hardware acceleration on that window.

    From my research on the net, people seem to be saying that all that is needed is to create the Direct3Device9 interface on that secondary display. I think that is what I am doing but hopefully someone here will pinpoint my mistake.

    I first create a window on the primary monitor to show some options. Once the user validates by pressing on the OK button I go through a routine to create a new window on the secondary monitor in which there will be some rendering using Direct3D.

    To do so, I call ::EnumDisplayDevices to obtain a pointer to a DISPLAY_DEVICE struct for the secondary monitor that will then be used in a call to ::EnumDisplaySettings to obtain a pointer to a DEVMODE struct. I then change the secondary display's resolution using ::ChangeDisplaySettingsEx. Once that's done, I hide the curent options window (which is a parent window created with WS_EX_CONTROLPARENT) and then proceed to create a new window on the secondary monitor. Now I am constrained in that I cannot create a fullscreen Direct3D device so I have to stick to windowed mode. So what I have to do instead is create a fake fullscreen by making a borderless window that has the same size as the secondary display which I have just resized. To create it in the proper place, I used the DEVMODE struct I obtained earlier. Now all that's left is to create a Direct3Device9 object and I pass it handles to that newly created window. Everything is created and seems to work except that the performance just isn't there when compared to using the same code to create the device on the primary monitor.

    Well that was maybe a little hard to follow with just text so here's some code + pseudocode. I removed error checking and some declarations to keep it short and concise.

    Code:
    m_hWindow = ::CreateWindowEx( WS_EX_CONTROLPARENT,
          "WindowClass",
          TITLE,
          WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU
          | WS_MINIMIZEBOX | WS_VISIBLE,
          (DesktopSize.right - m_dwWindowWidth)/2,
          (DesktopSize.bottom - m_dwWindowHeight)/2,
          m_dwWindowWidth,
          m_dwWindowHeight,
          NULL,
          NULL,
          ::GetModuleHandle( NULL ),
          NULL );
       //
       // Do some UI processing and get option choices from the user
       //
       ...
    
          //
          // Get the information for the secondary display
          //
          DISPLAY_DEVICE sDisplayDevice = {sizeof(sDisplayDevice)};
       DEVMODE sDevMode;
       BOOL bReturn = ::EnumDisplayDevices(	NULL,                              // device name
          m_dwMonitorIndex,                  // Selected Monitor
          (PDISPLAY_DEVICE) &sDisplayDevice, // device information
          NULL);                             // reserved
    
       bReturn = ::EnumDisplaySettings(	sDisplayDevice.DeviceName,  // display device
          ENUM_CURRENT_SETTINGS,      // graphics mode
          (LPDEVMODE) &sDevMode       // graphics mode settings
          );
    
       sDevMode.dmFields = 0;
       sDevMode.dmFields   |= DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY; 
       sDevMode.dmPelsWidth = m_dwWidth;
       sDevMode.dmPelsHeight = m_dwHeight;
    
       LONG lReturn = ::ChangeDisplaySettingsEx( sDisplayDevice.DeviceName,  // display device
          (LPDEVMODE) &sDevMode,
          NULL,
          (CDS_UPDATEREGISTRY),
          NULL );
       // Get back settings !
       bReturn = ::EnumDisplaySettings(	sDisplayDevice.DeviceName,  // display device
          ENUM_CURRENT_SETTINGS,      // graphics mode
          (LPDEVMODE) &sDevMode );    // graphics mode settings
    
       // Hide the options window
       ::SetWindowPos(   m_hWindow,
          NULL,
          m_dwWindowWidth/2,
          m_dwWindowHeight/2,
          m_dwWindowWidth,
          m_dwWindowHeight,
          SWP_HIDEWINDOW );
    
       // Create the window on which we will do 3D rendering
       m_hDXWindow = ::CreateWindowEx( WS_EX_CONTROLPARENT,
          "WindowClass",
          TITLE,
          WS_POPUP & ~WS_THICKFRAME & ~WS_BORDER | WS_VISIBLE | WS_EX_TOPMOST,
          sDevMode.dmPosition.x,
          sDevMode.dmPosition.y,
          m_dwWidth,
          m_dwHeight,
          NULL,
          NULL,
          ::GetModuleHandle( NULL ),
          NULL );
    
       // Fill the present parameters
       ::ZeroMemory( &m_PresentParameters, sizeof( m_PresentParameters ) );
       m_PresentParameters.Windowed = m_bWindowed;
       // Discard last displayed frame - Faster and supports multisampling
       m_PresentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
    
       // Depth/Stencil Format
       m_PresentParameters.EnableAutoDepthStencil = true;
       m_PresentParameters.AutoDepthStencilFormat = m_DepthStencilFormat;
       m_PresentParameters.hDeviceWindow = m_hDXWindow;			// Window handle
    
       //Disable vsync
       m_PresentParameters.PresentationInterval = D3DPRESENT_INTERVAL_ONE;//D3DPRESENT_INTERVAL_DEFAULT;//D3DPRESENT_INTERVAL_IMMEDIATE;
       m_PresentParameters.BackBufferCount = 2;              // Triple buffering
       m_PresentParameters.BackBufferWidth = m_dwWidth;		// Screen Width
       m_PresentParameters.BackBufferHeight = m_dwHeight;		// Screen Height
       m_PresentParameters.BackBufferFormat = m_ColorFormat;	// Color Depth
       m_PresentParameters.MultiSampleType = m_MultiSampling;	// Multi-Sampling
    
       // Create the Device
       m_pDirect3DObject->CreateDevice(	D3DADAPTER_DEFAULT,
          D3DDEVTYPE_HAL,
          m_hDXWindow,
          m_dwVertexProcessing,
          &m_PresentParameters,
          &m_pDirect3DDevice );
    Thanks in advance

  2. #2
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    There's certainly no limitation in Windows or the Direct3D architecture that will prevent this from working, but perhaps the driver is causing problems here.

    [I used to work for a company making graphics chips as a driver developer - and I can certainly say that both displays on the same card can be run at full-speed - please don't ask for details tho', as I don't really know what I can say and can't say with respect to still binding confidentiality agreements]

    --
    Mats

  3. #3
    Registered User
    Join Date
    Apr 2005
    Posts
    13
    Well, it was a stupid mistake as usual. I have always assumed that when you create the 3D Device, the adapter index referred to the graphics card. So if you have more than one graphics card on your system, that parameter would control which one you are creating the Direct3D device for.

    Well I just read the documentation and it actually deals with the display index. So just changing the D3DADAPTER_DEFAULT to the proper display index fixed my problem.

    Cheers!

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. My monitor doesn't work with Ubuntu Linux.
    By indigo0086 in forum Tech Board
    Replies: 1
    Last Post: 07-12-2007, 10:59 AM
  2. Hardware monitor found an error....
    By Perspective in forum Tech Board
    Replies: 1
    Last Post: 08-01-2003, 07:49 PM
  3. visual hardware solution
    By beely in forum Tech Board
    Replies: 4
    Last Post: 06-07-2003, 12:17 AM
  4. (De)Activating Secondary Monitor
    By Mr.Mister in forum Tech Board
    Replies: 4
    Last Post: 03-04-2003, 10:03 PM
  5. Monitor Woes
    By OneStiffRod in forum Tech Board
    Replies: 14
    Last Post: 12-11-2002, 05:02 AM