요즘 개발자라면 대부분 Dual 모니터 환경에서 작업을 할 것이다.
간혹 어떤 사연으로 Primary 모니터가 아닌 Secondary 모니터로 Full Screen으로 된 DX 화면을 띄우고 싶을 때가 있을 것이다(예컨데, 창모드 지원이 되지 않는 프레임워크에서 디버깅을 위해서나 그냥 그렇게 보는 게 더 편하다거나.).
그렇다면 IDirect3D9::CreateDevice() 에서 흔히 사용하는 D3DADAPTER_DEFAULT 대신 다른 방법을 써야 한다.
D3DADAPTER_DEFAULT는 Primary 모니터를 가르키기 때문이다. 안타깝게도 이를 위한 매크로는 따로 없다.
모니터 식별은 IDirect3D9::GetAdapterIdentifier()로 얻어낼 수 있는데 이름에서 알수 있듯, DX에게 중요한 것은 모니터가 아니라 비디오 카드의 출력단자인 것이다.
먼저 모니터 식별에 대한 리턴값을 저장하기 위해 구조체를 만든다.
{
public:
UINT m_iAdapterOrdinal;
D3DADAPTER_IDENTIFIER9 m_Identifier;
D3DDISPLAYMODE m_mode;
D3DDEVTYPE m_DevType;
};
그 다음은 IDirect3D9::GetAdapterCount()로 비디오카드의 출력단자가 몇개인지를 잰다.
이제 for()문을 돌며 각 그래픽 카드에 하드웨어 정보를 얻어내자.
for(UINT iAdapterOrdinal = 0; iAdapterOrdinal < iAapterCount; iAdapterOrdinal++)
{
CVGAAdapter VGAAdapter;
VGAAdapter.m_iAdapterOrdinal = iAdapterOrdinal;
VGAAdapter.m_DevType = m_D3DTypeDef;
m_pD3DObject->GetAdapterIdentifier(iAdapterOrdinal, 0, &VGAAdapter.m_Identifier );
m_pD3DObject->GetAdapterDisplayMode(iAdapterOrdinal, &VGAAdapter.m_mode);
// 윈도우 모드일때 정보 얻음
HR(m_pD3DObject->CheckDeviceType(iAdapterOrdinal, m_D3DTypeDef, VGAAdapter.m_mode.Format, VGAAdapter.m_mode.Format, TRUE));
// 풀스크린일때 정보 얻음
HR(m_pD3DObject->CheckDeviceType(iAdapterOrdinal, m_D3DTypeDef, D3DFMT_X8R8G8B8, D3DFMT_X8R8G8B8, FALSE));
// 벡터에 저장
m_vecVGAAdapter.push_back(VGAAdapter);
}
마지막 push_back에서 알 수 있듯이 CVGAAdapter는 vector로 관리했는데,
엽기적으로 그래픽카드를 여러개 꽂아 3개 이상의 모니터를 사용하는 변태도 있기 때문이다.
이제 m_vecVGAAdapter[0]은 Primary 모니터를 의미하고 m_vecVGAAdapter[1]은 Secondary 모니터를 의미하게 된다.
이제 IDirect3D9::CreateDevice()의 1, 2번 인자에는 각각 m_vecVGAAdapter[0].m_iAdapterOrdinal과 m_vecVGAAdapter[0].m_DevType 를 적어주면 된다.
만약 풀스크린과 윈도우 모드를 동시 지원하는 프레임워크라면 분명 각 모드에 대한 D3DPRESENT_PARAMETERS 구조체를 채우는 함수가 있을 것이다. 여기에 CVGAAdapter.m_mode의 값을 넣어주자. 이때 해상도를 변경하고 싶으면 사용가능한 해상도 정보를 얻기 위해 IDirect3D9::EnumAdapterModes()를 이용하여 위의 for() 내에서 한 아답터 정보를 얻어마자 다시 사용 가능한 해상도를 얻어낸다.
이는 어차피 DX 기본 프레임워크에 구현되어 있으니 참조하도록 하며 상기의 내용 정도라면 개발시 Secondary 모니터로 풀스크린을 만드는데에는 큰 불편함이 없을 것이다.
