Window mode error [updated]

Started by
22 comments, last by Halsafar 18 years, 11 months ago
This post has been edited. The original is below the dashes ---- I've thrown together a very simple set of calls that I think point out how simple this problem should be to solve. To me, it looks like what I have here is 1 + 1 = 3. If anyone can make sense out of this, I would appreciate it. This is how I've setup the test:

// This is my create device function:
BOOL GraphicsEngine::CreateDevice() // Creates the device
{
	// Setup Present
	Present.Windowed = Setup.Display.WindowMode;
	Present.hDeviceWindow = WindowHandle;
	Present.BackBufferWidth = Setup.Display.Size.X;
	Present.BackBufferHeight = Setup.Display.Size.Y;
	Present.BackBufferCount = Setup.Display.NumBuffers;
	Present.BackBufferFormat = ( ( Setup.Display.WindowMode ) ?
					D3DFMT_UNKNOWN : D3DFORMAT(Setup.Display.Format) );
	Present.PresentationInterval = ( Setup.Display.VSync ) ?
					D3DPRESENT_INTERVAL_DEFAULT : D3DPRESENT_INTERVAL_IMMEDIATE;

	// Create Device ?
	HRESULT hVal;
	if( Device )
	{
		// Reset it
		hVal = Device->Reset( &Present );
	}
	else
	{
		// Create it
		hVal = Direct3D->CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,
                         WindowHandle,
                         D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE,
                         &Present, &Device);
	}

	return !FAILED( hVal );
}

// Now this is the test code. The first two succeed. The third fails.
// Note that the first try should be exactly the same as the last!

Setup.Display.Size.X = 640;
Setup.Display.Size.Y = 480;
Setup.Display.WindowMode = FALSE;

if( !CreateDevice() )
	Error("Could not initialize");

Setup.Display.Size.X = 640;
Setup.Display.Size.Y = 480;
Setup.Display.WindowMode = TRUE;

if( !CreateDevice() )
	Error("Could not initialize");

Setup.Display.Size.X = 640;
Setup.Display.Size.Y = 480;
Setup.Display.WindowMode = FALSE;

if( !CreateDevice() )
	Error("Could not initialize");




If I change the order of window mode from FALSE, TRUE, FALSE, to TRUE, FALSE, TRUE, FALSE, all four calls will succeed. In other words, just puting a WindowMode = true test at the top of those three calls will make it work perfectly. I'm sorry for the code structuring, I had a hard time fitting the source into the box. I would really appreciate any help. Thanks. ------------------------ Original Post ------------------------ Here's the very strange situation I'm having. If I start my game in windowed mode, I can switch to full-screen of any resolution supported by my monitor. I can then switch back to window mode, then back and again and again, no problems. If I start my game in full-screen mode, then switch to window mode, the next time I switch to full-screen, Direct3D gives me these errors: Direct3D9: :DoneExclusiveMode Direct3D9: :Window has been subclassed; cannot restore! Direct3D9: (ERROR) :Exclusive Mode has been taken by other app or other device on the same adapter. SetCooperativeLevel returns D3DERR_DEVICELOST. Or rather these are the last statements in output. All of this is spewed when I call Reset(). And the device will simply not reset, no matter what I try after this situation. I've been trying to debug this all day, thinking that something in my engine was being switched on or off when I started in window mode but not when starting full-screen. There is nothing. I've removed all reference to windowed mode from everything except creating and restoring the device. The only way I've managed to get the device to restore after this point is by releasing both the device and the Direct3D object and re-creating them. Just releasing the device will not work. I have to release the Direct3D object as well. Does anyone know what's going on? What makes the difference if I start in windowed mode? Why does it fix everything if I remove and create the Direct3D object again? I'm a bit lossed. Anyone with explanations will be hailed as genius heroes. Thanks Oh, and I was joking about it being Microsoft's fault. But that doesn't mean it's not [smile] edit: After starting in full-screen and switching to window-mode, all is lost. There's no type of reset that works after that. I don't have to try switching to full-screen again. I can just resize the back buffer or simply reset the device for no reason. [Edited by - Jiia on July 13, 2005 10:09:20 AM]
Advertisement
Sounds like DX is not releasing exclusive control of the screen when you change to windowed mode if you've started in full-screen. Could you post the code for switching?
Sirob Yes.» - status: Work-O-Rama.
Did you check for TestCooperativeLevel()'s return value? It will first return DEVICELOST for a while, but only after it starts returning DEVICENOTRESET can you successfully reset the device.

Greetz,

Illco
I don't even set cooperative levels. Should I be doing this? [smile]
// I just create Direct3D..Direct3D = Direct3DCreate9(D3D_SDK_VERSION)// Setup static present data (these never change)Present.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;Present.MultiSampleQuality = 0;Present.MultiSampleType = D3DMULTISAMPLE_NONE;Present.SwapEffect = D3DSWAPEFFECT_DISCARD;Present.EnableAutoDepthStencil = TRUE;Present.AutoDepthStencilFormat = D3DFMT_D24S8;Present.Flags = D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL;// Set the display options present data..// Setup.* being a structure of settings in my engine.Present.Windowed = Setup.Display.WindowMode;Present.hDeviceWindow = WindowHandle;Present.BackBufferWidth = Setup.Display.Size.X;Present.BackBufferHeight = Setup.Display.Size.Y;Present.BackBufferCount = Setup.Display.NumBuffers;Present.BackBufferFormat = ( ( Setup.Display.WindowMode ) ?                D3DFMT_UNKNOWN : D3DFORMAT(Setup.Display.Format) );Present.PresentationInterval = ( Setup.Display.VSync ) ?                D3DPRESENT_INTERVAL_DEFAULT : D3DPRESENT_INTERVAL_IMMEDIATE;// Then create the device..Direct3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,WindowHandle,     D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE, &Present, &Device );// Then to reset after changing display options, I release all resources,// update the present structure, thenDevice->Reset( &Present )


Something important missing?

Thanks
Quote:Original post by Illco
Did you check for TestCooperativeLevel()'s return value? It will first return DEVICELOST for a while, but only after it starts returning DEVICENOTRESET can you successfully reset the device.

My engine throws up a message box asking the user if they want to try to restore the display again. I can press yes until I'm blue in the face, it just won't succeed [smile]

edit:

I tried calling TestCooperativeLevel() before Reset() fails, and that function succeeds. Reset still fails of course. I'm getting more confused.
Might sound silly, but does removing the Pure Device help any?
Sirob Yes.» - status: Work-O-Rama.
No, that doesn't help. Pure device just means DirectX won't try to emulate features that aren't available on the hardware. From my experience, if the hardware doesn't support it, Direct3D brings the CPU to a halt trying to fake it. So I don't bother.
Quote:Original post by Jiia
No, that doesn't help. Pure device just means DirectX won't try to emulate features that aren't available on the hardware. From my experience, if the hardware doesn't support it, Direct3D brings the CPU to a halt trying to fake it. So I don't bother.


Not exactly. From the FAQ:


What is the purpose of the D3DCREATE_PUREDEVICE flag?

If the D3DCREATE_PUREDEVICE flag is specified during device creation, Direct3D will create a "pure" device. This disables the use of the Get* family of methods and forces vertex processing to be hardware only. This allows the Direct3D runtime to make certain optimizations that afford the best possible path to the driver without having to track so much internal state. In other words, you can see a performance advantage using PUREDEVICE, at the cost of some convenience.


Since you are required to enable HW vertex processing when creating a pure device, any SWVP that was available is gone as well. In general, D3D doesn't ever attempt to "emulate" functionality that is not present in the HW.

I'm looking into why one would get the message originally posted.

Paul Bleisch
Quote:Original post by paulble
Not exactly
..
In general, D3D doesn't ever attempt to "emulate" functionality that is not present in the HW.


From SDK docs:
Quote:D3DCREATE_PUREDEVICE Specifies that Direct3D does not support Get* calls for anything that can be stored in state blocks. It also tells Direct3D not to provide any emulation services for vertex processing. This means that if the device does not support vertex processing, then the application can use only post-transformed vertices.

[smile]
Are you running the gameLoop in a seperate thread by any chance?

SetCooperativeLevel.... hmm I remmeber that being necessary in Dx7, but I just went through the code I wrote for Dx9 initialization and I am not setting the cooperative level either.

After you've released all necessary objects and are ready to reset you Device3D make sure you do the following:
//Get Displaymodes
D3DDISPLAYMODE d3ddm;
m_pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &d3ddm);

m_d3dParam.Windowed = TRUE;
m_d3dParam.SwapEffect = D3DSWAPEFFECT_COPY;
m_d3dParam.BackBufferWidth = 0;
m_d3dParam.BackBufferHeight = 0;
m_d3dParam.BackBufferFormat = d3ddm.Format;

This topic is closed to new replies.

Advertisement