00001
00002
00003
00004
00005
00006
00007
00008 using System;
00009 using System.Collections;
00010 using Microsoft.DirectX;
00011 using Microsoft.DirectX.Direct3D;
00012
00013 namespace Microsoft.Samples.DirectX.UtilityToolkit
00014 {
00018 public sealed class Framework : IDisposable
00019 {
00020
00021 #region Class Data
00022
00023 private const string CmdAdapter = "adapter";
00024 private const string CmdWindowed = "windowed";
00025 private const string CmdFullscreen = "fullscreen";
00026 private const string CmdForceHardware = "forcehal";
00027 private const string CmdForceRef = "forceref";
00028 private const string CmdPureHwVp = "forcepurehwvp";
00029 private const string CmdForceHwVp = "forcehwvp";
00030 private const string CmdForceSwVp = "forceswvp";
00031 private const string CmdWidth = "width";
00032 private const string CmdHeight = "height";
00033 private const string CmdStartx = "startx";
00034 private const string CmdStarty = "starty";
00035 private const string CmdConstantFrame = "constantframetime";
00036 private const string CmdQuitAfterFrame = "quitafterframe";
00037 private const string CmdNoErrorBoxes = "noerrormsgboxes";
00038 private const string CmdNoStats = "nostats";
00039
00040
00041 private delegate void DisposeDelegate();
00042
00043
00044 private const int MinimumWindowSizeX = 200;
00045 private const int MinimumWindowSizeY = 200;
00046 public const int DefaultSizeWidth = 640;
00047 public const int DefaultSizeHeight = 480;
00048
00049 private static readonly System.Drawing.Size DefaultStartingSize = new System.Drawing.Size(DefaultSizeWidth, DefaultSizeHeight);
00050 internal static readonly System.Drawing.Size MinWindowSize = new System.Drawing.Size(MinimumWindowSizeX, MinimumWindowSizeY);
00051 public static readonly IntPtr TrueIntPtr = new IntPtr(1);
00052 private const string WindowClassName = "ManagedDirect3DWindowClass";
00053
00054
00055 private FrameworkData State;
00056
00057 private Exception lastDisplayedMessage = null;
00058
00059 private bool isDisposed = false;
00060
00061 private bool toggleMaximized = false;
00062 #endregion
00063
00064 #region Creation
00068 public Framework()
00069 {
00070 State = new FrameworkData();
00071 }
00072 #endregion
00073
00074 #region Setting up callbacks
00075
00076 public void SetCallbackInterface(IFrameworkCallback callback) { State.CallbackInterface = callback; }
00077 public void SetDeviceCreationInterface(IDeviceCreation callback) { State.DeviceCreationInterface = callback; }
00078
00079
00080
00082 public event EventHandler Disposing;
00084 public event EventHandler DeviceLost;
00086 public event DeviceEventHandler DeviceCreated;
00088 public event DeviceEventHandler DeviceReset;
00089
00090 public void SetWndProcCallback(WndProcCallback callback) { State.WndProcFunction = callback; }
00091 #endregion
00092
00121 public void Initialize(bool isParsingCommandLine, bool handleDefaultKeys, bool showMessageBoxOnError)
00122 {
00123 State.WasInitCalled = true;
00124
00125
00126
00127 Device.IsUsingEventHandlers = false;
00128
00129
00130
00131
00132 State.IsShowingMsgBoxOnError = showMessageBoxOnError;
00133 State.IsHandlingDefaultHotkeys = handleDefaultKeys;
00134
00135
00136 try
00137 { NativeMethods.timeBeginPeriod(1); }
00138 catch { System.Diagnostics.Debugger.Log(9, string.Empty, "Could not set time period.\r\n"); }
00139
00140 if (isParsingCommandLine)
00141 {
00142 ParseCommandLine();
00143 }
00144
00145
00146 FrameworkTimer.Reset();
00147 State.IsInited = true;
00148
00149 }
00150
00154 private void ParseCommandLine()
00155 {
00156 string[] args = System.Environment.GetCommandLineArgs();
00157
00158
00159 for (int i = 1; i < args.Length; i++)
00160 {
00161 string argument = string.Empty;
00162 if ((args[i].StartsWith("-")) || (args[i].StartsWith("-")))
00163 {
00164 argument = args[i].Substring(1, args[i].Length - 1);
00165 }
00166 else
00167 continue;
00168
00169 if (argument.ToLower().StartsWith(CmdAdapter + ":"))
00170 {
00171 try
00172 { State.OverrideAdapterOrdinal = int.Parse(argument.Substring(CmdAdapter.Length + 1, argument.Length - (CmdAdapter.Length + 1))); }
00173 catch (FormatException) { }
00174 }
00175 else if (string.Compare(argument, CmdWindowed, true) == 0)
00176 {
00177 State.IsOverridingWindowed = true;
00178 }
00179 else if (string.Compare(argument, CmdFullscreen, true) == 0)
00180 {
00181 State.IsOverridingFullScreen = true;
00182 }
00183 else if (string.Compare(argument, CmdForceHardware, true) == 0)
00184 {
00185 State.IsOverridingForceHardware = true;
00186 }
00187 else if (string.Compare(argument, CmdForceRef, true) == 0)
00188 {
00189 State.IsOverridingForceReference = true;
00190 }
00191 else if (string.Compare(argument, CmdPureHwVp, true) == 0)
00192 {
00193 State.IsOverridingForcePureHardwareVertexProcessing = true;
00194 }
00195 else if (string.Compare(argument, CmdForceHwVp, true) == 0)
00196 {
00197 State.IsOverridingForceHardwareVertexProcessing = true;
00198 }
00199 else if (string.Compare(argument, CmdForceSwVp, true) == 0)
00200 {
00201 State.IsOverridingForceSoftwareVertexProcessing = true;
00202 }
00203 else if (argument.ToLower().StartsWith(CmdWidth + ":"))
00204 {
00205 try
00206 { State.OverrideWidth = int.Parse(argument.Substring(CmdWidth.Length + 1, argument.Length - (CmdWidth.Length + 1))); }
00207 catch (FormatException) { }
00208 }
00209 else if (argument.ToLower().StartsWith(CmdHeight + ":"))
00210 {
00211 try
00212 { State.OverrideHeight = int.Parse(argument.Substring(CmdHeight.Length + 1, argument.Length - (CmdHeight.Length + 1))); }
00213 catch (FormatException) { }
00214 }
00215 else if (argument.ToLower().StartsWith(CmdStartx + ":"))
00216 {
00217 try
00218 { State.OverrideStartX = int.Parse(argument.Substring(CmdStartx.Length + 1, argument.Length - (CmdStartx.Length + 1))); }
00219 catch (FormatException) { }
00220 }
00221 else if (argument.ToLower().StartsWith(CmdStarty + ":"))
00222 {
00223 try
00224 { State.OverrideStartY = int.Parse(argument.Substring(CmdStarty.Length + 1, argument.Length - (CmdStarty.Length + 1))); }
00225 catch (FormatException) { }
00226 }
00227 else if (argument.ToLower().StartsWith(CmdConstantFrame))
00228 {
00229 float timePerFrame = 0.033f;
00230 try
00231 {
00232 if ((argument.Length > CmdConstantFrame.Length))
00233 timePerFrame = float.Parse(argument.Substring(CmdConstantFrame.Length + 1, argument.Length - (CmdConstantFrame.Length + 1)));
00234 }
00235 catch (FormatException) { }
00236 State.OverrideConstantTimePerFrame = timePerFrame;
00237 State.IsOverridingConstantFrameTime = true;
00238 SetConstantFrameTime(true, timePerFrame);
00239 }
00240 else if (argument.ToLower().StartsWith(CmdQuitAfterFrame + ":"))
00241 {
00242 try
00243 { State.OverrideQuitAfterFrame = int.Parse(argument.Substring(CmdQuitAfterFrame.Length + 1, argument.Length - (CmdQuitAfterFrame.Length + 1))); }
00244 catch (FormatException) { }
00245 }
00246 else if (string.Compare(argument, CmdNoErrorBoxes, true) == 0)
00247 {
00248 State.IsShowingMsgBoxOnError = false;
00249 }
00250 else if (string.Compare(argument, CmdNoStats, true) == 0)
00251 {
00252 State.AreStatsHidden = true;
00253 }
00254 else
00255 System.Diagnostics.Debugger.Log(9, string.Empty, string.Format("Unrecognized flag: {0}\r\n", argument));
00256 }
00257 }
00258
00264 public void CreateWindow(string windowTitle, System.Drawing.Icon icon,
00265 System.Windows.Forms.MainMenu menu, int x, int y)
00266 {
00267 if (State.IsInsideDeviceCallback)
00268 throw new InvalidOperationException("You cannot create a window from inside a callback.");
00269
00270 State.WasWindowCreateCalled = true;
00271
00272 if (!State.IsInited)
00273 {
00274
00275 if (State.WasInitCalled)
00276 {
00277 throw new InvalidOperationException("Initialize was already called and failed.");
00278 }
00279
00280
00281 Initialize(true, true, true);
00282 }
00283
00284
00285 if (State.WindowFocus == null)
00286 {
00287
00288 if (State.OverrideStartX != -1)
00289 {
00290 State.DefaultStartingLocation = System.Windows.Forms.FormStartPosition.Manual;
00291 x = State.OverrideStartX;
00292 }
00293 if (State.OverrideStartY != -1)
00294 {
00295 State.DefaultStartingLocation = System.Windows.Forms.FormStartPosition.Manual;
00296 y = State.OverrideStartY;
00297 }
00298
00299
00300 GraphicsWindow renderWindow = new GraphicsWindow(this);
00301
00302 HookEvents(renderWindow);
00303
00304 if (State.DefaultStartingLocation == System.Windows.Forms.FormStartPosition.WindowsDefaultLocation)
00305 {
00306 State.IsWindowCreatedWithDefaultPositions = true;
00307 renderWindow.StartPosition = System.Windows.Forms.FormStartPosition.WindowsDefaultLocation;
00308 }
00309 else
00310 {
00311 State.IsWindowCreatedWithDefaultPositions = false;
00312 renderWindow.Location = new System.Drawing.Point(x, y);
00313 }
00314
00315
00316 System.Drawing.Size windowSize = DefaultStartingSize;
00317 if (State.OverrideWidth != 0)
00318 windowSize.Width = State.OverrideWidth;
00319 if (State.OverrideHeight != 0)
00320 windowSize.Height = State.OverrideHeight;
00321
00322 renderWindow.ClientSize = windowSize;
00323
00324
00325 State.WindowTitle = windowTitle;
00326 renderWindow.Text = windowTitle;
00327
00328
00329 System.Windows.Forms.Cursor.Current = System.Windows.Forms.Cursors.Default;
00330
00331
00332 renderWindow.Visible = false;
00333 renderWindow.CreateControl();
00334 State.ClientRectangle = renderWindow.ClientRectangle;
00335 State.WindowBoundsRectangle = renderWindow.Bounds;
00336
00337
00338 State.WasWindowCreated = true;
00339 State.WindowFocus = renderWindow;
00340 State.WindowDeviceFullScreen = renderWindow;
00341 State.WindowDeviceWindowed = renderWindow;
00342 }
00343 }
00344
00348 public void CreateWindow(string windowTitle)
00349 {
00350 CreateWindow(windowTitle, LoadFirstIconFromResource(), null, -1, -1);
00351 }
00357 public void SetWindow(System.Windows.Forms.Control windowFocus, System.Windows.Forms.Control windowDeviceFullscreen,
00358 System.Windows.Forms.Control windowDeviceWindowed, bool handleMessages)
00359 {
00360 if (State.IsInsideDeviceCallback)
00361 throw new InvalidOperationException("You cannot create a window from inside a callback.");
00362
00363 State.WasWindowCreateCalled = true;
00364
00365
00366
00367
00368 if ((windowDeviceFullscreen == null) || (windowDeviceWindowed == null)
00369 || (windowFocus == null))
00370 {
00371 throw new InvalidOperationException("You must pass in valid window handles.");
00372 }
00373
00374 if (handleMessages)
00375 {
00376
00377 HookEvents(windowFocus);
00378 }
00379
00380
00381 if (!State.IsInited)
00382 {
00383
00384 if (State.WasInitCalled)
00385 {
00386 throw new InvalidOperationException("Initialize was already called and failed.");
00387 }
00388
00389
00390 Initialize(true, true, true);
00391 }
00392
00393
00394 State.ClientRectangle = windowDeviceWindowed.ClientRectangle;
00395 State.WindowBoundsRectangle = windowDeviceWindowed.Bounds;
00396
00397
00398 State.WasWindowCreated = true;
00399 State.WindowFocus = windowFocus;
00400 State.WindowDeviceFullScreen = windowDeviceFullscreen;
00401 State.WindowDeviceWindowed = windowDeviceWindowed;
00402 }
00403
00404
00410 public void SetWinformWindow(System.Windows.Forms.Control windowFocus, System.Windows.Forms.Control windowDeviceFullscreen,
00411 System.Windows.Forms.Control windowDeviceWindowed)
00412 {
00413 if (State.IsInsideDeviceCallback)
00414 throw new InvalidOperationException("You cannot create a window from inside a callback.");
00415
00416 State.WasWindowCreateCalled = true;
00417
00418
00419
00420
00421 if ((windowDeviceFullscreen == null) || (windowDeviceWindowed == null)
00422 || (windowFocus == null))
00423 {
00424 throw new InvalidOperationException("You must pass in valid window handles.");
00425 }
00426
00427
00428 if (!State.IsInited)
00429 {
00430
00431 if (State.WasInitCalled)
00432 {
00433 throw new InvalidOperationException("Initialize was already called and failed.");
00434 }
00435
00436
00437 Initialize(true, true, true);
00438 }
00439
00440
00441 State.WasWindowCreated = true;
00442 State.WindowFocus = windowFocus;
00443 State.WindowDeviceFullScreen = windowDeviceFullscreen;
00444 State.WindowDeviceWindowed = windowDeviceWindowed;
00445 }
00446
00452 public void CreateDevice(uint adapterOridinal, bool windowed, int suggestedWidth,
00453 int suggestedHeight, IDeviceCreation callback)
00454 {
00455 if (State.IsInsideDeviceCallback)
00456 throw new InvalidOperationException("You cannot create a window from inside a callback.");
00457
00458
00459 SetDeviceCreationInterface(callback);
00460
00461
00462 State.WasDeviceCreateCalled = true;
00463
00464
00465 if (!State.WasWindowCreated)
00466 {
00467
00468 if (State.WasWindowCreateCalled)
00469 {
00470 throw new InvalidOperationException("CreateWindow was already called and failed.");
00471 }
00472
00473
00474 CreateWindow("Direct3D Window", null, null, -1, -1);
00475 }
00476
00477
00478 Enumeration.Enumerate(State.DeviceCreationInterface);
00479
00480
00481 MatchOptions match = new MatchOptions();
00482 match.AdapterOrdinal = MatchType.PreserveInput;
00483 match.DeviceType = MatchType.IgnoreInput;
00484 match.IsWindowed = MatchType.PreserveInput;
00485 match.AdapterFormat = MatchType.IgnoreInput;
00486 match.VertexProcessing = MatchType.IgnoreInput;
00487 match.Resolution = MatchType.ClosestToInput;
00488 match.BackBufferFormat = MatchType.IgnoreInput;
00489 match.BackBufferCount = MatchType.IgnoreInput;
00490 match.MultiSample = MatchType.IgnoreInput;
00491 match.SwapEffect = MatchType.IgnoreInput;
00492 match.DepthFormat = MatchType.IgnoreInput;
00493 match.StencilFormat = MatchType.IgnoreInput;
00494 match.PresentFlags = MatchType.IgnoreInput;
00495 match.RefreshRate = MatchType.IgnoreInput;
00496 match.PresentInterval = MatchType.IgnoreInput;
00497
00498
00499 DeviceSettings settings = new DeviceSettings();
00500 settings.presentParams = new PresentParameters();
00501 settings.AdapterOrdinal = adapterOridinal;
00502 settings.presentParams.IsWindowed = windowed;
00503 settings.presentParams.BackBufferWidth = suggestedWidth;
00504 settings.presentParams.BackBufferHeight = suggestedHeight;
00505
00506
00507 if (State.OverrideWidth != 0)
00508 settings.presentParams.BackBufferWidth = State.OverrideWidth;
00509 if (State.OverrideHeight != 0)
00510 settings.presentParams.BackBufferHeight = State.OverrideHeight;
00511 if (State.OverrideAdapterOrdinal != -1)
00512 settings.AdapterOrdinal = (uint)State.OverrideAdapterOrdinal;
00513
00514 if (State.IsOverridingFullScreen)
00515 {
00516 settings.presentParams.IsWindowed = false;
00517 if ((State.OverrideWidth == 0) && (State.OverrideHeight == 0))
00518 match.Resolution = MatchType.IgnoreInput;
00519 }
00520 if (State.IsOverridingWindowed)
00521 settings.presentParams.IsWindowed = true;
00522
00523 if (State.IsOverridingForceHardware)
00524 {
00525 settings.DeviceType = DeviceType.Hardware;
00526 match.DeviceType = MatchType.PreserveInput;
00527 }
00528 if (State.IsOverridingForceReference)
00529 {
00530 settings.DeviceType = DeviceType.Reference;
00531 match.DeviceType = MatchType.PreserveInput;
00532 }
00533 if (State.IsOverridingForcePureHardwareVertexProcessing)
00534 {
00535 settings.BehaviorFlags = CreateFlags.HardwareVertexProcessing | CreateFlags.PureDevice;
00536 match.VertexProcessing = MatchType.PreserveInput;
00537 }
00538 if (State.IsOverridingForceHardwareVertexProcessing)
00539 {
00540 settings.BehaviorFlags = CreateFlags.HardwareVertexProcessing;
00541 match.VertexProcessing = MatchType.PreserveInput;
00542 }
00543 if (State.IsOverridingForceSoftwareVertexProcessing)
00544 {
00545 settings.BehaviorFlags = CreateFlags.SoftwareVertexProcessing;
00546 match.VertexProcessing = MatchType.PreserveInput;
00547 }
00548
00549 try
00550 {
00551 settings = FindValidDeviceSettings(settings, match);
00552 }
00553 catch (Exception e)
00554 {
00555 DisplayErrorMessage(e);
00556 throw;
00557 }
00558
00559
00560
00561 if (State.DeviceCreationInterface != null)
00562 {
00563 Capabilities c = Manager.GetDeviceCapabilities((int)settings.AdapterOrdinal, settings.DeviceType);
00564 State.DeviceCreationInterface.ModifyDeviceSettings(settings, c);
00565 }
00566
00567
00568
00569 ChangeDevice(settings, null, false);
00570 }
00571
00572
00579 public void CreateDevice(int adapterOridinal, bool windowed, int suggestedWidth,
00580 int suggestedHeight, IDeviceCreation callback)
00581 {
00582 CreateDevice((uint)adapterOridinal, windowed, suggestedWidth,
00583 suggestedHeight, callback);
00584 }
00585
00586
00593 public void SetDevice(Device device)
00594 {
00595 if (device == null)
00596 throw new ArgumentNullException("device", "You cannot pass in a null device to SetDevice");
00597
00598 if (State.IsInsideDeviceCallback)
00599 throw new InvalidOperationException("You cannot set a device from inside a callback.");
00600
00601
00602 if (!State.WasWindowCreated)
00603 {
00604
00605 if (State.WasWindowCreateCalled)
00606 {
00607 throw new InvalidOperationException("CreateWindow was already called and failed.");
00608 }
00609
00610
00611 CreateWindow("Direct3D Window", null, null, -1, -1);
00612 }
00613
00614 DeviceSettings deviceSettings = new DeviceSettings();
00615
00616
00617 using (Surface backBuffer = device.GetBackBuffer(0, 0))
00618 {
00619 using (SwapChain swap = backBuffer.GetContainer(Constants.SwapChain) as SwapChain)
00620 {
00621 deviceSettings.presentParams = swap.PresentParameters;
00622 System.Diagnostics.Debug.Assert(deviceSettings.presentParams != null, "You must have valid present parameters here.");
00623 }
00624 }
00625
00626 DeviceCreationParameters creationParams = device.CreationParameters;
00627
00628
00629 deviceSettings.AdapterOrdinal = (uint)creationParams.AdapterOrdinal;
00630 deviceSettings.DeviceType = creationParams.DeviceType;
00631 deviceSettings.AdapterFormat = FindAdapterFormat(deviceSettings.AdapterOrdinal,
00632 deviceSettings.DeviceType, deviceSettings.presentParams.BackBufferFormat,
00633 deviceSettings.presentParams.IsWindowed);
00634 deviceSettings.BehaviorFlags = creationParams.BehaviorFlags.Value;
00635
00636
00637 ChangeDevice(deviceSettings, device, false);
00638 }
00639
00646 public void CreateDeviceFromSettings(DeviceSettings deviceSettings, bool preserveInput)
00647 {
00648
00649 State.WasDeviceCreateCalled = true;
00650
00651
00652 if (!State.WasWindowCreated)
00653 {
00654
00655 if (State.WasWindowCreateCalled)
00656 {
00657 throw new InvalidOperationException("CreateWindow was already called and failed.");
00658 }
00659
00660
00661 CreateWindow("Direct3D Window", null, null, -1, -1);
00662 }
00663
00664 if (!preserveInput)
00665 {
00666
00667 MatchOptions match = new MatchOptions();
00668 match.AdapterOrdinal = MatchType.ClosestToInput;
00669 match.DeviceType = MatchType.ClosestToInput;
00670 match.IsWindowed = MatchType.ClosestToInput;
00671 match.AdapterFormat = MatchType.ClosestToInput;
00672 match.VertexProcessing = MatchType.ClosestToInput;
00673 match.Resolution = MatchType.ClosestToInput;
00674 match.BackBufferFormat = MatchType.ClosestToInput;
00675 match.BackBufferCount = MatchType.ClosestToInput;
00676 match.MultiSample = MatchType.ClosestToInput;
00677 match.SwapEffect = MatchType.ClosestToInput;
00678 match.DepthFormat = MatchType.ClosestToInput;
00679 match.StencilFormat = MatchType.ClosestToInput;
00680 match.PresentFlags = MatchType.ClosestToInput;
00681 match.RefreshRate = MatchType.ClosestToInput;
00682 match.PresentInterval = MatchType.ClosestToInput;
00683
00684 try
00685 {
00686 deviceSettings = FindValidDeviceSettings(deviceSettings, match);
00687 }
00688 catch (Exception e)
00689 {
00690
00691 DisplayErrorMessage(e);
00692 throw;
00693 }
00694
00695
00696 ChangeDevice(deviceSettings, null, false);
00697 }
00698 }
00705 public void CreateDeviceFromSettings(DeviceSettings deviceSettings) { CreateDeviceFromSettings(deviceSettings, false); }
00706
00710 public void ToggleFullscreen()
00711 {
00712
00713 Pause(true, true);
00714
00715
00716
00717 DeviceSettings currentSettings = State.CurrentDeviceSettings.Clone();
00718 currentSettings.presentParams.IsWindowed = !currentSettings.presentParams.IsWindowed;
00719
00720 MatchOptions match = new MatchOptions();
00721 match.AdapterOrdinal = MatchType.PreserveInput;
00722 match.DeviceType = MatchType.ClosestToInput;
00723 match.IsWindowed = MatchType.PreserveInput;
00724 match.AdapterFormat = MatchType.IgnoreInput;
00725 match.VertexProcessing = MatchType.ClosestToInput;
00726 match.BackBufferFormat = MatchType.IgnoreInput;
00727 match.BackBufferCount = MatchType.ClosestToInput;
00728 match.MultiSample = MatchType.ClosestToInput;
00729 match.SwapEffect = MatchType.ClosestToInput;
00730 match.DepthFormat = MatchType.ClosestToInput;
00731 match.StencilFormat = MatchType.ClosestToInput;
00732 match.PresentFlags = MatchType.ClosestToInput;
00733 match.RefreshRate = MatchType.IgnoreInput;
00734 match.PresentInterval = MatchType.IgnoreInput;
00735
00736 System.Drawing.Rectangle windowClient;
00737 if (currentSettings.presentParams.IsWindowed)
00738 windowClient = State.ClientRectangle;
00739 else
00740 windowClient = State.FullScreenClientRectangle;
00741
00742 if (windowClient.Width > 0 && windowClient.Height > 0)
00743 {
00744 match.Resolution = MatchType.ClosestToInput;
00745 currentSettings.presentParams.BackBufferWidth = windowClient.Width;
00746 currentSettings.presentParams.BackBufferHeight = windowClient.Height;
00747 }
00748 else
00749 {
00750 match.Resolution = MatchType.IgnoreInput;
00751 }
00752
00753 try
00754 {
00755 if ((!currentSettings.presentParams.IsWindowed) && (State.IsMaximized))
00756 {
00757 if (WindowForm != null)
00758 {
00759 WindowForm.WindowState = System.Windows.Forms.FormWindowState.Normal;
00760 }
00761 toggleMaximized = true;
00762 }
00763 currentSettings = FindValidDeviceSettings(currentSettings, match);
00764 ChangeDevice(currentSettings, null, false);
00765 Window.Size = State.WindowBoundsRectangle.Size;
00766 Window.Location = State.WindowBoundsRectangle.Location;
00767 if (currentSettings.presentParams.IsWindowed)
00768 {
00769 if (toggleMaximized)
00770 {
00771 if (WindowForm != null)
00772 {
00773 WindowForm.WindowState = System.Windows.Forms.FormWindowState.Maximized;
00774 }
00775 }
00776 toggleMaximized = false;
00777 }
00778 }
00779 finally
00780 {
00781
00782 Pause(false, false);
00783 State.CurrentDeviceSettings = currentSettings;
00784 }
00785 }
00786
00787
00791 public void ToggleReference()
00792 {
00793
00794 DeviceSettings currentSettings = State.CurrentDeviceSettings.Clone();
00795 if (currentSettings.DeviceType == DeviceType.Hardware)
00796 currentSettings.DeviceType = DeviceType.Reference;
00797 else if (currentSettings.DeviceType == DeviceType.Reference)
00798 currentSettings.DeviceType = DeviceType.Hardware;
00799
00800 MatchOptions match = new MatchOptions();
00801 match.AdapterOrdinal = MatchType.PreserveInput;
00802 match.DeviceType = MatchType.PreserveInput;
00803 match.IsWindowed = MatchType.ClosestToInput;
00804 match.AdapterFormat = MatchType.ClosestToInput;
00805 match.VertexProcessing = MatchType.ClosestToInput;
00806 match.Resolution = MatchType.ClosestToInput;
00807 match.BackBufferFormat = MatchType.ClosestToInput;
00808 match.BackBufferCount = MatchType.ClosestToInput;
00809 match.MultiSample = MatchType.ClosestToInput;
00810 match.SwapEffect = MatchType.ClosestToInput;
00811 match.DepthFormat = MatchType.ClosestToInput;
00812 match.StencilFormat = MatchType.ClosestToInput;
00813 match.PresentFlags = MatchType.ClosestToInput;
00814 match.RefreshRate = MatchType.ClosestToInput;
00815 match.PresentInterval = MatchType.ClosestToInput;
00816
00817 try
00818 {
00819 currentSettings = FindValidDeviceSettings(currentSettings, match);
00820 ChangeDevice(currentSettings, null, false);
00821 }
00822 #if(DEBUG)
00823 catch (Exception e)
00824 {
00825
00826 DisplayErrorMessage(e);
00827 #else
00828 catch
00829 {
00830
00831 #endif
00832 }
00833 finally
00834 {
00835
00836 State.CurrentDeviceSettings = currentSettings;
00837 }
00838 }
00839
00855 private DeviceSettings FindValidDeviceSettings(DeviceSettings settings, MatchOptions match)
00856 {
00857
00858
00859
00860
00861 DeviceSettings optimalSettings = BuildOptimalDeviceSettings(settings, match);
00862 float bestRanking = -1.0f;
00863 EnumDeviceSettingsCombo bestDeviceSettingsCombo = new EnumDeviceSettingsCombo();
00864
00865
00866
00867
00868
00869
00870
00871
00872
00873 DisplayMode adapterDesktopDisplayMode;
00874 for (int iAdapter = 0; iAdapter < Enumeration.AdapterInformationList.Count; iAdapter++)
00875 {
00876 EnumAdapterInformation adapterInfo = Enumeration.AdapterInformationList[iAdapter] as EnumAdapterInformation;
00877
00878
00879 adapterDesktopDisplayMode = Manager.Adapters[(int)adapterInfo.AdapterOrdinal].CurrentDisplayMode;
00880
00881
00882 for (int iDeviceInfo = 0; iDeviceInfo < adapterInfo.deviceInfoList.Count; iDeviceInfo++)
00883 {
00884 EnumDeviceInformation deviceInfo = adapterInfo.deviceInfoList[iDeviceInfo] as EnumDeviceInformation;
00885 for (int iDeviceCombo = 0; iDeviceCombo < deviceInfo.deviceSettingsList.Count; iDeviceCombo++)
00886 {
00887 EnumDeviceSettingsCombo deviceSettings = deviceInfo.deviceSettingsList[iDeviceCombo];
00888
00889
00890 if (deviceSettings.IsWindowed && (deviceSettings.AdapterFormat != adapterDesktopDisplayMode.Format))
00891 continue;
00892
00893
00894 if (!DoesDeviceComboMatchPreserveOptions(deviceSettings, settings, match))
00895 continue;
00896
00897
00898 float curRanking = RankDeviceCombo(deviceSettings, optimalSettings, adapterDesktopDisplayMode);
00899
00900
00901 if (curRanking > bestRanking)
00902 {
00903 bestDeviceSettingsCombo = deviceSettings;
00904 bestRanking = curRanking;
00905 }
00906 }
00907 }
00908 }
00909
00910
00911 if (bestRanking == -1.0f)
00912 {
00913 throw new NoCompatibleDevicesException();
00914 }
00915
00916
00917
00918 return BuildValidDeviceSettings(bestDeviceSettingsCombo, settings, match);
00919 }
00923 private DeviceSettings FindValidDeviceSettings(DeviceSettings settings)
00924 {
00925 return FindValidDeviceSettings(settings, new MatchOptions());
00926 }
00927
00934 private DeviceSettings BuildOptimalDeviceSettings(DeviceSettings settings, MatchOptions match)
00935 {
00936 DeviceSettings optimal = new DeviceSettings();
00937 optimal.presentParams = new PresentParameters();
00938
00939
00940
00941
00942 if (match.AdapterOrdinal == MatchType.IgnoreInput)
00943 optimal.AdapterOrdinal = 0;
00944 else
00945 optimal.AdapterOrdinal = settings.AdapterOrdinal;
00946
00947
00948
00949
00950 if (match.DeviceType == MatchType.IgnoreInput)
00951 optimal.DeviceType = DeviceType.Hardware;
00952 else
00953 optimal.DeviceType = settings.DeviceType;
00954
00955
00956
00957
00958 if (match.IsWindowed == MatchType.IgnoreInput)
00959 optimal.presentParams.IsWindowed = true;
00960 else
00961 optimal.presentParams.IsWindowed = settings.presentParams.IsWindowed;
00962
00963
00964
00965
00966 if (match.AdapterFormat == MatchType.IgnoreInput)
00967 {
00968
00969
00970
00971 DisplayMode adapterDesktopMode = Manager.Adapters[(int)optimal.AdapterOrdinal].CurrentDisplayMode;
00972
00973 if (optimal.presentParams.IsWindowed ||
00974 ManagedUtility.GetColorChannelBits(adapterDesktopMode.Format) >= 8)
00975 optimal.AdapterFormat = adapterDesktopMode.Format;
00976 else
00977 optimal.AdapterFormat = Format.X8R8G8B8;
00978 }
00979 else
00980 {
00981 optimal.AdapterFormat = settings.AdapterFormat;
00982 }
00983
00984
00985
00986
00987 if (match.VertexProcessing == MatchType.IgnoreInput)
00988 optimal.BehaviorFlags = CreateFlags.HardwareVertexProcessing;
00989 else
00990 optimal.BehaviorFlags = settings.BehaviorFlags;
00991
00992
00993
00994
00995 if (match.Resolution == MatchType.IgnoreInput)
00996 {
00997
00998
00999 if (optimal.presentParams.IsWindowed)
01000 {
01001 optimal.presentParams.BackBufferWidth = DefaultSizeWidth;
01002 optimal.presentParams.BackBufferHeight = DefaultSizeHeight;
01003 }
01004 else
01005 {
01006 DisplayMode adapterDesktopMode = Manager.Adapters[(int)optimal.AdapterOrdinal].CurrentDisplayMode;
01007
01008 optimal.presentParams.BackBufferWidth = adapterDesktopMode.Width;
01009 optimal.presentParams.BackBufferHeight = adapterDesktopMode.Height;
01010 }
01011 }
01012 else
01013 {
01014 optimal.presentParams.BackBufferWidth = settings.presentParams.BackBufferWidth;
01015 optimal.presentParams.BackBufferHeight = settings.presentParams.BackBufferHeight;
01016 }
01017
01018
01019
01020
01021 if (match.BackBufferFormat == MatchType.IgnoreInput)
01022 optimal.presentParams.BackBufferFormat = optimal.AdapterFormat;
01023 else
01024 optimal.presentParams.BackBufferFormat = settings.presentParams.BackBufferFormat;
01025
01026
01027
01028
01029 if (match.BackBufferCount == MatchType.IgnoreInput)
01030 optimal.presentParams.BackBufferCount = 2;
01031 else
01032 optimal.presentParams.BackBufferCount = settings.presentParams.BackBufferCount;
01033
01034
01035
01036
01037 if (match.MultiSample == MatchType.IgnoreInput)
01038 optimal.presentParams.MultiSampleQuality = 0;
01039 else
01040 optimal.presentParams.MultiSampleQuality = settings.presentParams.MultiSampleQuality;
01041
01042
01043
01044
01045 if (match.SwapEffect == MatchType.IgnoreInput)
01046 optimal.presentParams.SwapEffect = SwapEffect.Discard;
01047 else
01048 optimal.presentParams.SwapEffect = settings.presentParams.SwapEffect;
01049
01050
01051
01052
01053 if (match.DepthFormat == MatchType.IgnoreInput &&
01054 match.StencilFormat == MatchType.IgnoreInput)
01055 {
01056 uint backBufferBits = ManagedUtility.GetColorChannelBits(optimal.presentParams.BackBufferFormat);
01057 if (backBufferBits >= 8)
01058 optimal.presentParams.AutoDepthStencilFormat = DepthFormat.D32;
01059 else
01060 optimal.presentParams.AutoDepthStencilFormat = DepthFormat.D16;
01061 }
01062 else
01063 {
01064 optimal.presentParams.AutoDepthStencilFormat = settings.presentParams.AutoDepthStencilFormat;
01065 }
01066
01067
01068
01069
01070 if (match.PresentFlags == MatchType.IgnoreInput)
01071 optimal.presentParams.PresentFlag = PresentFlag.DiscardDepthStencil;
01072 else
01073 optimal.presentParams.PresentFlag = settings.presentParams.PresentFlag;
01074
01075
01076
01077
01078 if (match.RefreshRate == MatchType.IgnoreInput)
01079 optimal.presentParams.FullScreenRefreshRateInHz = 0;
01080 else
01081 optimal.presentParams.FullScreenRefreshRateInHz = settings.presentParams.FullScreenRefreshRateInHz;
01082
01083
01084
01085
01086 if (match.PresentInterval == MatchType.IgnoreInput)
01087 {
01088
01089
01090
01091
01092
01093 if (optimal.presentParams.IsWindowed)
01094 optimal.presentParams.PresentationInterval = PresentInterval.Immediate;
01095 else
01096 optimal.presentParams.PresentationInterval = PresentInterval.Default;
01097 }
01098 else
01099 {
01100 optimal.presentParams.PresentationInterval = settings.presentParams.PresentationInterval;
01101 }
01102
01103 return optimal;
01104 }
01105
01106
01111 private DeviceSettings BuildValidDeviceSettings(EnumDeviceSettingsCombo deviceCombo, DeviceSettings settings, MatchOptions match)
01112 {
01113 DeviceSettings validSettings = new DeviceSettings();
01114 DisplayMode adapterDesktopDisplayMode = Manager.Adapters[(int)deviceCombo.AdapterOrdinal].CurrentDisplayMode;
01115
01116
01117
01118
01119
01120
01121
01122
01123
01124
01125
01126
01127
01128
01129
01130
01131
01132
01133
01134
01135
01136
01137
01138
01139
01140
01141
01142 CreateFlags bestBehaviorFlags = 0;
01143 if (match.VertexProcessing == MatchType.PreserveInput)
01144 {
01145 bestBehaviorFlags = settings.BehaviorFlags;
01146 }
01147 else if (match.VertexProcessing == MatchType.IgnoreInput)
01148 {
01149
01150 if (deviceCombo.deviceInformation.Caps.DeviceCaps.SupportsHardwareTransformAndLight)
01151 bestBehaviorFlags |= CreateFlags.HardwareVertexProcessing;
01152 else
01153 bestBehaviorFlags |= CreateFlags.SoftwareVertexProcessing;
01154 }
01155 else
01156 {
01157
01158 bestBehaviorFlags = settings.BehaviorFlags;
01159 if ((!deviceCombo.deviceInformation.Caps.DeviceCaps.SupportsHardwareTransformAndLight) &&
01160 ((bestBehaviorFlags & CreateFlags.HardwareVertexProcessing) != 0 ||
01161 (bestBehaviorFlags & CreateFlags.MixedVertexProcessing) != 0))
01162 {
01163 bestBehaviorFlags &= ~CreateFlags.HardwareVertexProcessing;
01164 bestBehaviorFlags &= ~CreateFlags.MixedVertexProcessing;
01165 bestBehaviorFlags |= CreateFlags.SoftwareVertexProcessing;
01166 }
01167
01168
01169 if ((bestBehaviorFlags & CreateFlags.HardwareVertexProcessing) == 0 &&
01170 (bestBehaviorFlags & CreateFlags.MixedVertexProcessing) == 0 &&
01171 (bestBehaviorFlags & CreateFlags.SoftwareVertexProcessing) == 0)
01172 {
01173 if (deviceCombo.deviceInformation.Caps.DeviceCaps.SupportsHardwareTransformAndLight)
01174 bestBehaviorFlags |= CreateFlags.HardwareVertexProcessing;
01175 else
01176 bestBehaviorFlags |= CreateFlags.SoftwareVertexProcessing;
01177 }
01178 }
01179
01180
01181
01182
01183 DisplayMode bestDisplayMode = new DisplayMode();
01184 if (match.Resolution == MatchType.PreserveInput)
01185 {
01186 bestDisplayMode.Width = settings.presentParams.BackBufferWidth;
01187 bestDisplayMode.Height = settings.presentParams.BackBufferHeight;
01188 }
01189 else
01190 {
01191 DisplayMode displayModeIn = new DisplayMode();
01192 if (match.Resolution == MatchType.ClosestToInput &&
01193 (settings.presentParams.BackBufferWidth != 0 && settings.presentParams.BackBufferWidth != 0))
01194 {
01195 displayModeIn.Width = settings.presentParams.BackBufferWidth;
01196 displayModeIn.Height = settings.presentParams.BackBufferHeight;
01197 }
01198 else
01199 {
01200 if (deviceCombo.IsWindowed)
01201 {
01202
01203 displayModeIn.Width = DefaultSizeWidth;
01204 displayModeIn.Height = DefaultSizeHeight;
01205 }
01206 else
01207 {
01208
01209 displayModeIn.Width = adapterDesktopDisplayMode.Width;
01210 displayModeIn.Height = adapterDesktopDisplayMode.Height;
01211 }
01212 }
01213
01214
01215 bestDisplayMode = FindValidResolution(deviceCombo, displayModeIn);
01216 }
01217
01218
01219
01220
01221
01222
01223
01224
01225
01226 uint bestBackBufferCount;
01227 if (match.BackBufferCount == MatchType.PreserveInput)
01228 {
01229 bestBackBufferCount = (uint)settings.presentParams.BackBufferCount;
01230 }
01231 else if (match.BackBufferCount == MatchType.IgnoreInput)
01232 {
01233
01234 bestBackBufferCount = 2;
01235 }
01236 else
01237 {
01238 bestBackBufferCount = (uint)settings.presentParams.BackBufferCount;
01239 if (bestBackBufferCount > 3)
01240 bestBackBufferCount = 3;
01241 if (bestBackBufferCount < 1)
01242 bestBackBufferCount = 1;
01243 }
01244
01245
01246
01247
01248 MultiSampleType bestMultiSampleType;
01249 uint bestMultiSampleQuality;
01250 if (settings.presentParams.SwapEffect != SwapEffect.Discard)
01251 {
01252
01253 bestMultiSampleType = MultiSampleType.None;
01254 bestMultiSampleQuality = 0;
01255 }
01256 else
01257 {
01258 if (match.BackBufferCount == MatchType.PreserveInput)
01259 {
01260 bestMultiSampleType = settings.presentParams.MultiSampleType;
01261 bestMultiSampleQuality = (uint)settings.presentParams.MultiSampleQuality;
01262 }
01263 else if (match.BackBufferCount == MatchType.IgnoreInput)
01264 {
01265
01266 bestMultiSampleType = MultiSampleType.None;
01267 bestMultiSampleQuality = 0;
01268 }
01269 else if (match.BackBufferCount == MatchType.ClosestToInput)
01270 {
01271
01272 bestMultiSampleType = MultiSampleType.None;
01273 bestMultiSampleQuality = 0;
01274
01275 for (int i = 0; i < deviceCombo.multiSampleTypeList.Count; i++)
01276 {
01277 MultiSampleType tempType = (MultiSampleType)deviceCombo.multiSampleTypeList[i];
01278 uint tempQuality = (uint)(int)deviceCombo.multiSampleQualityList[i];
01279
01280
01281 if (Math.Abs((int)tempType - (int)settings.presentParams.MultiSampleType) < Math.Abs((int)bestMultiSampleType - (int)settings.presentParams.MultiSampleType))
01282 {
01283 bestMultiSampleType = tempType;
01284 bestMultiSampleQuality = (uint)Math.Min(tempQuality - 1, settings.presentParams.MultiSampleQuality);
01285 }
01286 }
01287 }
01288 else
01289 {
01290
01291 bestMultiSampleType = MultiSampleType.None;
01292 bestMultiSampleQuality = 0;
01293 }
01294 }
01295
01296
01297
01298
01299 SwapEffect bestSwapEffect;
01300 if (match.SwapEffect == MatchType.PreserveInput)
01301 {
01302 bestSwapEffect = settings.presentParams.SwapEffect;
01303 }
01304 else if (match.SwapEffect == MatchType.IgnoreInput)
01305 {
01306 bestSwapEffect = SwapEffect.Discard;
01307 }
01308 else
01309 {
01310 bestSwapEffect = settings.presentParams.SwapEffect;
01311
01312
01313 if (bestSwapEffect != SwapEffect.Discard &&
01314 bestSwapEffect != SwapEffect.Flip &&
01315 bestSwapEffect != SwapEffect.Copy)
01316 {
01317 bestSwapEffect = SwapEffect.Discard;
01318 }
01319 }
01320
01321
01322
01323
01324 DepthFormat bestDepthStencilFormat;
01325 bool bestEnableAutoDepthStencil;
01326
01327 int[] depthStencilRanking = new int[deviceCombo.depthStencilFormatList.Count];
01328
01329 uint backBufferBitDepth = ManagedUtility.GetColorChannelBits(deviceCombo.BackBufferFormat);
01330 uint inputDepthBitDepth = ManagedUtility.GetDepthBits(settings.presentParams.AutoDepthStencilFormat);
01331
01332 for (int i = 0; i < deviceCombo.depthStencilFormatList.Count; i++)
01333 {
01334 DepthFormat curDepthStencilFmt = (DepthFormat)deviceCombo.depthStencilFormatList[i];
01335 uint curDepthBitDepth = ManagedUtility.GetDepthBits(curDepthStencilFmt);
01336 int ranking;
01337
01338 if (match.DepthFormat == MatchType.PreserveInput)
01339 {
01340
01341 if (curDepthBitDepth == inputDepthBitDepth)
01342 ranking = 0;
01343 else
01344 ranking = 10000;
01345 }
01346 else if (match.DepthFormat == MatchType.IgnoreInput)
01347 {
01348
01349 ranking = Math.Abs((int)curDepthBitDepth - (int)(backBufferBitDepth * 4));
01350 }
01351 else
01352 {
01353
01354 ranking = Math.Abs((int)curDepthBitDepth - (int)inputDepthBitDepth);
01355 }
01356
01357 depthStencilRanking[i] = ranking;
01358 }
01359
01360 uint inputStencilBitDepth = ManagedUtility.GetStencilBits(settings.presentParams.AutoDepthStencilFormat);
01361
01362 for (int i = 0; i < deviceCombo.depthStencilFormatList.Count; i++)
01363 {
01364 DepthFormat curDepthStencilFmt = (DepthFormat)deviceCombo.depthStencilFormatList[i];
01365 int ranking = depthStencilRanking[i];
01366 uint curStencilBitDepth = ManagedUtility.GetStencilBits(curDepthStencilFmt);
01367
01368 if (match.StencilFormat == MatchType.PreserveInput)
01369 {
01370
01371 if (curStencilBitDepth == inputStencilBitDepth)
01372 ranking += 0;
01373 else
01374 ranking += 10000;
01375 }
01376 else if (match.StencilFormat == MatchType.IgnoreInput)
01377 {
01378
01379 ranking += (int)curStencilBitDepth;
01380 }
01381 else
01382 {
01383
01384 ranking += Math.Abs((int)curStencilBitDepth - (int)inputStencilBitDepth);
01385 }
01386
01387 depthStencilRanking[i] = ranking;
01388 }
01389
01390 int bestRanking = 100000;
01391 int bestIndex = -1;
01392 for (int i = 0; i < depthStencilRanking.Length; i++)
01393 {
01394 if (depthStencilRanking[i] < bestRanking)
01395 {
01396 bestRanking = depthStencilRanking[i];
01397 bestIndex = i;
01398 }
01399 }
01400
01401 if (bestIndex >= 0)
01402 {
01403 bestDepthStencilFormat = (DepthFormat)deviceCombo.depthStencilFormatList[bestIndex];
01404 bestEnableAutoDepthStencil = true;
01405 }
01406 else
01407 {
01408 bestDepthStencilFormat = DepthFormat.Unknown;
01409 bestEnableAutoDepthStencil = false;
01410 }
01411
01412
01413
01414
01415
01416 PresentFlag bestPresentFlag;
01417 if (match.PresentFlags == MatchType.PreserveInput)
01418 {
01419 bestPresentFlag = settings.presentParams.PresentFlag;
01420 }
01421 else if (match.PresentFlags == MatchType.IgnoreInput)
01422 {
01423 bestPresentFlag = 0;
01424 if (bestEnableAutoDepthStencil)
01425 bestPresentFlag = PresentFlag.DiscardDepthStencil;
01426 }
01427 else
01428 {
01429 bestPresentFlag = settings.presentParams.PresentFlag;
01430 if (bestEnableAutoDepthStencil)
01431 bestPresentFlag |= PresentFlag.DiscardDepthStencil;
01432 }
01433
01434
01435
01436
01437 if (deviceCombo.IsWindowed)
01438 {
01439
01440 bestDisplayMode.RefreshRate = 0;
01441 }
01442 else
01443 {
01444 if (match.RefreshRate == MatchType.PreserveInput)
01445 {
01446 bestDisplayMode.RefreshRate = settings.presentParams.FullScreenRefreshRateInHz;
01447 }
01448 else
01449 {
01450 uint refreshRateMatch;
01451 if (match.RefreshRate == MatchType.ClosestToInput)
01452 {
01453 refreshRateMatch = (uint)settings.presentParams.FullScreenRefreshRateInHz;
01454 }
01455 else
01456 {
01457 refreshRateMatch = (uint)adapterDesktopDisplayMode.RefreshRate;
01458 }
01459
01460 bestDisplayMode.RefreshRate = 0;
01461
01462 if (refreshRateMatch != 0)
01463 {
01464 int bestRefreshRanking = 100000;
01465 for (int iDisplayMode = 0; iDisplayMode < deviceCombo.adapterInformation.displayModeList.Count; iDisplayMode++)
01466 {
01467 DisplayMode displayMode = (DisplayMode)deviceCombo.adapterInformation.displayModeList[iDisplayMode];
01468 if (displayMode.Format != deviceCombo.AdapterFormat ||
01469 displayMode.Height != bestDisplayMode.Height ||
01470 displayMode.Width != bestDisplayMode.Width)
01471 continue;
01472
01473
01474 int currentRefreshRanking = Math.Abs((int)displayMode.RefreshRate - (int)refreshRateMatch);
01475
01476 if (currentRefreshRanking < bestRefreshRanking)
01477 {
01478 bestDisplayMode.RefreshRate = displayMode.RefreshRate;
01479 bestRefreshRanking = currentRefreshRanking;
01480
01481
01482 if (bestRefreshRanking == 0)
01483 break;
01484 }
01485 }
01486 }
01487 }
01488 }
01489
01490
01491
01492
01493 PresentInterval bestPresentInterval;
01494 if (match.PresentInterval == MatchType.PreserveInput)
01495 {
01496 bestPresentInterval = settings.presentParams.PresentationInterval;
01497 }
01498 else if (match.PresentInterval == MatchType.IgnoreInput)
01499 {
01500 if (deviceCombo.IsWindowed)
01501 {
01502
01503
01504
01505 bestPresentInterval = PresentInterval.Immediate;
01506 }
01507 else
01508 {
01509
01510
01511 bestPresentInterval = PresentInterval.Default;
01512 }
01513 }
01514 else
01515 {
01516 if (deviceCombo.presentIntervalList.Contains(settings.presentParams.PresentationInterval))
01517 {
01518 bestPresentInterval = settings.presentParams.PresentationInterval;
01519 }
01520 else
01521 {
01522 if (deviceCombo.IsWindowed)
01523 bestPresentInterval = PresentInterval.Immediate;
01524 else
01525 bestPresentInterval = PresentInterval.Default;
01526 }
01527 }
01528
01529
01530 validSettings.AdapterOrdinal = deviceCombo.AdapterOrdinal;
01531 validSettings.DeviceType = deviceCombo.DeviceType;
01532 validSettings.AdapterFormat = deviceCombo.AdapterFormat;
01533 validSettings.BehaviorFlags = bestBehaviorFlags;
01534 validSettings.presentParams = new PresentParameters();
01535 validSettings.presentParams.BackBufferWidth = bestDisplayMode.Width;
01536 validSettings.presentParams.BackBufferHeight = bestDisplayMode.Height;
01537 validSettings.presentParams.BackBufferFormat = deviceCombo.BackBufferFormat;
01538 validSettings.presentParams.BackBufferCount = (int)bestBackBufferCount;
01539 validSettings.presentParams.MultiSampleType = bestMultiSampleType;
01540 validSettings.presentParams.MultiSampleQuality = (int)bestMultiSampleQuality;
01541 validSettings.presentParams.SwapEffect = bestSwapEffect;
01542 validSettings.presentParams.DeviceWindowHandle = deviceCombo.IsWindowed ? State.WindowDeviceWindowed.Handle : State.WindowDeviceFullScreen.Handle;
01543 validSettings.presentParams.IsWindowed = deviceCombo.IsWindowed;
01544 validSettings.presentParams.EnableAutoDepthStencil = bestEnableAutoDepthStencil;
01545 validSettings.presentParams.AutoDepthStencilFormat = bestDepthStencilFormat;
01546 validSettings.presentParams.PresentFlag = bestPresentFlag;
01547 validSettings.presentParams.FullScreenRefreshRateInHz = bestDisplayMode.RefreshRate;
01548 validSettings.presentParams.PresentationInterval = bestPresentInterval;
01549 validSettings.presentParams.DisableMultithreadedFlag = true;
01550
01551 return validSettings;
01552 }
01553
01554
01559 private bool DoesDeviceComboMatchPreserveOptions(EnumDeviceSettingsCombo deviceCombo, DeviceSettings settings, MatchOptions match)
01560 {
01561
01562
01563
01564 if (match.AdapterOrdinal == MatchType.PreserveInput &&
01565 (deviceCombo.AdapterOrdinal != settings.AdapterOrdinal))
01566 return false;
01567
01568
01569
01570
01571 if (match.DeviceType == MatchType.PreserveInput &&
01572 (deviceCombo.DeviceType != settings.DeviceType))
01573 return false;
01574
01575
01576
01577
01578 if (match.IsWindowed == MatchType.PreserveInput &&
01579 (deviceCombo.IsWindowed != settings.presentParams.IsWindowed))
01580 return false;
01581
01582
01583
01584
01585 if (match.AdapterFormat == MatchType.PreserveInput &&
01586 (deviceCombo.AdapterFormat != settings.AdapterFormat))
01587 return false;
01588
01589
01590
01591
01592
01593 if (match.VertexProcessing == MatchType.PreserveInput &&
01594 ((settings.BehaviorFlags & CreateFlags.HardwareVertexProcessing) != 0) &&
01595 (deviceCombo.deviceInformation.Caps.DeviceCaps.SupportsHardwareTransformAndLight))
01596 return false;
01597
01598
01599
01600
01601
01602 if (match.Resolution == MatchType.PreserveInput)
01603 {
01604 bool bFound = false;
01605 for (int i = 0; i < deviceCombo.adapterInformation.displayModeList.Count; i++)
01606 {
01607 DisplayMode displayMode = (DisplayMode)deviceCombo.adapterInformation.displayModeList[i];
01608 if (displayMode.Format != deviceCombo.AdapterFormat)
01609 continue;
01610
01611 if (displayMode.Width == settings.presentParams.BackBufferWidth &&
01612 displayMode.Height == settings.presentParams.BackBufferHeight)
01613 {
01614 bFound = true;
01615 break;
01616 }
01617 }
01618
01619
01620 if (!bFound)
01621 return false;
01622 }
01623
01624
01625
01626
01627 if (match.BackBufferFormat == MatchType.PreserveInput &&
01628 deviceCombo.BackBufferFormat != settings.presentParams.BackBufferFormat)
01629 return false;
01630
01631
01632
01633
01634
01635
01636
01637
01638
01639 if (match.MultiSample == MatchType.PreserveInput)
01640 {
01641 bool bFound = false;
01642 for (int i = 0; i < deviceCombo.multiSampleTypeList.Count; i++)
01643 {
01644 MultiSampleType msType = (MultiSampleType)deviceCombo.multiSampleTypeList[i];
01645 uint msQuality = (uint)(int)deviceCombo.multiSampleQualityList[i];
01646
01647 if (msType == settings.presentParams.MultiSampleType &&
01648 msQuality >= settings.presentParams.MultiSampleQuality)
01649 {
01650 bFound = true;
01651 break;
01652 }
01653 }
01654
01655
01656 if (!bFound)
01657 return false;
01658 }
01659
01660
01661
01662
01663
01664
01665
01666
01667
01668
01669 if (match.DepthFormat == MatchType.PreserveInput &&
01670 match.StencilFormat == MatchType.PreserveInput)
01671 {
01672 if (settings.presentParams.AutoDepthStencilFormat != (DepthFormat)Format.Unknown &&
01673 !deviceCombo.depthStencilFormatList.Contains(settings.presentParams.AutoDepthStencilFormat))
01674 return false;
01675 }
01676
01677
01678 if (match.DepthFormat == MatchType.PreserveInput &&
01679 settings.presentParams.AutoDepthStencilFormat != DepthFormat.Unknown)
01680 {
01681 bool bFound = false;
01682 uint depthBits = ManagedUtility.GetDepthBits(settings.presentParams.AutoDepthStencilFormat);
01683 for (int i = 0; i < deviceCombo.depthStencilFormatList.Count; i++)
01684 {
01685 DepthFormat depthStencilFmt = (DepthFormat)deviceCombo.depthStencilFormatList[i];
01686 uint curDepthBits = ManagedUtility.GetDepthBits(depthStencilFmt);
01687 if (curDepthBits - depthBits == 0)
01688 bFound = true;
01689 }
01690
01691 if (!bFound)
01692 return false;
01693 }
01694
01695
01696 if (match.StencilFormat == MatchType.PreserveInput &&
01697 settings.presentParams.AutoDepthStencilFormat != DepthFormat.Unknown)
01698 {
01699 bool bFound = false;
01700 uint stencilBits = ManagedUtility.GetStencilBits(settings.presentParams.AutoDepthStencilFormat);
01701 for (int i = 0; i < deviceCombo.depthStencilFormatList.Count; i++)
01702 {
01703 DepthFormat depthStencilFmt = (DepthFormat)deviceCombo.depthStencilFormatList[i];
01704 uint curStencilBits = ManagedUtility.GetStencilBits(depthStencilFmt);
01705 if (curStencilBits - stencilBits == 0)
01706 bFound = true;
01707 }
01708
01709 if (!bFound)
01710 return false;
01711 }
01712
01713
01714
01715
01716
01717
01718
01719
01720
01721
01722 if (match.RefreshRate == MatchType.PreserveInput)
01723 {
01724 bool bFound = false;
01725 for (int i = 0; i < deviceCombo.adapterInformation.displayModeList.Count; i++)
01726 {
01727 DisplayMode displayMode = (DisplayMode)deviceCombo.adapterInformation.displayModeList[i];
01728 if (displayMode.Format != deviceCombo.AdapterFormat)
01729 continue;
01730 if (displayMode.RefreshRate == settings.presentParams.FullScreenRefreshRateInHz)
01731 {
01732 bFound = true;
01733 break;
01734 }
01735 }
01736
01737
01738 if (!bFound)
01739 return false;
01740 }
01741
01742
01743
01744
01745
01746 if (match.PresentInterval == MatchType.PreserveInput &&
01747 !deviceCombo.presentIntervalList.Contains(settings.presentParams.PresentationInterval))
01748 return false;
01749
01750 return true;
01751 }
01752
01756 private float RankDeviceCombo(EnumDeviceSettingsCombo deviceCombo, DeviceSettings settings, DisplayMode adapterMode)
01757 {
01758 float currentRanking = 0.0f;
01759
01760
01761 const float adapterOrdinalWeight = 1000.0f;
01762 const float deviceTypeWeight = 100.0f;
01763 const float windowWeight = 10.0f;
01764 const float adapterFormatWeight = 1.0f;
01765 const float vertexProcessingWeight = 1.0f;
01766 const float resolutionWeight = 1.0f;
01767 const float backBufferFormatWeight = 1.0f;
01768 const float multiSampleWeight = 1.0f;
01769 const float depthStencilWeight = 1.0f;
01770 const float refreshRateWeight = 1.0f;
01771 const float presentIntervalWeight = 1.0f;
01772
01773
01774
01775
01776
01777 if (deviceCombo.AdapterOrdinal == settings.AdapterOrdinal)
01778 currentRanking += adapterOrdinalWeight;
01779
01780
01781
01782
01783 if (deviceCombo.DeviceType == settings.DeviceType)
01784 currentRanking += deviceTypeWeight;
01785
01786 if (deviceCombo.DeviceType == DeviceType.Hardware)
01787 currentRanking += 0.1f;
01788
01789
01790
01791
01792 if (deviceCombo.IsWindowed == settings.presentParams.IsWindowed)
01793 currentRanking += windowWeight;
01794
01795
01796
01797
01798 if (deviceCombo.AdapterFormat == settings.AdapterFormat)
01799 {
01800 currentRanking += adapterFormatWeight;
01801 }
01802 else
01803 {
01804 int bitDepthDelta = Math.Abs((int)ManagedUtility.GetColorChannelBits(deviceCombo.AdapterFormat) -
01805 (int)ManagedUtility.GetColorChannelBits(settings.AdapterFormat));
01806 float scale = Math.Max(0.9f - (float)bitDepthDelta * 0.2f, 0);
01807 currentRanking += scale * adapterFormatWeight;
01808 }
01809
01810 if (!deviceCombo.IsWindowed)
01811 {
01812
01813 bool isAdapterOptimalMatch;
01814 if (ManagedUtility.GetColorChannelBits(adapterMode.Format) >= 8)
01815 isAdapterOptimalMatch = (deviceCombo.AdapterFormat == adapterMode.Format);
01816 else
01817 isAdapterOptimalMatch = (deviceCombo.AdapterFormat == Format.X8R8G8B8);
01818
01819 if (isAdapterOptimalMatch)
01820 currentRanking += 0.1f;
01821 }
01822
01823
01824
01825
01826 if ((settings.BehaviorFlags & CreateFlags.HardwareVertexProcessing) != 0 ||
01827 (settings.BehaviorFlags & CreateFlags.MixedVertexProcessing) != 0)
01828 {
01829 if (deviceCombo.deviceInformation.Caps.DeviceCaps.SupportsHardwareTransformAndLight)
01830 currentRanking += vertexProcessingWeight;
01831 }
01832
01833 if (deviceCombo.deviceInformation.Caps.DeviceCaps.SupportsHardwareTransformAndLight)
01834 currentRanking += 0.1f;
01835
01836
01837
01838
01839 bool bResolutionFound = false;
01840 for (int idm = 0; idm < deviceCombo.adapterInformation.displayModeList.Count; idm++)
01841 {
01842 DisplayMode displayMode = (DisplayMode)deviceCombo.adapterInformation.displayModeList[idm];
01843 if (displayMode.Format != deviceCombo.AdapterFormat)
01844 continue;
01845 if (displayMode.Width == settings.presentParams.BackBufferWidth &&
01846 displayMode.Height == settings.presentParams.BackBufferHeight)
01847 bResolutionFound = true;
01848 }
01849 if (bResolutionFound)
01850 currentRanking += resolutionWeight;
01851
01852
01853
01854
01855 if (deviceCombo.BackBufferFormat == settings.presentParams.BackBufferFormat)
01856 {
01857 currentRanking += backBufferFormatWeight;
01858 }
01859 else
01860 {
01861 int bitDepthDelta = Math.Abs((int)ManagedUtility.GetColorChannelBits(deviceCombo.BackBufferFormat) -
01862 (int)ManagedUtility.GetColorChannelBits(settings.presentParams.BackBufferFormat));
01863 float scale = Math.Max(0.9f - (float)bitDepthDelta * 0.2f, 0);
01864 currentRanking += scale * backBufferFormatWeight;
01865 }
01866
01867
01868
01869 bool bAdapterMatchesBB = (deviceCombo.BackBufferFormat == deviceCombo.AdapterFormat);
01870 if (bAdapterMatchesBB)
01871 currentRanking += 0.1f;
01872
01873
01874
01875
01876
01877
01878
01879
01880
01881 bool bMultiSampleFound = false;
01882 for (int i = 0; i < deviceCombo.multiSampleTypeList.Count; i++)
01883 {
01884 MultiSampleType msType = (MultiSampleType)deviceCombo.multiSampleTypeList[i];
01885 uint msQuality = (uint)(int)deviceCombo.multiSampleQualityList[i];
01886
01887 if (msType == settings.presentParams.MultiSampleType &&
01888 msQuality >= settings.presentParams.MultiSampleQuality)
01889 {
01890 bMultiSampleFound = true;
01891 break;
01892 }
01893 }
01894 if (bMultiSampleFound)
01895 currentRanking += multiSampleWeight;
01896
01897
01898
01899
01900
01901
01902
01903
01904
01905 if (deviceCombo.depthStencilFormatList.Contains(settings.presentParams.AutoDepthStencilFormat))
01906 currentRanking += depthStencilWeight;
01907
01908
01909
01910
01911
01912
01913
01914
01915
01916 bool bRefreshFound = false;
01917 for (int idm = 0; idm < deviceCombo.adapterInformation.displayModeList.Count; idm++)
01918 {
01919 DisplayMode displayMode = (DisplayMode)deviceCombo.adapterInformation.displayModeList[idm];
01920 if (displayMode.Format != deviceCombo.AdapterFormat)
01921 continue;
01922 if (displayMode.RefreshRate == settings.presentParams.FullScreenRefreshRateInHz)
01923 bRefreshFound = true;
01924 }
01925 if (bRefreshFound)
01926 currentRanking += refreshRateWeight;
01927
01928
01929
01930
01931
01932 if (deviceCombo.presentIntervalList.Contains(settings.presentParams.PresentationInterval))
01933 currentRanking += presentIntervalWeight;
01934
01935 return currentRanking;
01936 }
01937
01941 private DisplayMode FindValidResolution(EnumDeviceSettingsCombo deviceCombo, DisplayMode displayMode)
01942 {
01943 DisplayMode bestDisplayMode = displayMode;
01944
01945 if (deviceCombo.IsWindowed)
01946 {
01947
01948
01949
01950
01951 EnumAdapterInformation adapterInfo = Enumeration.GetAdapterInformation(deviceCombo.AdapterOrdinal);
01952
01953 System.Windows.Forms.Screen displayScreen = null;
01954 string adapterName = adapterInfo.AdapterInformation.DeviceName.ToLower();
01955 foreach (System.Windows.Forms.Screen s in System.Windows.Forms.Screen.AllScreens)
01956 {
01957 string deviceName = s.DeviceName.ToLower();
01958
01959 if (deviceName.IndexOf("\0") > 0)
01960 {
01961 deviceName = deviceName.Substring(0, deviceName.IndexOf("\0"));
01962 }
01963 if (deviceName == adapterName)
01964 {
01965
01966 displayScreen = s;
01967 break;
01968 }
01969 }
01970 System.Diagnostics.Debug.Assert(displayScreen != null, "We should have found the screen by now.");
01971
01972
01973
01974 if (bestDisplayMode.Width > displayScreen.WorkingArea.Width)
01975 bestDisplayMode.Width = displayScreen.WorkingArea.Width;
01976 if (bestDisplayMode.Height > displayScreen.WorkingArea.Height)
01977 bestDisplayMode.Height = displayScreen.WorkingArea.Height;
01978
01979 }
01980 else
01981 {
01982 int bestRanking = 100000;
01983 int currentRanking;
01984 for (int iDisplayMode = 0; iDisplayMode < deviceCombo.adapterInformation.displayModeList.Count; iDisplayMode++)
01985 {
01986 DisplayMode storedMode = (DisplayMode)deviceCombo.adapterInformation.displayModeList[iDisplayMode];
01987
01988
01989 if (storedMode.Format != deviceCombo.AdapterFormat)
01990 continue;
01991
01992
01993 currentRanking = Math.Abs((int)storedMode.Width - (int)displayMode.Width) +
01994 Math.Abs((int)storedMode.Height - (int)displayMode.Height);
01995
01996 if (currentRanking < bestRanking)
01997 {
01998 bestDisplayMode = displayMode;
01999 bestRanking = currentRanking;
02000
02001
02002 if (bestRanking == 0)
02003 break;
02004 }
02005 }
02006
02007
02008 if (bestDisplayMode.Width == 0)
02009 {
02010 throw new NoCompatibleDevicesException();
02011 }
02012 }
02013
02014 return bestDisplayMode;
02015 }
02016
02023 private void ChangeDevice(DeviceSettings newDeviceSettings, Device deviceFromApp, bool forceRecreate)
02024 {
02025
02026 if (isDisposed)
02027 return;
02028
02029
02030 DeviceSettings oldSettings = null;
02031 if (State.CurrentDeviceSettings != null)
02032 oldSettings = State.CurrentDeviceSettings.Clone();
02033
02034
02035 Pause(true, true);
02036
02037
02038
02039
02040 State.AreSizeChangesIgnored = true;
02041
02042
02043
02044 if ((deviceFromApp == null) && (oldSettings == null))
02045 {
02046
02047
02048 UpdateDeviceSettingsWithOverrides(ref newDeviceSettings);
02049 }
02050
02051
02052
02053
02054 if (newDeviceSettings.presentParams.IsWindowed)
02055 {
02056
02057
02058 if (newDeviceSettings.presentParams.BackBufferWidth < MinimumWindowSizeX)
02059 newDeviceSettings.presentParams.BackBufferWidth = MinimumWindowSizeX;
02060 if (newDeviceSettings.presentParams.BackBufferHeight < MinimumWindowSizeY)
02061 newDeviceSettings.presentParams.BackBufferHeight = MinimumWindowSizeY;
02062
02063 if (State.WindowFocus != null)
02064 {
02065
02066 System.Drawing.Rectangle windowClient = State.ClientRectangle;
02067 windowClient.Size = new System.Drawing.Size(newDeviceSettings.presentParams.BackBufferWidth, newDeviceSettings.presentParams.BackBufferHeight);
02068
02069 State.ClientRectangle = windowClient;
02070 State.WindowBoundsRectangle = WindowFocus.Bounds; ;
02071 }
02072 }
02073
02074
02075 State.CurrentDeviceSettings = newDeviceSettings;
02076
02077
02078
02079
02080
02081 if (!forceRecreate &&
02082 (deviceFromApp == null || deviceFromApp == State.Device) &&
02083 oldSettings != null &&
02084 oldSettings.AdapterOrdinal == newDeviceSettings.AdapterOrdinal &&
02085 oldSettings.DeviceType == newDeviceSettings.DeviceType &&
02086 oldSettings.BehaviorFlags == newDeviceSettings.BehaviorFlags)
02087 {
02088 try
02089 {
02090
02091 Reset3DEnvironment();
02092 }
02093 catch
02094 {
02095
02096 Pause(false, false);
02097 State.IsDeviceLost = true;
02098 }
02099 }
02100 else
02101 {
02102
02103 if (oldSettings != null)
02104 {
02105
02106
02107 Cleanup3DEnvironment(false);
02108 }
02109
02110 Device device = deviceFromApp;
02111
02112 if (deviceFromApp == null)
02113 {
02114 try
02115 {
02116 device = new Device((int)newDeviceSettings.AdapterOrdinal, newDeviceSettings.DeviceType,
02117 State.WindowFocus.Handle, newDeviceSettings.BehaviorFlags,
02118 newDeviceSettings.presentParams);
02119 }
02120 catch (Exception e)
02121 {
02122
02123 Pause(false, false);
02124 CreatingDeviceException cde = new CreatingDeviceException(e);
02125 DisplayErrorMessage(cde);
02126 throw;
02127 }
02128 }
02129
02130
02131 device.DeviceLost += new EventHandler(OnDeviceLost);
02132 device.DeviceReset += new EventHandler(OnDeviceReset);
02133 device.Disposing += new EventHandler(OnDeviceDisposing);
02134
02135
02136 State.Device = device;
02137
02138
02139
02140 try
02141 {
02142 Initialize3DEnvironment();
02143 }
02144 catch
02145 {
02146 Pause(false, false);
02147 throw;
02148 }
02149
02150 Enumeration.Enumerate(null);
02151 EnumAdapterInformation adapterInfo = Enumeration.GetAdapterInformation(newDeviceSettings.AdapterOrdinal);
02152 UpdateDeviceStats(newDeviceSettings.DeviceType, newDeviceSettings.BehaviorFlags, adapterInfo.AdapterInformation);
02153 }
02154
02155
02156 State.AdapterMonitor = Manager.GetAdapterMonitorHandle((int)newDeviceSettings.AdapterOrdinal);
02157
02158
02159
02160
02161
02162
02163
02164
02165
02166 if (newDeviceSettings.presentParams.IsWindowed)
02167 {
02168 if (State.WindowFocus == null)
02169 {
02170 System.Drawing.Rectangle rect = State.WindowBoundsRectangle;
02171
02172
02173 System.Drawing.Point pt = rect.Location;
02174 pt = Window.PointToScreen(pt);
02175
02176 if (!State.IsMaximized)
02177 {
02178 Window.SetBounds(pt.X, pt.Y, rect.Width, rect.Height, System.Windows.Forms.BoundsSpecified.All);
02179 }
02180
02181
02182
02183
02184 NativeMethods.MonitorInformation infoAdapter = new NativeMethods.MonitorInformation();
02185
02186 infoAdapter.Size = (uint)System.Runtime.InteropServices.Marshal.SizeOf(typeof(NativeMethods.MonitorInformation));
02187 NativeMethods.GetMonitorInfo(State.AdapterMonitor, ref infoAdapter);
02188
02189 int monitorWidth = infoAdapter.WorkRectangle.Right - infoAdapter.WorkRectangle.Left;
02190 int monitorHeight = infoAdapter.WorkRectangle.Bottom - infoAdapter.WorkRectangle.Top;
02191
02192
02193 IntPtr monitorHandle = NativeMethods.MonitorFromWindow(Window.Handle, 1);
02194 NativeMethods.MonitorInformation infoWindow = new NativeMethods.MonitorInformation();
02195
02196 infoWindow.Size = (uint)System.Runtime.InteropServices.Marshal.SizeOf(typeof(NativeMethods.MonitorInformation));
02197 NativeMethods.GetMonitorInfo(monitorHandle, ref infoWindow);
02198
02199 rect = State.WindowBoundsRectangle;
02200 int windowOffsetX = rect.Left - infoWindow.MonitorRectangle.Left;
02201 int windowOffsetY = rect.Top - infoWindow.MonitorRectangle.Top;
02202 int windowWidth = rect.Right - rect.Left;
02203 int windowHeight = rect.Bottom - rect.Top;
02204
02205 if (State.IsWindowCreatedWithDefaultPositions)
02206 {
02207
02208
02209
02210
02211 State.IsWindowCreatedWithDefaultPositions = false;
02212
02213
02214 if (infoAdapter.WorkRectangle.Left + windowOffsetX + windowWidth > infoAdapter.WorkRectangle.Right)
02215 windowOffsetX = (monitorWidth - windowWidth) / 2;
02216 if (infoAdapter.WorkRectangle.Top + windowOffsetY + windowHeight > infoAdapter.WorkRectangle.Bottom)
02217 windowOffsetY = (monitorHeight - windowHeight) / 2;
02218 }
02219
02220
02221 pt.X = infoAdapter.MonitorRectangle.Left + windowOffsetX;
02222 pt.Y = infoAdapter.MonitorRectangle.Top + windowOffsetY;
02223 }
02224
02225 }
02226 else
02227 {
02228
02229 State.FullScreenClientRectangle = new System.Drawing.Rectangle(0, 0, newDeviceSettings.presentParams.BackBufferWidth,
02230 newDeviceSettings.presentParams.BackBufferHeight);
02231 }
02232
02233
02234 State.AreSizeChangesIgnored = false;
02235 Pause(false, false);
02236 State.WasDeviceCreated = true;
02237 }
02238
02242 private void UpdateDeviceStats(DeviceType deviceType, CreateFlags behaviorFlags, AdapterInformation info)
02243 {
02244 if (State.AreStatsHidden)
02245 return;
02246
02247
02248 BehaviorFlags flags = new BehaviorFlags(behaviorFlags);
02249
02250 System.Text.StringBuilder builder = new System.Text.StringBuilder();
02251
02252 builder.Append(deviceType.ToString());
02253
02254 if (flags.HardwareVertexProcessing && flags.PureDevice)
02255 {
02256 if (deviceType == DeviceType.Hardware)
02257 builder.Append(" (pure hw vp)");
02258 else
02259 builder.Append(" (simulated pure hw vp)");
02260 }
02261 else if (flags.HardwareVertexProcessing)
02262 {
02263 if (deviceType == DeviceType.Hardware)
02264 builder.Append(" (hw vp)");
02265 else
02266 builder.Append(" (simulated hw vp)");
02267 }
02268 else if (flags.MixedVertexProcessing)
02269 {
02270 if (deviceType == DeviceType.Hardware)
02271 builder.Append(" (mixed vp)");
02272 else
02273 builder.Append(" (simulated mixed vp)");
02274 }
02275 else if (flags.SoftwareVertexProcessing)
02276 {
02277 builder.Append(" (sw vp)");
02278 }
02279
02280
02281 builder.Append(": ");
02282 builder.Append(info.Description);
02283
02284
02285 State.DeviceStats = builder.ToString();
02286 }
02287
02291 private void UpdateDeviceSettingsWithOverrides(ref DeviceSettings settings)
02292 {
02293 if (State.OverrideAdapterOrdinal != -1)
02294 settings.AdapterOrdinal = (uint)State.OverrideAdapterOrdinal;
02295
02296 if (State.IsOverridingFullScreen)
02297 settings.presentParams.IsWindowed = false;
02298 if (State.IsOverridingWindowed)
02299 settings.presentParams.IsWindowed = true;
02300
02301 if (State.IsOverridingForceReference)
02302 settings.DeviceType = DeviceType.Reference;
02303 else if (State.IsOverridingForceHardware)
02304 settings.DeviceType = DeviceType.Hardware;
02305
02306 if (State.OverrideWidth != 0)
02307 settings.presentParams.BackBufferWidth = State.OverrideWidth;
02308 if (State.OverrideHeight != 0)
02309 settings.presentParams.BackBufferHeight = State.OverrideHeight;
02310
02311 if (State.IsOverridingForcePureHardwareVertexProcessing)
02312 {
02313 settings.BehaviorFlags &= ~CreateFlags.SoftwareVertexProcessing;
02314 settings.BehaviorFlags |= CreateFlags.HardwareVertexProcessing;
02315 settings.BehaviorFlags |= CreateFlags.PureDevice;
02316 }
02317 else if (State.IsOverridingForceHardwareVertexProcessing)
02318 {
02319 settings.BehaviorFlags &= ~CreateFlags.SoftwareVertexProcessing;
02320 settings.BehaviorFlags &= ~CreateFlags.PureDevice;
02321 settings.BehaviorFlags |= CreateFlags.HardwareVertexProcessing;
02322 }
02323 else if (State.IsOverridingForceSoftwareVertexProcessing)
02324 {
02325 settings.BehaviorFlags &= ~CreateFlags.HardwareVertexProcessing;
02326 settings.BehaviorFlags &= ~CreateFlags.PureDevice;
02327 settings.BehaviorFlags |= CreateFlags.SoftwareVertexProcessing;
02328 }
02329 }
02330
02331
02340 public void Reset3DEnvironment()
02341 {
02342 Device device = State.Device;
02343 System.Diagnostics.Debug.Assert(device != null, "The device should not be null here.");
02344 if (device == null)
02345 throw new InvalidOperationException("The device should not be null.");
02346
02347
02348 if (DeviceLost != null)
02349 DeviceLost(this, EventArgs.Empty);
02350
02351
02352
02353 AdjustWindowStyle(Window, IsWindowed);
02354
02355 try
02356 {
02357
02358
02359 device.Reset(State.CurrentDeviceSettings.presentParams);
02360 }
02361 catch (Exception e)
02362 {
02363 if (e is MediaNotFoundException)
02364 DisplayErrorMessage(e as MediaNotFoundException);
02365 else
02366 {
02367
02368 if (!(e is DeviceLostException))
02369 {
02370 DisplayErrorMessage(new ResettingDeviceException(e));
02371 }
02372 }
02373
02374
02375 OnDeviceLost(null, EventArgs.Empty);
02376 if (!(e is DeviceLostException))
02377 {
02378 throw;
02379 }
02380 }
02381 }
02382
02391 public void Render3DEnvironment()
02392 {
02393 Device device = State.Device;
02394 if (device == null)
02395 return;
02396
02397 if (State.IsDeviceLost || State.IsRenderingPaused)
02398 {
02399
02400
02401 System.Threading.Thread.Sleep(100);
02402 }
02403
02404 if (!State.IsActive)
02405 {
02406
02407 System.Threading.Thread.Sleep(20);
02408 }
02409
02410 if (State.IsDeviceLost && !State.IsRenderingPaused)
02411 {
02412 ResultCode result;
02413
02414 if ( ( result = device.CheckCooperativeLevelResult()) != ResultCode.Success )
02415 {
02416 if (result == ResultCode.DeviceLost)
02417 {
02418
02419
02420 System.Threading.Thread.Sleep(50);
02421 return;
02422 }
02423
02424
02425
02426
02427 if (IsWindowed)
02428 {
02429 DisplayMode adapterDesktopMode = Manager.Adapters[(int)State.CurrentDeviceSettings.AdapterOrdinal].CurrentDisplayMode;
02430 if (State.CurrentDeviceSettings.AdapterFormat != adapterDesktopMode.Format)
02431 {
02432
02433 MatchOptions match = new MatchOptions();
02434 match.AdapterOrdinal = MatchType.PreserveInput;
02435 match.DeviceType = MatchType.PreserveInput;
02436 match.IsWindowed = MatchType.PreserveInput;
02437 match.AdapterFormat = MatchType.PreserveInput;
02438 match.VertexProcessing = MatchType.ClosestToInput;
02439 match.Resolution = MatchType.ClosestToInput;
02440 match.BackBufferFormat = MatchType.ClosestToInput;
02441 match.BackBufferCount = MatchType.ClosestToInput;
02442 match.MultiSample = MatchType.ClosestToInput;
02443 match.SwapEffect = MatchType.ClosestToInput;
02444 match.DepthFormat = MatchType.ClosestToInput;
02445 match.StencilFormat = MatchType.ClosestToInput;
02446 match.PresentFlags = MatchType.ClosestToInput;
02447 match.RefreshRate = MatchType.ClosestToInput;
02448 match.PresentInterval = MatchType.ClosestToInput;
02449
02450 DeviceSettings settings = State.CurrentDeviceSettings;
02451 settings.AdapterFormat = adapterDesktopMode.Format;
02452 try
02453 {
02454 settings = FindValidDeviceSettings(settings, match);
02455
02456
02457 ChangeDevice(settings, null, false);
02458 }
02459 catch
02460 {
02461 DisplayErrorMessage(new NoCompatibleDevicesException());
02462 Dispose();
02463 }
02464 return;
02465 }
02466 }
02467
02468
02469 try
02470 {
02471 Reset3DEnvironment();
02472 }
02473 catch (DeviceLostException)
02474 {
02475
02476 System.Threading.Thread.Sleep(50);
02477 return;
02478 }
02479 catch
02480 {
02481
02482
02483 DeviceSettings deviceSettings = State.CurrentDeviceSettings;
02484 try
02485 {
02486 ChangeDevice(deviceSettings, null, false);
02487 }
02488 catch (Exception e)
02489 {
02490 ResettingDeviceException rde = new ResettingDeviceException(e);
02491 DisplayErrorMessage(rde);
02492 Dispose();
02493 throw;
02494 }
02495 }
02496 }
02497 State.IsDeviceLost = false;
02498 }
02499
02500
02501 double time = FrameworkTimer.GetTime();
02502 float elapsedTime = (float)FrameworkTimer.GetElapsedTime();
02503
02504
02505 if (State.IsUsingConstantFrameTime)
02506 {
02507 elapsedTime = State.TimePerFrame;
02508 time = State.CurrentTime + elapsedTime;
02509 }
02510
02511 State.CurrentTime = time;
02512 State.ElapsedTime = elapsedTime;
02513
02514
02515 UpdateFrameStats();
02516
02517
02518
02519 if (State.Settings != null && State.IsD3DSettingsDialogShowing)
02520 {
02521 if (!State.IsRenderingPaused)
02522 {
02523
02524 device.Clear(ClearFlags.Target, 0x00003F3F, 1.0f, 0);
02525
02526
02527 device.BeginScene();
02528 State.Settings.OnRender(elapsedTime);
02529 device.EndScene();
02530 }
02531 }
02532 else
02533 {
02534 HandleTimers();
02535
02536
02537 if (State.CallbackInterface != null)
02538 {
02539 State.CallbackInterface.OnFrameMove(device, time, elapsedTime);
02540 device = State.Device;
02541 if (device == null)
02542 return;
02543 }
02544
02545 if (!State.IsRenderingPaused)
02546 {
02547
02548 if (State.CallbackInterface != null)
02549 {
02550 State.CallbackInterface.OnFrameRender(device, time, elapsedTime);
02551 device = State.Device;
02552 if (device == null)
02553 return;
02554 }
02555 }
02556 }
02557
02558 if (!State.IsRenderingPaused)
02559 {
02560
02561 try
02562 {
02563 device.Present();
02564 }
02565 catch (DeviceLostException)
02566 {
02567
02568 State.IsDeviceLost = true;
02569 }
02570 catch (DriverInternalErrorException)
02571 {
02572
02573
02574
02575
02576
02577
02578
02579
02580
02581
02582
02583
02584
02585
02586 State.IsDeviceLost = true;
02587 }
02588 }
02589
02590
02591 State.CurrentFrameNumber++;
02592
02593 if (State.OverrideQuitAfterFrame != 0)
02594 {
02595 if (State.CurrentFrameNumber > State.OverrideQuitAfterFrame)
02596 Dispose();
02597 }
02598 }
02599
02603 private void Shutdown()
02604 {
02605
02606 Cleanup3DEnvironment(true);
02607
02608 if (Window != null)
02609 {
02610 if (WindowForm != null)
02611 {
02612 WindowForm.Close();
02613 }
02614 }
02615 }
02616
02620 public void Pause(bool pauseTime, bool pauseRendering)
02621 {
02622
02623 State.PauseTimeCount += pauseTime ? +1 : -1;
02624 if (State.PauseTimeCount < 0)
02625 State.PauseTimeCount = 0;
02626
02627 State.PauseRenderingCount += pauseRendering ? +1 : -1;
02628 if (State.PauseRenderingCount < 0)
02629 State.PauseRenderingCount = 0;
02630
02631 if (State.PauseTimeCount > 0)
02632 {
02633
02634 FrameworkTimer.Stop();
02635 }
02636 else
02637 {
02638
02639 FrameworkTimer.Start();
02640 }
02641
02642 State.IsRenderingPaused = (State.PauseRenderingCount > 0);
02643 State.IsTimePaused = (State.PauseTimeCount > 0);
02644 }
02645
02646
02650 public void DisplayErrorMessage(Exception e)
02651 {
02652 if (e == lastDisplayedMessage)
02653 return;
02654
02655 lastDisplayedMessage = e;
02656
02657 State.ApplicationExitCode = 1;
02658 bool found = true;
02659 if (e is ApplicationException)
02660 {
02661 if (e is NoDirect3DException)
02662 State.ApplicationExitCode = 2;
02663 else if (e is MediaNotFoundException)
02664 State.ApplicationExitCode = 4;
02665 else if (e is CreatingDeviceException)
02666 State.ApplicationExitCode = 6;
02667 else if (e is ResettingDeviceException)
02668 State.ApplicationExitCode = 7;
02669 else if (e is CreatingDeviceObjectsException)
02670 State.ApplicationExitCode = 8;
02671 else if (e is ResettingDeviceObjectsException)
02672 State.ApplicationExitCode = 9;
02673 else if (e is NoCompatibleDevicesException)
02674 State.ApplicationExitCode = 3;
02675 else
02676 found = false;
02677 }
02678 else
02679 found = false;
02680
02681 string errorText = string.Empty;
02682 if (found && State.IsShowingMsgBoxOnError)
02683 {
02684 errorText = e.Message;
02685 if (e.InnerException != null)
02686 {
02687 errorText += "\r\n\r\n" + e.InnerException.ToString();
02688 lastDisplayedMessage = e.InnerException;
02689 }
02690
02691 if (State.WindowTitle != null && State.WindowTitle.Length > 0)
02692 System.Windows.Forms.MessageBox.Show(errorText, "DirectX Application",
02693 System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);
02694 else
02695 System.Windows.Forms.MessageBox.Show(errorText, State.WindowTitle,
02696 System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);
02697 }
02698 else if (!found && State.IsShowingMsgBoxOnError)
02699 {
02700 errorText = e.ToString();
02701
02702 if (State.WindowTitle != null && State.WindowTitle.Length > 0)
02703 System.Windows.Forms.MessageBox.Show(errorText, "DirectX Application",
02704 System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);
02705 else
02706 System.Windows.Forms.MessageBox.Show(errorText, State.WindowTitle,
02707 System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);
02708 }
02709 }
02710
02717 private void Cleanup3DEnvironment(bool releaseSettings)
02718 {
02719 DialogResourceManager.GetGlobalInstance().OnLostDevice();
02720 DialogResourceManager.GetGlobalInstance().OnDestroyDevice();
02721 ResourceCache.GetGlobalInstance().OnLostDevice();
02722 ResourceCache.GetGlobalInstance().OnDestroyDevice();
02723 if (State.Settings != null)
02724 {
02725 State.Settings.OnLostDevice();
02726 State.Settings.OnDestroyDevice(this, EventArgs.Empty);
02727 }
02728
02729 using (Device device = State.Device)
02730 {
02731 if (releaseSettings)
02732 {
02733
02734 State.CurrentDeviceSettings = null;
02735 }
02736
02737
02738 State.BackBufferSurfaceDesc = new SurfaceDescription();
02739 State.Capabilities.Clear();
02740 State.WasDeviceCreated = false;
02741 }
02742
02743 State.Device = null;
02744 }
02745
02755 private void Initialize3DEnvironment()
02756 {
02757 Device device = State.Device;
02758 System.Diagnostics.Debug.Assert(device != null, "The device should not be null here.");
02759 if (device == null)
02760 throw new InvalidOperationException("The device should not be null.");
02761
02762 bool success = true;
02763 try
02764 {
02765 State.AreDeviceObjectsCreated = false;
02766 State.AreDeviceObjectsReset = false;
02767
02768
02769
02770 AdjustWindowStyle(Window, IsWindowed);
02771
02772
02773
02774 PrepareDevice(device);
02775
02776 try
02777 {
02778
02779 if (State.Settings != null)
02780 {
02781 State.Settings.OnCreateDevice(device);
02782 State.Settings.OnResetDevice();
02783 }
02784
02785 DialogResourceManager.GetGlobalInstance().OnCreateDevice(device);
02786
02787
02788 ResourceCache.GetGlobalInstance().OnCreateDevice(device);
02789
02790
02791 State.IsInsideDeviceCallback = true;
02792 if (DeviceCreated != null)
02793 {
02794 DeviceCreated(this, new DeviceEventArgs(device, State.BackBufferSurfaceDesc));
02795 }
02796 State.IsInsideDeviceCallback = false;
02797 State.AreDeviceObjectsCreated = true;
02798 }
02799 catch (MediaNotFoundException e)
02800 {
02801 DisplayErrorMessage(e);
02802 success = false;
02803 throw;
02804 }
02805 catch (Exception e)
02806 {
02807 DisplayErrorMessage(new CreatingDeviceException(e));
02808 success = false;
02809 throw;
02810 }
02811
02812 try
02813 {
02814
02815 DialogResourceManager.GetGlobalInstance().OnResetDevice(device);
02816
02817
02818 ResourceCache.GetGlobalInstance().OnResetDevice(device);
02819
02820
02821 State.IsInsideDeviceCallback = true;
02822 if (DeviceReset != null)
02823 DeviceReset(this, new DeviceEventArgs(device, State.BackBufferSurfaceDesc));
02824
02825 State.IsInsideDeviceCallback = false;
02826 State.AreDeviceObjectsReset = true;
02827 }
02828 catch (MediaNotFoundException e)
02829 {
02830 DisplayErrorMessage(e);
02831 success = false;
02832 throw;
02833 }
02834 catch (Exception e)
02835 {
02836 DisplayErrorMessage(new CreatingDeviceException(e));
02837 success = false;
02838 throw;
02839 }
02840 }
02841 finally
02842 {
02843 if (!success)
02844 Cleanup3DEnvironment(true);
02845 }
02846
02847 }
02848
02853 private void PrepareDevice(Device device)
02854 {
02855
02856 UpdateStaticFrameStats();
02857
02858
02859 using (Surface backBuffer = device.GetBackBuffer(0, 0))
02860 {
02861 State.BackBufferSurfaceDesc = backBuffer.Description;
02862 }
02863
02864
02865 State.Capabilities = device.Capabilities;
02866
02867
02868 if (State.IsShowingCursorWhenFullScreen && !IsWindowed)
02869 {
02870
02871 System.Windows.Forms.Cursor cursor = System.Windows.Forms.Cursor.Current;
02872 if (cursor == null)
02873 cursor = System.Windows.Forms.Cursors.Default;
02874
02875 device.SetCursor(cursor.Handle, false);
02876 device.ShowCursor(true);
02877 }
02878
02879
02880 if (State.IsCursorClippedWhenFullScreen)
02881 {
02882 if (!IsWindowed)
02883 {
02884
02885 System.Windows.Forms.Cursor.Clip = State.FullScreenClientRectangle;
02886 }
02887 else
02888 {
02889
02890 System.Windows.Forms.Cursor.Clip = System.Drawing.Rectangle.Empty;
02891 }
02892 }
02893 }
02894
02898 private void AdjustWindowStyle(System.Windows.Forms.Control control, bool isWindowed)
02899 {
02900 System.Windows.Forms.Form window = control as System.Windows.Forms.Form;
02901 if (window == null)
02902 return;
02903
02904 if (isWindowed)
02905 {
02906
02907
02908 if (State.WindowDeviceWindowed != State.WindowDeviceFullScreen)
02909 {
02910 State.WindowDeviceFullScreen.Hide();
02911 }
02912
02913
02914 window.FormBorderStyle = System.Windows.Forms.FormBorderStyle.Sizable;
02915 }
02916 else
02917 {
02918
02919
02920 if (State.WindowDeviceWindowed != State.WindowDeviceFullScreen)
02921 {
02922 System.Windows.Forms.Form fullscreen = State.WindowDeviceFullScreen as System.Windows.Forms.Form;
02923 if (fullscreen != null)
02924 {
02925 if (fullscreen.WindowState == System.Windows.Forms.FormWindowState.Minimized)
02926 fullscreen.WindowState = System.Windows.Forms.FormWindowState.Normal;
02927
02928 State.WindowDeviceFullScreen.Show();
02929 }
02930 }
02931
02932 window.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
02933 }
02934 }
02935
02939 private void UpdateFrameStats()
02940 {
02941 if (State.AreStatsHidden)
02942 return;
02943
02944
02945 double time = FrameworkTimer.GetAbsoluteTime();
02946 State.LastStatsUpdateFrames++;
02947
02948 if (time - State.LastStatsUpdateTime > 1.0)
02949 {
02950 float fps = (float)(State.LastStatsUpdateFrames / (time - State.LastStatsUpdateTime));
02951 State.CurrentFrameRate = fps;
02952 State.LastStatsUpdateFrames = 0;
02953 State.LastStatsUpdateTime = time;
02954
02955 State.FrameStats = string.Format(State.StaticFrameStats, fps.ToString("f2",
02956 System.Globalization.CultureInfo.CurrentUICulture));
02957 }
02958 }
02959
02963 private void UpdateStaticFrameStats()
02964 {
02965 if (State.AreStatsHidden)
02966 return;
02967
02968 State.StaticFrameStats = string.Empty;
02969 DeviceSettings settings = State.CurrentDeviceSettings;
02970 if (settings.presentParams == null)
02971 return;
02972
02973 EnumDeviceSettingsCombo combo = Enumeration.GetDeviceSettingsCombo(
02974 settings.AdapterOrdinal, settings.DeviceType, settings.AdapterFormat,
02975 settings.presentParams.BackBufferFormat, settings.presentParams.IsWindowed);
02976
02977 if (combo == null)
02978 return;
02979
02980
02981 string formatString = null;
02982 if (settings.AdapterFormat == combo.BackBufferFormat)
02983 {
02984
02985 formatString = "Format." + settings.AdapterFormat.ToString();
02986 }
02987 else
02988 {
02989 formatString = string.Format("backbuffer Format.{0}, adapter Format.{1}",
02990 combo.BackBufferFormat, settings.AdapterFormat);
02991 }
02992
02993
02994 string depthFormat = null;
02995 if (settings.presentParams.EnableAutoDepthStencil)
02996 {
02997 depthFormat = " Format." + settings.presentParams.AutoDepthStencilFormat.ToString();
02998 }
02999
03000
03001 string multiSampleString = null;
03002 switch (settings.presentParams.MultiSampleType)
03003 {
03004 case MultiSampleType.None:
03005 multiSampleString = null;
03006 break;
03007 case MultiSampleType.NonMaskable:
03008 multiSampleString = " (Nonmaskable Multisample)";
03009 break;
03010 default:
03011 multiSampleString = string.Format(" ({0} Multisample)", settings.presentParams.MultiSampleType.ToString());
03012 break;
03013 }
03014
03015
03016 State.StaticFrameStats = string.Format("{0} fps ({1}x{2}), {3}{4}{5}",
03017 "{0}", settings.presentParams.BackBufferWidth, settings.presentParams.BackBufferHeight,
03018 formatString, depthFormat, multiSampleString);
03019 }
03020
03025 private Format FindAdapterFormat(uint adapterOrdinal, DeviceType deviceType, Format backbufferFormat,
03026 bool isWindowed)
03027 {
03028 EnumDeviceInformation deviceInfo = Enumeration.GetDeviceInfo(adapterOrdinal, deviceType);
03029 if (deviceInfo != null)
03030 {
03031 for (int i = 0; i < deviceInfo.deviceSettingsList.Count; i++)
03032 {
03033 EnumDeviceSettingsCombo combo = deviceInfo.deviceSettingsList[i] as EnumDeviceSettingsCombo;
03034 if ((combo.BackBufferFormat == backbufferFormat) &&
03035 (combo.IsWindowed == isWindowed))
03036 {
03037
03038 return combo.AdapterFormat;
03039 }
03040 }
03041 }
03042
03043
03044 return backbufferFormat;
03045 }
03046
03047
03051 private void HandlePossibleSizeChange()
03052 {
03053 if ((!State.WasDeviceCreated) || (State.AreSizeChangesIgnored))
03054 return;
03055
03056 if (!State.CurrentDeviceSettings.presentParams.IsWindowed)
03057 return;
03058
03059 if (Window == null)
03060 return;
03061
03062 System.Drawing.Rectangle oldClient = State.ClientRectangle;
03063
03064 State.ClientRectangle = Window.ClientRectangle;
03065
03066
03067 State.WindowBoundsRectangle = Window.Bounds;
03068
03069
03070 if (oldClient.Width != Window.ClientRectangle.Width || oldClient.Height != Window.ClientRectangle.Height)
03071 {
03072
03073
03074 Pause(true, true);
03075
03076 DeviceSettings settings = State.CurrentDeviceSettings;
03077 settings.presentParams.BackBufferWidth = Window.ClientRectangle.Width;
03078 settings.presentParams.BackBufferHeight = Window.ClientRectangle.Height;
03079
03080
03081 if (State.Device != null)
03082 {
03083 try
03084 {
03085 Reset3DEnvironment();
03086 }
03087 catch
03088 {
03089 State.IsDeviceLost = true;
03090 }
03091 }
03092
03093 Pause(false, false);
03094 }
03095
03096 CheckForWindowMonitorChange();
03097 }
03098
03103 private void CheckForWindowMonitorChange()
03104 {
03105
03106 if (!State.CanAutoChangeAdapter)
03107 return;
03108
03109 IntPtr monitorHandle = NativeMethods.MonitorFromWindow(Window.Handle, 1);
03110 if (monitorHandle != State.AdapterMonitor)
03111 {
03112
03113 Pause(true, true);
03114
03115 uint newOrdinal = GetAdapterOridinalFromMonitor(monitorHandle);
03116
03117
03118
03119 DeviceSettings settings = State.CurrentDeviceSettings.Clone();
03120 settings.AdapterOrdinal = newOrdinal;
03121
03122
03123 MatchOptions match = new MatchOptions();
03124 match.AdapterOrdinal = MatchType.PreserveInput;
03125 match.DeviceType = MatchType.ClosestToInput;
03126 match.IsWindowed = MatchType.ClosestToInput;
03127 match.AdapterFormat = MatchType.ClosestToInput;
03128 match.VertexProcessing = MatchType.ClosestToInput;
03129 match.Resolution = MatchType.ClosestToInput;
03130 match.BackBufferFormat = MatchType.ClosestToInput;
03131 match.BackBufferCount = MatchType.ClosestToInput;
03132 match.MultiSample = MatchType.ClosestToInput;
03133 match.SwapEffect = MatchType.ClosestToInput;
03134 match.DepthFormat = MatchType.ClosestToInput;
03135 match.StencilFormat = MatchType.ClosestToInput;
03136 match.PresentFlags = MatchType.ClosestToInput;
03137 match.RefreshRate = MatchType.ClosestToInput;
03138 match.PresentInterval = MatchType.ClosestToInput;
03139
03140 try
03141 {
03142
03143 settings = FindValidDeviceSettings(settings, match);
03144 try
03145 {
03146
03147
03148 ChangeDevice(settings, null, false);
03149 }
03150 catch (Exception e)
03151 {
03152
03153 Dispose();
03154 Pause(false, false);
03155 System.Diagnostics.Debugger.Log(0, string.Empty, e.ToString());
03156 return;
03157 }
03158 }
03159 catch
03160 {
03161
03162
03163 }
03164
03165 }
03166 Pause(false, false);
03167 }
03168
03170 private uint GetAdapterOridinalFromMonitor(IntPtr monitorHandle)
03171 {
03172 uint ordinal = 0;
03173
03174 foreach (EnumAdapterInformation info in Enumeration.AdapterInformationList)
03175 {
03176 if (Manager.GetAdapterMonitorHandle((int)info.AdapterOrdinal) == monitorHandle)
03177 ordinal = info.AdapterOrdinal;
03178 }
03179 return ordinal;
03180 }
03181
03183 public System.Drawing.Icon LoadFirstIconFromResource()
03184 {
03185
03186 System.Reflection.Assembly currentAssembly = System.Reflection.Assembly.GetCallingAssembly();
03187 foreach (string s in currentAssembly.GetManifestResourceNames())
03188 {
03189 try
03190 {
03191
03192 System.IO.Stream resourceStream = currentAssembly.GetManifestResourceStream(s);
03193 return new System.Drawing.Icon(resourceStream);
03194 }
03195 catch
03196 {
03197
03198 try
03199 {
03200 System.Resources.ResourceReader reader = new System.Resources.ResourceReader(currentAssembly.GetManifestResourceStream(s));
03201 IDictionaryEnumerator en = reader.GetEnumerator();
03202 while (en.MoveNext())
03203 {
03204 System.Drawing.Icon test = en.Value as System.Drawing.Icon;
03205 if (test != null)
03206 return test;
03207 }
03208 }
03209 catch
03210 {
03211
03212 continue;
03213 }
03214 }
03215 }
03216
03217 return null;
03218 }
03219
03221 public void SetCursorSettings(bool showCursorWhenFullscreen, bool clipCursorWhenFullscreen)
03222 {
03223 State.IsCursorClippedWhenFullScreen = clipCursorWhenFullscreen;
03224 State.IsShowingCursorWhenFullScreen = showCursorWhenFullscreen;
03225 }
03226
03228 public bool CanAutomaticallyChangeMonitor
03229 {
03230 get { return State.CanAutoChangeAdapter; }
03231 set { State.CanAutoChangeAdapter = value; }
03232 }
03233
03235 public void SetConstantFrameTime(bool constantFrameTime, float timePerFrame)
03236 {
03237 if (State.IsOverridingConstantFrameTime)
03238 {
03239 constantFrameTime = true;
03240 timePerFrame = State.OverrideConstantTimePerFrame;
03241 }
03242 State.TimePerFrame = timePerFrame;
03243 State.IsUsingConstantFrameTime = constantFrameTime;
03244 }
03246 public void SetConstantFrameTime(bool constantFrameTime)
03247 {
03248 State.OverrideConstantTimePerFrame = 0.0333f;
03249 State.IsUsingConstantFrameTime = constantFrameTime;
03250 }
03251
03255 public int ExitCode
03256 {
03257 get { return State.ApplicationExitCode; }
03258 }
03259
03263 public void ShowSettingsDialog(bool shouldShow)
03264 {
03265 State.IsD3DSettingsDialogShowing = shouldShow;
03266
03267 if (shouldShow)
03268 {
03269 SettingsDialog dialog = PrepareSettingsDialog();
03270 dialog.Refresh();
03271 }
03272 }
03273
03279 private SettingsDialog PrepareSettingsDialog()
03280 {
03281 SettingsDialog dialog = State.Settings;
03282 if (dialog == null)
03283 {
03284
03285 dialog = new SettingsDialog(this);
03286 State.Settings = dialog;
03287
03288 if (State.AreDeviceObjectsCreated)
03289 {
03290 dialog.OnCreateDevice(State.Device);
03291 }
03292 if (State.AreDeviceObjectsReset)
03293 {
03294 dialog.OnResetDevice();
03295 }
03296 }
03297
03298 return dialog;
03299 }
03300
03301 #region External state access functions
03305 public Device Device
03306 {
03307 get { return State.Device; }
03308 }
03309
03313 public SurfaceDescription BackBufferSurfaceDescription
03314 {
03315 get { return State.BackBufferSurfaceDesc; }
03316 }
03317
03321 public Capabilities DeviceCapabilities
03322 {
03323 get { return State.Capabilities; }
03324 }
03325
03329 public System.Windows.Forms.Control Window
03330 {
03331 get { return IsWindowed ? State.WindowDeviceWindowed : State.WindowDeviceFullScreen; }
03332 }
03333
03337 public System.Windows.Forms.Form WindowForm
03338 {
03339 get { return Window as System.Windows.Forms.Form; }
03340 }
03341
03345 public System.Windows.Forms.Control WindowFocus
03346 {
03347 get { return State.WindowFocus; }
03348 }
03349
03353 public System.Windows.Forms.Control WindowDeviceWindowed
03354 {
03355 get { return State.WindowDeviceWindowed; }
03356 }
03357
03361 public System.Windows.Forms.Control WindowDeviceFullscreen
03362 {
03363 get { return State.WindowDeviceFullScreen; }
03364 }
03365
03369 public System.Drawing.Rectangle WindowClientRectangle
03370 {
03371 get { return State.ClientRectangle; }
03372 }
03373
03377 public System.Drawing.Rectangle ClientRectangle
03378 {
03379 get { return IsWindowed ? State.ClientRectangle : State.FullScreenClientRectangle; }
03380 }
03381
03385 public bool IsWindowed
03386 {
03387 get
03388 {
03389 DeviceSettings settings = State.CurrentDeviceSettings;
03390 if ((settings != null) && (settings.presentParams != null))
03391 return settings.presentParams.IsWindowed;
03392 else
03393 return false;
03394 }
03395 }
03396
03397
03401 public string FrameStats
03402 {
03403 get { return State.FrameStats; }
03404 }
03408 public string DeviceStats
03409 {
03410 get { return State.DeviceStats; }
03411 }
03412
03416 public float FPS
03417 {
03418 get { return State.CurrentFrameRate; }
03419 }
03420
03424 public bool IsD3DSettingsDialogShowing
03425 {
03426 get { return State.IsD3DSettingsDialogShowing; }
03427 }
03428
03432 public bool IsShowingMsgBoxOnError
03433 {
03434 get { return State.IsShowingMsgBoxOnError; }
03435 }
03436
03441 public DeviceSettings DeviceSettings
03442 {
03443 get
03444 {
03445 if (State.CurrentDeviceSettings != null)
03446 {
03447 return State.CurrentDeviceSettings;
03448 }
03449 else
03450 {
03451 return new DeviceSettings();
03452 }
03453 }
03454 }
03459 public PresentParameters PresentParameters
03460 {
03461 get
03462 {
03463 if (State.CurrentDeviceSettings != null)
03464 {
03465 return State.CurrentDeviceSettings.presentParams;
03466 }
03467 else
03468 {
03469 return new PresentParameters();
03470 }
03471 }
03472 }
03474 public bool IsNotifiedOnMouseMove
03475 {
03476 get { return State.IsNotifiedOnMouseMove; }
03477 set { State.IsNotifiedOnMouseMove = value; }
03478 }
03479
03481 public bool IsOverridingFullScreen
03482 {
03483 get { return State.IsOverridingFullScreen; }
03484 set { State.IsOverridingFullScreen = value; }
03485 }
03486
03488 public bool IsIgnoringSizeChanges { get { return State.AreSizeChangesIgnored; } set { State.AreSizeChangesIgnored = value; } }
03489
03491 public void ResetState()
03492 {
03493 State = new FrameworkData();
03494 }
03495 #endregion
03496
03497 #region Timer Callbacks
03500 public int SetTimer(TimerCallback callbackTimer, float timeoutInSeconds)
03501 {
03502 if (callbackTimer == null)
03503 throw new ArgumentNullException("callbackTimer", "You must pass in a valid timer callback .");
03504
03505 TimerData timer = new TimerData();
03506 timer.callback = callbackTimer;
03507 timer.Countdown = timeoutInSeconds;
03508 timer.TimeoutInSecs = timeoutInSeconds;
03509 timer.IsEnabled = true;
03510
03511 State.Timers.Add(timer);
03512 return State.Timers.Count;
03513 }
03514
03516 public void KillTimer(int id)
03517 {
03518 if (id < State.Timers.Count)
03519 {
03520 TimerData timer = (TimerData)State.Timers[id];
03521 timer.IsEnabled = false;
03522 State.Timers[id] = timer;
03523 }
03524 else
03525 {
03526 throw new ArgumentException("An invalid timer ID was passed in", "id");
03527 }
03528 }
03529
03531 private void HandleTimers()
03532 {
03533 float elapsedTime = State.ElapsedTime;
03534
03535
03536 for (int i = 0; i < State.Timers.Count; i++)
03537 {
03538 TimerData ft = (TimerData)State.Timers[i];
03539 if (ft.IsEnabled)
03540 {
03541 ft.Countdown -= elapsedTime;
03542
03543 if (ft.Countdown < 0)
03544 {
03545 ft.callback((uint)i);
03546 ft.Countdown = ft.TimeoutInSecs;
03547 }
03548 State.Timers[i] = ft;
03549 }
03550 }
03551 }
03552 #endregion
03553
03555 public void CloseWindow()
03556 {
03557 if (WindowForm != null)
03558 WindowForm.Close();
03559 }
03560
03561 #region Window Message Handling
03562
03566 private void OnPaint(object sender, System.Windows.Forms.PaintEventArgs e)
03567 {
03568
03569 if ((State.Device != null) && (State.AreDeviceObjectsCreated) &&
03570 (State.AreDeviceObjectsReset) && (State.IsRenderingPaused))
03571 {
03572 double time = State.CurrentTime;
03573 float elapsedTime = State.ElapsedTime;
03574
03575 if (State.Settings != null && State.IsD3DSettingsDialogShowing)
03576 {
03577
03578 State.Device.Clear(ClearFlags.Target, 0x00003F3F, 1.0f, 0);
03579
03580
03581 State.Device.BeginScene();
03582 State.Settings.OnRender(elapsedTime);
03583 State.Device.EndScene();
03584 }
03585 else
03586 {
03587 if (State.CallbackInterface != null)
03588 {
03589 State.CallbackInterface.OnFrameRender(State.Device, time, elapsedTime);
03590 }
03591 }
03592
03593
03594 try
03595 {
03596 State.Device.Present();
03597 }
03598 catch (DeviceLostException)
03599 {
03600
03601 State.IsDeviceLost = true;
03602 }
03603 catch (DriverInternalErrorException)
03604 {
03605
03606 State.IsDeviceLost = true;
03607 }
03608 }
03609 }
03610
03614 private void OnResize(object sender, EventArgs e)
03615 {
03616 System.Windows.Forms.Form form = sender as System.Windows.Forms.Form;
03617 System.Windows.Forms.Control control = sender as System.Windows.Forms.Control;
03618
03619 if (form != null)
03620 {
03621 if (form.WindowState == System.Windows.Forms.FormWindowState.Minimized)
03622 {
03623 if ((State.IsCursorClippedWhenFullScreen) && !(IsWindowed))
03624 System.Windows.Forms.Cursor.Clip = System.Drawing.Rectangle.Empty;
03625 State.IsMinimized = true;
03626 State.IsMaximized = false;
03627 Pause(true, true);
03628 }
03629 else
03630 {
03631 if (State.IsMinimized)
03632 {
03633 Pause(false, false);
03634 }
03635 State.IsMinimized = false;
03636 State.IsMaximized = form.WindowState == System.Windows.Forms.FormWindowState.Maximized;
03637
03638
03639 HandlePossibleSizeChange();
03640 }
03641 }
03642
03643 }
03644
03648 private void OnKeyDown(object sender, System.Windows.Forms.KeyEventArgs e)
03649 {
03650 if (State.IsHandlingDefaultHotkeys)
03651 {
03652 switch (e.KeyCode)
03653 {
03654 case System.Windows.Forms.Keys.Enter:
03655 if (e.Alt)
03656 {
03657
03658 Pause(true, true);
03659 ToggleFullscreen();
03660 Pause(false, false);
03661 e.Handled = true;
03662 }
03663 break;
03664 case System.Windows.Forms.Keys.F2:
03665 ShowSettingsDialog(!State.IsD3DSettingsDialogShowing);
03666 break;
03667 case System.Windows.Forms.Keys.F3:
03668 Pause(true, true);
03669 ToggleReference();
03670 Pause(false, false);
03671 break;
03672
03673 case System.Windows.Forms.Keys.F8:
03674 State.IsInWireframeMode = !State.IsInWireframeMode;
03675 if (State.Device != null)
03676 {
03677 State.Device.RenderState.FillMode = State.IsInWireframeMode ? FillMode.WireFrame : FillMode.Solid;
03678 }
03679 break;
03680
03681 case System.Windows.Forms.Keys.Escape:
03682
03683 if (WindowForm != null)
03684 {
03685 WindowForm.Close();
03686 }
03687 break;
03688
03689 case System.Windows.Forms.Keys.Pause:
03690 bool isTimePaused = (State.PauseTimeCount > 0);
03691 isTimePaused = !isTimePaused;
03692 if (isTimePaused)
03693 Pause(true, false);
03694 else
03695 Pause(false, false);
03696
03697 break;
03698
03699 }
03700 }
03701 }
03702
03706 private void OnCursorChanged(object sender, EventArgs e)
03707 {
03708
03709 if ((!State.IsRenderingPaused) && (!IsWindowed))
03710 {
03711 System.Windows.Forms.Cursor.Current = null;
03712 if ((State.Device != null) && State.IsShowingCursorWhenFullScreen)
03713 State.Device.ShowCursor(true);
03714 }
03715 else
03716 System.Windows.Forms.Cursor.Current = System.Windows.Forms.Cursors.Default;
03717 }
03718
03722 private void OnMouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
03723 {
03724 if ((!State.IsRenderingPaused) && (!IsWindowed))
03725 {
03726 if (State.Device != null)
03727 {
03728 State.Device.SetCursorPosition(e.X, e.Y, false);
03729 }
03730 }
03731 }
03732
03736 private void OnFormClosed(object sender, EventArgs e)
03737 {
03738
03739 State.WindowFocus = null;
03740 State.WindowDeviceWindowed = null;
03741 State.WindowDeviceFullScreen = null;
03742 }
03743
03747 private void OnFormActivated(object sender, EventArgs e)
03748 {
03749 State.IsActive = true;
03750 }
03751
03755 private void OnFormDeactivated(object sender, EventArgs e)
03756 {
03757 State.IsActive = false;
03758 }
03759
03763 private void OnMenuStart(object sender, EventArgs e)
03764 {
03765 Pause(true, true);
03766 }
03767
03771 private void OnMenuEnd(object sender, EventArgs e)
03772 {
03773 Pause(false, false);
03774 }
03775
03779 private void HookEvents(System.Windows.Forms.Control c)
03780 {
03781 c.Paint += new System.Windows.Forms.PaintEventHandler(OnPaint);
03782 c.Resize += new EventHandler(OnResize);
03783 c.KeyDown += new System.Windows.Forms.KeyEventHandler(OnKeyDown);
03784 c.CursorChanged += new EventHandler(OnCursorChanged);
03785 c.MouseMove += new System.Windows.Forms.MouseEventHandler(OnMouseMove);
03786 System.Windows.Forms.Form form = c as System.Windows.Forms.Form;
03787 if (form != null)
03788 {
03789
03790 form.Closed += new EventHandler(OnFormClosed);
03791 form.Activated += new EventHandler(OnFormActivated);
03792 form.Deactivate += new EventHandler(OnFormDeactivated);
03793 form.MenuStart += new EventHandler(OnMenuStart);
03794 form.MenuComplete += new EventHandler(OnMenuEnd);
03795 }
03796 }
03798 internal void WindowsProcedure(ref System.Windows.Forms.Message m)
03799 {
03800 if (State.Settings != null && State.IsD3DSettingsDialogShowing)
03801 {
03802 State.Settings.HandleMessages(m.HWnd, (NativeMethods.WindowMessage)m.Msg, m.WParam, m.LParam);
03803 }
03804 else
03805 {
03806 if (State.WndProcFunction != null)
03807 {
03808 bool doneProcessing = false;
03809
03810
03811 IntPtr result = State.WndProcFunction(m.HWnd, (NativeMethods.WindowMessage)m.Msg, m.WParam, m.LParam, ref doneProcessing);
03812 if (doneProcessing)
03813 m.Result = result;
03814 }
03815 }
03816
03817 switch ((NativeMethods.WindowMessage)m.Msg)
03818 {
03819 case NativeMethods.WindowMessage.PowerBroadcast:
03820 if (m.WParam == IntPtr.Zero)
03821 {
03822
03823
03824
03825
03826 m.Result = TrueIntPtr;
03827 }
03828 if (m.WParam.ToInt32() == 7)
03829 {
03830
03831
03832
03833
03834
03835
03836
03837 FrameworkTimer.Reset();
03838 State.LastStatsUpdateTime = 0;
03839
03840 m.Result = TrueIntPtr;
03841 }
03842 break;
03843 case NativeMethods.WindowMessage.SystemCommand:
03844
03845 const int SystemCommandSize = 0xF000;
03846 const int SystemCommandMove = 0xF010;
03847 const int SystemCommandMaximize = 0xF030;
03848 const int SystemCommandKeyMenu = 0xF100;
03849 const int SystemCommandMonitorPower = 0xF170;
03850 switch (m.WParam.ToInt32())
03851 {
03852 case SystemCommandSize:
03853 case SystemCommandMove:
03854 case SystemCommandMaximize:
03855 case SystemCommandKeyMenu:
03856 case SystemCommandMonitorPower:
03857 if (!IsWindowed)
03858 m.Result = TrueIntPtr;
03859 break;
03860 }
03861 break;
03862 }
03863 }
03864 #endregion
03865
03870 public void MainLoop()
03871 {
03872
03873 if (isDisposed)
03874 return;
03875
03876
03877 if (State.IsInsideDeviceCallback || State.IsInsideMainloop)
03878 {
03879 State.ApplicationExitCode = 1;
03880 throw new InvalidOperationException("You cannot call this method from a callback, or reenter the method.");
03881 }
03882
03883
03884 State.IsInsideMainloop = true;
03885
03886
03887
03888 if (!State.WasDeviceCreated)
03889 {
03890 if (State.WasDeviceCreateCalled)
03891 {
03892
03893 State.ApplicationExitCode = 1;
03894 throw new InvalidOperationException("The device was never created.");
03895 }
03896
03897 try
03898 {
03899 CreateDevice(0, true, DefaultSizeWidth, DefaultSizeHeight, null);
03900 }
03901 catch
03902 {
03903
03904 State.ApplicationExitCode = 1;
03905 throw;
03906 }
03907 }
03908
03909
03910
03911
03912 if ((!State.IsInited) || (!State.WasWindowCreated) || (!State.WasDeviceCreated))
03913 {
03914 State.ApplicationExitCode = 1;
03915 throw new InvalidOperationException("The framework was not initialized, cannot continue.");
03916 }
03917
03918 using (System.Windows.Forms.Control app = Window)
03919 {
03920
03921 System.Windows.Forms.Application.Idle += new EventHandler(OnApplicationIdle);
03922
03923 if (app is System.Windows.Forms.Form)
03924 {
03925 System.Windows.Forms.Application.Run(app as System.Windows.Forms.Form);
03926 }
03927 else
03928 {
03929
03930 app.Show();
03931 System.Windows.Forms.Application.Run();
03932 }
03933 }
03934
03935 State.IsInsideMainloop = false;
03936 }
03937
03938 #region App Idle Events
03940 private void OnApplicationIdle(object sender, EventArgs e)
03941 {
03942 while (AppStillIdle)
03943 {
03944
03945 Render3DEnvironment();
03946 }
03947 }
03949 private bool AppStillIdle
03950 {
03951 get
03952 {
03953 NativeMethods.Message msg;
03954 return !NativeMethods.PeekMessage(out msg, IntPtr.Zero, 0, 0, 0);
03955 }
03956 }
03957 #endregion
03958
03959 #region IDisposable Members
03961 public void Dispose()
03962 {
03963
03964 GC.SuppressFinalize(this);
03965
03966 if (!isDisposed)
03967 {
03968
03969 if (Disposing != null)
03970 Disposing(this, EventArgs.Empty);
03971
03972
03973 if (Window != null)
03974 {
03975
03976 Window.BeginInvoke(new DisposeDelegate(this.Shutdown));
03977 }
03978 else
03979 {
03980
03981 Shutdown();
03982 }
03983 }
03984
03985
03986 isDisposed = true;
03987 }
03988
03990 ~Framework()
03991 {
03992 Dispose();
03993 }
03994 #endregion
03995
03996 #region Device event handlers
03998 private void OnDeviceDisposing(object sender, EventArgs e)
03999 {
04000
04001 State.IsInsideDeviceCallback = true;
04002
04003
04004 if (State.AreDeviceObjectsReset)
04005 {
04006 DialogResourceManager.GetGlobalInstance().OnDestroyDevice();
04007 ResourceCache.GetGlobalInstance().OnDestroyDevice();
04008 if (State.Settings != null)
04009 {
04010 State.Settings.OnDestroyDevice(this, EventArgs.Empty);
04011 }
04012 State.AreDeviceObjectsCreated = false;
04013 }
04014
04015
04016 if (Disposing != null)
04017 Disposing(this, e);
04018
04019
04020 State.IsInsideDeviceCallback = false;
04021 }
04022
04024 private void OnDeviceLost(object sender, EventArgs e)
04025 {
04026
04027 State.IsInsideDeviceCallback = true;
04028
04029
04030 if (State.AreDeviceObjectsReset)
04031 {
04032 DialogResourceManager.GetGlobalInstance().OnLostDevice();
04033 ResourceCache.GetGlobalInstance().OnLostDevice();
04034 if (State.Settings != null)
04035 {
04036 State.Settings.OnLostDevice();
04037 }
04038 State.AreDeviceObjectsReset = false;
04039 }
04040
04041
04042 if (DeviceLost != null)
04043 DeviceLost(this, e);
04044
04045
04046 State.IsInsideDeviceCallback = false;
04047 }
04048
04050 private void OnDeviceReset(object sender, EventArgs e)
04051 {
04052
04053 Device device = sender as Device;
04054 System.Diagnostics.Debug.Assert(device != null, "Must have a device here.");
04055
04056
04057 State.IsInsideDeviceCallback = true;
04058
04059
04060
04061 PrepareDevice(device);
04062
04063 if (State.Settings != null)
04064 State.Settings.OnResetDevice();
04065
04066
04067 DialogResourceManager.GetGlobalInstance().OnResetDevice(device);
04068
04069 ResourceCache.GetGlobalInstance().OnResetDevice(device);
04070
04071
04072 if (DeviceReset != null)
04073 DeviceReset(this, new DeviceEventArgs(device, State.BackBufferSurfaceDesc));
04074
04075
04076 State.AreDeviceObjectsReset = true;
04077
04078 State.IsInsideDeviceCallback = false;
04079 }
04080 #endregion
04081
04082 }
04083 }