CU_MDX_LostDevice.zip (63.4 KB, 1,164 hits)
CUnitFramework.zip (101.1 KB, 12,470 hits)
inside the project (not solution) directory.
When a device is in fullscreen mode, many of the resources that the application is using (textures, buffers, etc.) are stored in video memory. When the user Alt-Tabs to go to another application, video memory may be given over to other applications and the original data may be lost. When this occurs, the Device.Present method will throw an exception. This is what is known as a lost device. To get back to the normal operational state, we must reset the device whenever it is lost. In this tutorial, I will explain how the C-Unit Framework handles a lost device.
private void OnRenderFrame()
{
m_graphics.Device == null || m_graphics.Device.IsDisposed || m_state.FormClosing ||
m_state.DeviceLost )
{
}
try
{
}
catch ( DeviceLostException )
{
System.Threading.Thread.Sleep( 50 );
if ( !m_state.DeviceLost )
{
m_state.DeviceLost = true;
}
}
}
As stated above, when the device is lost, the Device.Present method will throw a DeviceLostException. Since this method is called in one of the GameStates, we’ll surround the StateManager’s OnRenderDevice with a try block to catch the DeviceLostException. When we catch the exception, we flag the Device as being lost.
/// <param name=”sender”>Sending object</param>
/// <param name=”e”>Event arguments</param>
private void OnApplicationIdle( object sender, EventArgs e )
{
{
}
while ( AppStillIdle )
{
this.WindowState != FormWindowState.Minimized && m_state.Initialized )
{
OnRenderFrame();
}
else if ( m_state.DeviceLost )
{
}
}
}
When the Device is flagged as lost, the Framework will call the RegainLostDevice method:
private void RegainLostDevice()
{
if ( !m_graphics.Device.CheckCooperativeLevel() )
{
if ( code == ResultCode.DeviceLost )
{
// So wait until it can be reset.
System.Threading.Thread.Sleep( 50 );
return;
}
try
{
m_graphics.Reset();
m_state.DeviceLost = false;
m_state.DisableResize = false;
Pause( false, false );
}
catch ( DeviceLostException )
{
System.Threading.Thread.Sleep( 50 );
}
}
}
When a device is lost, the Device.CheckCooperativeLevel method returns false and we should try to regain the Device. To see if we can reset the Device, we call Device.CheckCooperativeLevelResult, which returns a ResultCode. This result code has 2 possible values when the Device is lost: DeviceLost and DeviceNotReset. A DeviceLost result code means that the device is lost but cannot be reset yet. When we see this result code, we pause the program thread for a bit and then return out of the method. A DeviceNotReset result code means that we can attempt to reset the device to return to normal. There is a chance that when we reset the device, the device will have become lost again. If this is the case, Device.Reset will throw a DeviceLostException. We catch this exception, pause for a bit and return just like we did when the result code was DeviceLost.
m_graphics.Device.DeviceLost += new System.EventHandler( this.OnLostDevice );
m_graphics.Device.DeviceReset += new System.EventHandler( this.OnResetDevice );
m_graphics.Device.Disposing += new System.EventHandler( this.OnDestroyDevice );
Since we’ve hooked the DeviceLost and DeviceReset events of the device, our OnLostDevice and OnResetDevice methods will be called automatically when the device is lost and reset.
And that’s all I have to say about that.