Odd Lost Device Issue

Started by
2 comments, last by Nightcrawler99 19 years ago
Ok.. I've read posts, tutorials, looked at example code until my head swelled up and still I cannot figure out what my problem is exactly. I'm no stranger to Direct3D. I have a 2D platformer that I have gotten into the stages of limited playbility. However, my problem is much more basic than that. I understand the lost devices basics. My device stays lost when I am in fullscreen and is unable to be reset. I know that indicates that a device resource has not been freed, but I see no such resource. Just to be absolutely certain, I started a new project, with only the barebones to get a blank window up and running. Still the same problem. The program does nothing but initiate the device and clear the screen. For further information, everythign works fine in windowed mode and I can restore a lost device there. I can also switch from windowed to full screen mode with no problem. But once in full screen mode, D3D keeps telling me I cannot reset the device. I must have missed something basic somewhere along the line. This is the code in it's entirety. It's only a mere 4 functions, the bare minimum to get a window up and running with restoring the device. I hope that someone can point out the embarrassing mistake I have made in either the fundementals of D3D or Win32. If you run the program, it will hang in the beginning of the Render() function waiting for the device to become resetable.
#include<windows.h>
#include<d3d9.h>
#include<d3dx9.h>

LRESULT WINAPI WinProc(HWND mainwindow, UINT msg, WPARAM wParam, LPARAM lParam);
INT WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR CmdLine, INT CmdShow);

HWND mainwindow;
#define SCREENX 1280			//actual resolution used
#define SCREENY 1024
#define FULLSCREEN 1

//Global COM Objects
IDirect3D9* d3dobject;					//D3D Com Interface Object
IDirect3DDevice9 *d3ddev;				//D3D Device

D3DPRESENT_PARAMETERS d3dparam;			//Set parameters to create d3d device
int InitD3D(int fullscreen,int reset);
int Render();
int D3DCleanup();

INT WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR CmdLine, INT CmdShow)
{
	MSG msg;				//Message
	
	
	
	WNDCLASSEX winclass = {sizeof(WNDCLASSEX),	//size of structure
					 CS_CLASSDC,			//Class Style
					 WinProc,				//Message Hander
					 0, 0,					
                     hInst,					//Application Instance
					 NULL, NULL, NULL, NULL, //Icon, Cursor, Brush, Menu
                     "DX9 Project", NULL};
   
	winclass.hCursor = LoadCursor(NULL, IDC_ARROW);
	if(!RegisterClassEx(&winclass))
		return FALSE;

	
	mainwindow = CreateWindow("DX9 Project",		//Window Class Name
							  "Game Window",		//Window Title
                              WS_OVERLAPPEDWINDOW,	//Window Style
							  0, 0,				//x,y coordinate
							  SCREENX, SCREENY,				//size
                              NULL, NULL,			//Parent Window, Menu Handle 
							  hInst,					//Instance
							  NULL);
	if(mainwindow==NULL)
		return FALSE;

	ShowWindow(mainwindow, SW_NORMAL);
	UpdateWindow(mainwindow);

	ShowCursor(true);
	if(InitD3D(FULLSCREEN,0))
	{
		MessageBox(mainwindow,"Initialization of D3D9 Failed!","Uh Oh!",MB_OK);
		return 0;
	}

	while(msg.message!=WM_QUIT)
	{
		if(PeekMessage(&msg,NULL,0,0,PM_REMOVE))
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
		else
		{
	
	
			if(Render())
			{
			
				MessageBox(mainwindow,"Rendering Failed!","Uh Oh!",MB_OK);
				return 0;
			}
		}
	}


	UnregisterClass("DX9 Project",hInst);
	return 0;

}


LRESULT WINAPI WinProc(HWND mainwindow, UINT msg, WPARAM wParam, LPARAM lParam)
{ 
	switch(msg)
	{
	case WM_QUIT:
	case WM_DESTROY:
		KillTimer(mainwindow,1);
		D3DCleanup();				//Delete Textures
		PostQuitMessage(0);
		break;
	

	
	case WM_KEYDOWN:
		switch(wParam)
		{
		case VK_ESCAPE:					//Escape
			PostMessage(mainwindow,WM_DESTROY,NULL,NULL);
			break;
		
		}


	default:
		return DefWindowProc(mainwindow,msg,wParam,lParam);
	}

	return 0;

}

int InitD3D(int fullscreen,int reset)
{
	if((d3dobject=Direct3DCreate9(D3D_SDK_VERSION))==NULL)
		return 1;

	D3DDISPLAYMODE d3ddm;
	HWND hwnd=mainwindow;

	
	
	if(FAILED(d3dobject->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &d3ddm)))
		return 1;
	ZeroMemory( &d3dparam, sizeof(d3dparam) );
	
	if(fullscreen)
	{
		d3dparam.Windowed=FALSE;
		d3dparam.SwapEffect = D3DSWAPEFFECT_FLIP;
		d3dparam.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
		d3dparam.BackBufferHeight=SCREENY;
		d3dparam.BackBufferWidth=SCREENX;
		d3dparam.BackBufferFormat=d3ddm.Format;
		d3dparam.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
//maybe		d3dparam.BackBufferCount = 1;
//maybe		d3dparam.SwapEffect = D3DSWAPEFFECT_COPY;
		if(FAILED(d3dobject->CheckDeviceType(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,d3ddm.Format,d3ddm.Format,FALSE)))
		{
			MessageBox(NULL,"Video Mode not supported!","Error",MB_ICONSTOP|MB_OK);
			return FALSE;
		}
		
	}
	else
	{
		d3dparam.Windowed   = TRUE;
		d3dparam.SwapEffect = D3DSWAPEFFECT_DISCARD;
		d3dparam.BackBufferFormat = d3ddm.Format;
		d3dparam.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;//D3DPRESENT_INTERVAL_ONE
	}

	
	if( FAILED( d3dobject->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,		//Create device
                                  D3DCREATE_SOFTWARE_VERTEXPROCESSING,
                                  &d3dparam, &d3ddev)))
    return 1;

	
	
	
	
    
	return 0;
}

int Render()
{ 

		HRESULT tempresult=0;
	if(d3ddev->TestCooperativeLevel()!=D3D_OK)
	{
		
		tempresult=d3ddev->TestCooperativeLevel();
		if(tempresult==D3DERR_DRIVERINTERNALERROR)
		{
			MessageBox(NULL,"Major Crash","Oh Shit!",MB_OK);
			return 1;
		}
		while(tempresult!=D3DERR_DEVICENOTRESET)
			tempresult=d3ddev->TestCooperativeLevel(); //wait until you can reset
	
		if(tempresult==D3DERR_DEVICENOTRESET)
		{
								
			while(tempresult!=D3D_OK)
				tempresult=d3ddev->Reset(&d3dparam);
					
		}
			
	}
	//Set Render States
	d3ddev->SetRenderState(D3DRS_LIGHTING, FALSE);					//Lighting ON/OFF
	d3ddev->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);			//polygon culling mode
	d3ddev->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);			//Turn alpha blending ON
	d3ddev->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);		//These next two are the type of blending
	d3ddev->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);	//type of blending


	

	if(FAILED(d3ddev->Clear(0,NULL,D3DCLEAR_TARGET,D3DCOLOR_RGBA(0,255,255,255),1.0f,0)))
		return 1;

	d3ddev->BeginScene();

	d3ddev->EndScene();

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

	
	
	return 0;

}


int D3DCleanup()
{
		//d3ddev->SetTexture(0,NULL);
	
		if(d3ddev != NULL)
            int one=d3ddev->Release();
        if(d3dobject!= NULL)
            int two=d3dobject->Release();
				
		return 0;

}


Advertisement
Messages may need to be processed. I'd drop out of the Render() call, and let the message pump run. When not active, you may also want to switch to waiting for messages rather than Peeking as fast as you can. If you don't want to bother making it wait, at least put a Sleep in there, allowing other things to run while you're not active.
Yeah, I agree with above poster.

This part:
while(tempresult!=D3DERR_DEVICENOTRESET)  tempresult=d3ddev->TestCooperativeLevel();


Is no good. My guess is the device context isn't ready yet, and you arn't giving the windows messages a chance to prepair it for you. Try this instead:

if(tempresult==D3DERR_DEVICENOTRESET){  tempresult=d3ddev->Reset(&d3dparam);  return;}


If you want to structure it better to get rid of the ugly return then go for it, but the point is to get rid of the while statements. If you call reset and it's not working, then the same problem that stopped you the first time will continue to stop you, unless you let the windows messaging do its thing.

Help?
That was it guys. Jeez.. I knew it was something basic like that. I've been banging my head on this simple problem for a few days now.

I DID have a sleep() statement in there in my actual game. I forgot to put that in there when I made up the barebones test.

Thanks alot. I was under the impression that you could just loop and wait a bit until the device was ready to be reset. I didn't know it would never become ready unless I let it keep processing messages. Works flawlessly now.

Thanks again.

[Edited by - Nightcrawler99 on April 1, 2005 12:57:27 PM]

This topic is closed to new replies.

Advertisement