Handling Lost Devices


Before you start using that timer, you need to take care of something more pressing. To see the problem in action, change your project to run in release mode. You can do so by selecting Build, Configuration Manager. For the Active Solution Configuration, choose Release. (See Figure 5.1.)

Figure 5.1. The Configuration Manager dialog.


Running the application now renders the fledgling game in full-screen mode. On the surface, everything should appear the same; however, you might notice quickly that with the window border no longer around, you can't close the application. Luckily, you are using the sample framework; otherwise, if you decided to minimize the window (for example, by using the Alt+Tab key combination to switch to the next application) or close the window, the game would throw an exception as soon as it lost focus. Even though you don't have this problem because you're using the sample framework, it's important to know what causes this.

When you are running the application in full-screen mode, Direct3D takes exclusive mode over the monitor that is being used to render the full screen image.

When you switch to a different application, that exclusive mode must be released to allow the other application to run, so the current application is minimized and the device is lost. Once a device is lost, you cannot render to it any longer, and trying to do so throws an exception (specifically the DeviceLostException).

Because this is a common problem that every game has to solve, you wouldn't want to clutter your rendering method with code to handle the situation, which is why the sample framework handles it for you. Look at the code snippet in Listing 5.4 for more information.

Listing 5.4. Handling Lost Devices
 int result; // Check the cooperative level to see if it's ok to render if (!device.CheckCooperativeLevel(out result)) {     if (result == (int)ResultCode.DeviceLost)     {         // The device has been lost but cannot be reset at this time.         // So wait until it can be reset.         System.Threading.Thread.Sleep(50);         return;     }     // Other code snippets } // Other code snippets // Show the frame on the primary surface try {     device.Present(); } catch (DeviceLostException) {     // Whoops, device is lost now     State.IsDeviceLost = true; } catch (DriverInternalErrorException) {     // When DriverInternalErrorException is thrown from Present(),     // the application can do one of the following:     //     // - End, with the pop-up window saying that the application cannot continue     //   because of problems in the display adapter and that the user should     //   contact the adapter manufacturer.     //     // - Attempt to restart by calling Device.Reset, which is essentially the     //   same path as recovering from a lost device. If Device.Reset throws the     //   DriverInternalErrorException, the application should end immediately     //   with the message that the user should contact the adapter manufacturer.     //     // The framework attempts the path of resetting the device     //     State.IsDeviceLost = true; } 

You'll notice immediately that this method updates the variable IsDeviceLost on the State class. In this method, you check to see whether the device is currently lost, and if it is, you call the CheckCooperativeLevel method on the device. This call returns a Boolean value, true if the device is available and ready to use and false otherwise. Notice that an integer value is returned as an out parameter, which is the reason why the device is still not available.

After this call (assuming it returned false), you want to check the reason why the device is not available to render. The two likely reasons are that the device is still lost (the application still doesn't have focus) or that the application has regained focus, but the device hasn't been reset. If the device is still lost, there's nothing you can do right now, so you simply return from the method. However, if the device needs to be reset (which it always does after regaining focus), you simply call the Reset method, which should return the device back to the exclusive mode and be ready for rendering (the framework handles this for you).

Assuming you made it past that section, either the device was never lost to begin with or it is reset and ready to use now. Next, you are ready to render your scene. The framework calls the render method you have written and then makes the Present call. This call is the one that throws the exception when the device is lost, so after the render method is called, Present is called, wrapped in a try/catch block. Notice that the only exceptions caught are DeviceLostException and DriverInternalErrorException and the only action taken is to set the Boolean variable to TRue to start the check of the current cooperative level.



Beginning 3D Game Programming
Beginning 3D Game Programming
ISBN: 0672326612
EAN: 2147483647
Year: 2003
Pages: 191
Authors: Tom Miller

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net