Current setup -
One single core graphics device,
Two monitors.
As the title would suggest, I'm currently attempting to create an application in c++/DirectX which supports a theoretically uncapped limit on the number of full screen view points in the program. I'm utilising swap chains for each display and worthy of note is that this does work in windowed mode but due to the nature of the program, windowed is not an option. It also works, in full screen if only a single display is activated, with no code changed... so it's basically, just the 'multi' part which is the problem. :(
Apologies for the comments being misplaced, as well as my trimming of the error clauses; I've rejigged the thing, mostly for ease of reading.
For each display, I populate the following 'struct' and the d3d adapter + device are private members of the files header..
struct DISPLAY_HANDLE{
HWND wndHandle;
HINSTANCE hInstance;
D3DPRESENT_PARAMETERS d3dpp;
LPDIRECT3DSWAPCHAIN9 swapChain;
LPDIRECT3DSURFACE9 backBuffer;
};
class DeviceGfx{
private:
LPDIRECT3D9;
LPDIRECT3DDEVICE9 d3dDevice;
vector<DISPLAY_HANDLE> displayHandles;
etc etc
Upon the class being created, the above objects are NULLed and the 'init' function is called with appropriate options having already been loaded into the program.
Inside the init function, I start off by creating the d3d device appropriately:
d3d = Direct3DCreate9(D3D_SDK_VERSION);
if(d3d == NULL)
return E_FAIL;
For each display, determined by use of the options file, I do the following:
Firstly, I create an appropriate window handle.
DISPLAY_HANDLE newHandle = {0};
WNDCLASSEX wcex;
wcex.cbClsExtra = 0;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.cbWndExtra = 0;
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+2);
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hIcon = 0;
wcex.hIconSm = 0;
wcex.hInstance = newHandle.hInstance;
wcex.lpfnWndProc = (WNDPROC)messageProcess;
wcex.lpszClassName = "WindowMain";
wcex.lpszMenuName = NULL;
wcex.style = CS_HREDRAW | CS_VREDRAW;
RegisterClassEx(&wcex);
string lpClassName = "WindowMain";
string lpWindowName = "Blank DirectX Project";
DWORD dwStyle;
if(options->getGlobalDisplayOptions().fullScreen == true)
dwStyle = WS_EX_TOPMOST | WS_POPUP | WS_VISIBLE;
else
dwStyle = WS_OVERLAPPEDWINDOW;
newHandle.wndHandle = CreateWindow(lpClassName.c_str(),
lpWindowName.c_str(), dwStyle,
options->getIndividualDisplayOptionsAt(x).WindowPosition.left,
options->getIndividualDisplayOptionsAt(x).WindowPosition.top,
options->getIndividualDisplayOptionsAt(x).resolutionW,
options->getIndividualDisplayOptionsAt(x).resolutionH,
NULL,
NULL,
newHandle.hInstance, NULL);
if(newHandle.wndHandle == false)
return E_FAIL;
ShowWindow(newHandle.wndHandle, SW_SHOW);
After having done this, I fill the d3dparameter lists for each device, once again loaded frrom file. Rather then showing the code, I'll just list off the values of the parameters for each device as I'm guessing that may be where the problem is.
Displays:
BackBufferWidth = 800;
BackBufferHeight = 600;
BackBufferFormat = D3DFMT_X8R8G8B8;
BackBufferCount = 1;
MultiSampleType = D3DMULTISAMPLE_NONE;
MultiSampleQuality = 0;
SwapEffect = D3DSWAPEFFECT_DISCARD;
hDeviceWindow = memory address...this works anyhow.
Windowed = 0;
EnableAutoDepthStencil = 1;
AutoDepthStencilFormat = D3DFMT_D16;
Flags = 0;
FullScreen_RefreshRateInHz = 0;
PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
The only difference between the 2 devices is the address of the hDeviceWindow handle. The handles create properly, no worries there (unless a certain parameter isn't supported). All of this works correctly however that's kind of a moot point as its simply filling in a parameters list.
After this, I create the d3d device.
d3dDevice = NULL;
if(FAILED(d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, displayHandles.at(0).wndHandle, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &displayHandles.at(0).d3dpp, &d3dDevice))){
return E_FAIL;
}
For the next part, I loop through each display, creating a swap chain and then things start to go wrong.
for(int x = 0; x < (int)displayHandles.size(); x++){
displayHandles.at(x).swapChain = NULL;
if(x == 0)
d3dDevice->GetSwapChain( 0, &displayHandles.at(0).swapChain );
else
d3dDevice->CreateAdditionalSwapChain( &displayHandles.at(1).d3dpp, &displayHandles.at(1).swapChain );
displayHandles.at(x).swapChain->GetBackBuffer( 0, D3DBACKBUFFER_TYPE_MONO, &displayHandles.at(x).backBuffer);
}
This will loop through once, successfully completing the 'GetSwapChain' method for the first device, as well as getting its backbuffer with 'GetBackBuffer'.
Upon the second device iterating through however, the 'CreateAdditionalSwapChain' method fails, returning a D3DERR_INVALIDCALL error. Then of course, as it tries to find its backbuffer, the program falls apart.
It's annoying being so close yet so far with this but of course I know it's possible...several multi-fullscreen applications exist which have worked with both DirectX9 and C++, it's as always, just a case of how :)
Any advice, pointers or the like would be most welcomed. Thanks in advance.