OSDN Git Service

rev154(Direct3D9Ex対応)の続き。今度はwindowでの起動に失敗していた問題を修正。これでフルスクリーンとウインドウ、どちらも大丈夫となった。
[dtxmania/dtxmania.git] / FDK17プロジェクト / コード / 01.フレームワーク / Rendering / GraphicsDeviceManager.cs
1 /*\r
2 * Copyright (c) 2007-2009 SlimDX Group\r
3\r
4 * Permission is hereby granted, free of charge, to any person obtaining a copy\r
5 * of this software and associated documentation files (the "Software"), to deal\r
6 * in the Software without restriction, including without limitation the rights\r
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r
8 * copies of the Software, and to permit persons to whom the Software is\r
9 * furnished to do so, subject to the following conditions:\r
10\r
11 * The above copyright notice and this permission notice shall be included in\r
12 * all copies or substantial portions of the Software.\r
13\r
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r
20 * THE SOFTWARE.\r
21 */\r
22 using System;\r
23 using System.ComponentModel;\r
24 using System.Drawing;\r
25 using System.Text;\r
26 using System.Threading;\r
27 using System.Windows.Forms;\r
28 using SlimDX;\r
29 using SlimDX.Direct3D9;\r
30 using SlimDX.DXGI;\r
31 using System.Diagnostics;\r
32 namespace SampleFramework\r
33 {\r
34     /// <summary>\r
35     /// Handles the configuration and management of the graphics device.\r
36     /// </summary>\r
37     public class GraphicsDeviceManager : IDisposable\r
38     {\r
39         Game game;\r
40         bool ignoreSizeChanges;\r
41         bool deviceLost;\r
42 //        bool doNotStoreBufferSize;\r
43 //        bool renderingOccluded;\r
44 \r
45         int fullscreenWindowWidth;\r
46         int fullscreenWindowHeight;\r
47         int windowedWindowWidth;\r
48         int windowedWindowHeight;\r
49         WINDOWPLACEMENT windowedPlacement;\r
50         long windowedStyle;\r
51         bool savedTopmost;\r
52 \r
53 #if TEST_Direct3D9Ex\r
54                 internal static Direct3DEx Direct3D9Object                      // yyagi\r
55 #else\r
56                 internal static Direct3D Direct3D9Object\r
57 #endif\r
58                 {\r
59             get;\r
60             private set;\r
61         }\r
62 \r
63         public DeviceSettings CurrentSettings\r
64         {\r
65             get;\r
66             private set;\r
67         }\r
68         public bool IsWindowed\r
69         {\r
70             get { return CurrentSettings.Windowed; }\r
71         }\r
72         public int ScreenWidth\r
73         {\r
74             get { return CurrentSettings.BackBufferWidth; }\r
75         }\r
76         public int ScreenHeight\r
77         {\r
78             get { return CurrentSettings.BackBufferHeight; }\r
79         }\r
80         public Size ScreenSize\r
81         {\r
82             get { return new Size(CurrentSettings.BackBufferWidth, CurrentSettings.BackBufferHeight); }\r
83         }\r
84         public Direct3D9Manager Direct3D9\r
85         {\r
86             get;\r
87             private set;\r
88         }\r
89         public string DeviceStatistics\r
90         {\r
91             get;\r
92             private set;\r
93         }\r
94         public string DeviceInformation\r
95         {\r
96             get;\r
97             private set;\r
98         }\r
99 \r
100                 public GraphicsDeviceManager( Game game )\r
101                 {\r
102                         if( game == null )\r
103                                 throw new ArgumentNullException( "game" );\r
104 \r
105                         this.game = game;\r
106 \r
107                         game.Window.ScreenChanged += Window_ScreenChanged;\r
108                         game.Window.UserResized += Window_UserResized;\r
109 \r
110                         game.FrameStart += game_FrameStart;\r
111                         game.FrameEnd += game_FrameEnd;\r
112 \r
113                         Direct3D9 = new Direct3D9Manager( this );\r
114                 }\r
115 \r
116         public void Dispose()\r
117         {\r
118             Dispose(true);\r
119             GC.SuppressFinalize(this);\r
120         }\r
121 \r
122                 public void ChangeDevice( DeviceSettings settings, DeviceSettings minimumSettings )\r
123                 {\r
124                         if( settings == null )\r
125                                 throw new ArgumentNullException( "settings" );\r
126 \r
127                         Enumeration9.MinimumSettings = minimumSettings;\r
128 \r
129                         DeviceSettings validSettings = DeviceSettings.FindValidSettings( settings );\r
130 \r
131                         validSettings.Direct3D9.PresentParameters.DeviceWindowHandle = game.Window.Handle;\r
132 \r
133                         CreateDevice( validSettings );\r
134                 }\r
135         public void ChangeDevice(bool windowed, int desiredWidth, int desiredHeight)\r
136         {\r
137             DeviceSettings desiredSettings = new DeviceSettings();\r
138             desiredSettings.Windowed = windowed;\r
139             desiredSettings.BackBufferWidth = desiredWidth;\r
140             desiredSettings.BackBufferHeight = desiredHeight;\r
141 \r
142             ChangeDevice(desiredSettings, null);\r
143         }\r
144         public void ChangeDevice(DeviceSettings settings)\r
145         {\r
146             ChangeDevice(settings, null);\r
147         }\r
148 \r
149         public void ToggleFullScreen()\r
150         {\r
151             if (!EnsureDevice())\r
152                 throw new InvalidOperationException("No valid device.");\r
153 \r
154             DeviceSettings newSettings = CurrentSettings.Clone();\r
155 \r
156             newSettings.Windowed = !newSettings.Windowed;\r
157 \r
158             int width = newSettings.Windowed ? windowedWindowWidth : fullscreenWindowWidth;\r
159             int height = newSettings.Windowed ? windowedWindowHeight : fullscreenWindowHeight;\r
160 \r
161             newSettings.BackBufferWidth = width;\r
162             newSettings.BackBufferHeight = height;\r
163 \r
164             ChangeDevice(newSettings);\r
165         }\r
166         public bool EnsureDevice()\r
167         {\r
168             if (Direct3D9.Device != null && !deviceLost)\r
169                 return true;\r
170 \r
171             return false;\r
172         }\r
173 \r
174                 protected virtual void Dispose( bool disposing )\r
175                 {\r
176                         if( this.bDisposed )\r
177                                 return;\r
178                         this.bDisposed = true;\r
179 \r
180                         if( disposing )\r
181                                 ReleaseDevice();\r
182 \r
183                 }\r
184                 private bool bDisposed = false;\r
185 \r
186         void CreateDevice(DeviceSettings settings)\r
187         {\r
188             DeviceSettings oldSettings = CurrentSettings;\r
189             CurrentSettings = settings;\r
190 \r
191             ignoreSizeChanges = true;\r
192 \r
193             bool keepCurrentWindowSize = false;\r
194             if (settings.BackBufferWidth == 0 && settings.BackBufferHeight == 0)\r
195                 keepCurrentWindowSize = true;\r
196 \r
197             // handle the window state in Direct3D9 (it will be handled for us in DXGI)\r
198                 // check if we are going to windowed or fullscreen mode\r
199                         if( settings.Windowed )\r
200                         {\r
201                                 if( oldSettings != null && !oldSettings.Windowed )\r
202                                         NativeMethods.SetWindowLong( game.Window.Handle, WindowConstants.GWL_STYLE, (uint) windowedStyle );\r
203                         }\r
204                         else\r
205                         {\r
206                                 if( oldSettings == null || oldSettings.Windowed )\r
207                                 {\r
208                                         savedTopmost = game.Window.TopMost;\r
209                                         long style = NativeMethods.GetWindowLong( game.Window.Handle, WindowConstants.GWL_STYLE );\r
210                                         style &= ~WindowConstants.WS_MAXIMIZE & ~WindowConstants.WS_MINIMIZE;\r
211                                         windowedStyle = style;\r
212 \r
213                                         windowedPlacement = new WINDOWPLACEMENT();\r
214                                         windowedPlacement.length = WINDOWPLACEMENT.Length;\r
215                                         NativeMethods.GetWindowPlacement( game.Window.Handle, ref windowedPlacement );\r
216                                 }\r
217 \r
218                                 // hide the window until we are done messing with it\r
219                                 game.Window.Hide();\r
220                                 NativeMethods.SetWindowLong( game.Window.Handle, WindowConstants.GWL_STYLE, (uint) ( WindowConstants.WS_POPUP | WindowConstants.WS_SYSMENU ) );\r
221 \r
222                                 WINDOWPLACEMENT placement = new WINDOWPLACEMENT();\r
223                                 placement.length = WINDOWPLACEMENT.Length;\r
224                                 NativeMethods.GetWindowPlacement( game.Window.Handle, ref placement );\r
225 \r
226                                 // check if we are in the middle of a restore\r
227                                 if( ( placement.flags & WindowConstants.WPF_RESTORETOMAXIMIZED ) != 0 )\r
228                                 {\r
229                                         // update the flags to avoid sizing issues\r
230                                         placement.flags &= ~WindowConstants.WPF_RESTORETOMAXIMIZED;\r
231                                         placement.showCmd = WindowConstants.SW_RESTORE;\r
232                                         NativeMethods.SetWindowPlacement( game.Window.Handle, ref placement );\r
233                                 }\r
234                         }\r
235 \r
236             if (settings.Windowed)\r
237             {\r
238                 if (oldSettings != null && !oldSettings.Windowed)\r
239                 {\r
240                     fullscreenWindowWidth = oldSettings.BackBufferWidth;\r
241                     fullscreenWindowHeight = oldSettings.BackBufferHeight;\r
242                 }\r
243             }\r
244             else\r
245             {\r
246                 if (oldSettings != null && oldSettings.Windowed)\r
247                 {\r
248                     windowedWindowWidth = oldSettings.BackBufferWidth;\r
249                     windowedWindowHeight = oldSettings.BackBufferHeight;\r
250                 }\r
251             }\r
252 \r
253             // check if the device can be reset, or if we need to completely recreate it\r
254             Result result = SlimDX.Direct3D9.ResultCode.Success;\r
255             bool canReset = CanDeviceBeReset(oldSettings, settings);\r
256             if (canReset)\r
257                 result = ResetDevice();\r
258 \r
259             if (result == SlimDX.Direct3D9.ResultCode.DeviceLost)\r
260                 deviceLost = true;\r
261             else if (!canReset || result.IsFailure)\r
262             {\r
263                 if (oldSettings != null)\r
264                     ReleaseDevice();\r
265 \r
266                 InitializeDevice();\r
267             }\r
268 \r
269             UpdateDeviceInformation();\r
270 \r
271             // check if we changed from fullscreen to windowed mode\r
272             if (oldSettings != null && !oldSettings.Windowed && settings.Windowed)\r
273             {\r
274                 NativeMethods.SetWindowPlacement(game.Window.Handle, ref windowedPlacement);\r
275                 game.Window.TopMost = savedTopmost;\r
276             }\r
277 \r
278             // check if we need to resize\r
279             if (settings.Windowed && !keepCurrentWindowSize)\r
280             {\r
281                 int width;\r
282                 int height;\r
283                 if (NativeMethods.IsIconic(game.Window.Handle))\r
284                 {\r
285                     WINDOWPLACEMENT placement = new WINDOWPLACEMENT();\r
286                     placement.length = WINDOWPLACEMENT.Length;\r
287                     NativeMethods.GetWindowPlacement(game.Window.Handle, ref placement);\r
288 \r
289                     // check if we are being restored\r
290                     if ((placement.flags & WindowConstants.WPF_RESTORETOMAXIMIZED) != 0 && placement.showCmd == WindowConstants.SW_SHOWMINIMIZED)\r
291                     {\r
292                         NativeMethods.ShowWindow(game.Window.Handle, WindowConstants.SW_RESTORE);\r
293 \r
294                         Rectangle rect = NativeMethods.GetClientRectangle(game.Window.Handle);\r
295 \r
296                         width = rect.Width;\r
297                         height = rect.Height;\r
298                         NativeMethods.ShowWindow(game.Window.Handle, WindowConstants.SW_MINIMIZE);\r
299                     }\r
300                     else\r
301                     {\r
302                         NativeRectangle frame = new NativeRectangle();\r
303                         NativeMethods.AdjustWindowRect(ref frame, (uint)windowedStyle, false);\r
304                         int frameWidth = frame.right - frame.left;\r
305                         int frameHeight = frame.bottom - frame.top;\r
306 \r
307                         width = placement.rcNormalPosition.right - placement.rcNormalPosition.left - frameWidth;\r
308                         height = placement.rcNormalPosition.bottom - placement.rcNormalPosition.top - frameHeight;\r
309                     }\r
310                 }\r
311                 else\r
312                 {\r
313                     Rectangle rect = NativeMethods.GetClientRectangle(game.Window.Handle);\r
314                     width = rect.Width;\r
315                     height = rect.Height;\r
316                 }\r
317 \r
318                 // check if we have a different desired size\r
319                 if (width != settings.BackBufferWidth ||\r
320                     height != settings.BackBufferHeight)\r
321                 {\r
322                     if (NativeMethods.IsIconic(game.Window.Handle))\r
323                         NativeMethods.ShowWindow(game.Window.Handle, WindowConstants.SW_RESTORE);\r
324                     if (NativeMethods.IsZoomed(game.Window.Handle))\r
325                         NativeMethods.ShowWindow(game.Window.Handle, WindowConstants.SW_RESTORE);\r
326 \r
327                     NativeRectangle rect = new NativeRectangle();\r
328                     rect.right = settings.BackBufferWidth;\r
329                     rect.bottom = settings.BackBufferHeight;\r
330                     NativeMethods.AdjustWindowRect(ref rect,\r
331                         NativeMethods.GetWindowLong(game.Window.Handle, WindowConstants.GWL_STYLE), false);\r
332 \r
333                     NativeMethods.SetWindowPos(game.Window.Handle, IntPtr.Zero, 0, 0, rect.right - rect.left,\r
334                         rect.bottom - rect.top, WindowConstants.SWP_NOZORDER | WindowConstants.SWP_NOMOVE);\r
335 \r
336                     Rectangle r = NativeMethods.GetClientRectangle(game.Window.Handle);\r
337                     int clientWidth = r.Width;\r
338                     int clientHeight = r.Height;\r
339 \r
340                     // check if the size was modified by Windows\r
341                     if (clientWidth != settings.BackBufferWidth ||\r
342                         clientHeight != settings.BackBufferHeight)\r
343                     {\r
344                         DeviceSettings newSettings = CurrentSettings.Clone();\r
345                         newSettings.BackBufferWidth = 0;\r
346                         newSettings.BackBufferHeight = 0;\r
347                         if (newSettings.Direct3D9 != null)\r
348                         {\r
349                                                         newSettings.Direct3D9.PresentParameters.BackBufferWidth = 640;  // #23510 2010.10.31 add yyagi: to avoid setting BackBufferSize=ClientSize\r
350                                                         newSettings.Direct3D9.PresentParameters.BackBufferHeight = 480; // #23510 2010.10.31 add yyagi: to avoid setting BackBufferSize=ClientSize\r
351                         }\r
352 \r
353                         CreateDevice(newSettings);\r
354                     }\r
355                 }\r
356             }\r
357 \r
358             // if the window is still hidden, make sure it is shown\r
359             if (!game.Window.Visible)\r
360                 NativeMethods.ShowWindow(game.Window.Handle, WindowConstants.SW_SHOW);\r
361 \r
362             // set the execution state of the thread\r
363             if (!IsWindowed)\r
364                 NativeMethods.SetThreadExecutionState(WindowConstants.ES_DISPLAY_REQUIRED | WindowConstants.ES_CONTINUOUS);\r
365             else\r
366                 NativeMethods.SetThreadExecutionState(WindowConstants.ES_CONTINUOUS);\r
367 \r
368             ignoreSizeChanges = false;\r
369         }\r
370 \r
371                 void Window_UserResized( object sender, EventArgs e )\r
372                 {\r
373                         if( ignoreSizeChanges || !EnsureDevice() || ( !IsWindowed ) )\r
374                                 return;\r
375 \r
376                         DeviceSettings newSettings = CurrentSettings.Clone();\r
377 \r
378                         Rectangle rect = NativeMethods.GetClientRectangle( game.Window.Handle );\r
379                         if( rect.Width != newSettings.BackBufferWidth || rect.Height != newSettings.BackBufferHeight )\r
380                         {\r
381                                 newSettings.BackBufferWidth = 0;\r
382                                 newSettings.BackBufferHeight = 0;\r
383                                 newSettings.Direct3D9.PresentParameters.BackBufferWidth = 640;          // #23510 2010.10.31 add yyagi: to avoid setting BackBufferSize=ClientSize\r
384                                 newSettings.Direct3D9.PresentParameters.BackBufferHeight = 480;         // \r
385                                 CreateDevice( newSettings );\r
386                         }\r
387                 }\r
388                 void Window_ScreenChanged( object sender, EventArgs e )\r
389                 {\r
390                         if( !EnsureDevice() || !CurrentSettings.Windowed || ignoreSizeChanges )\r
391                                 return;\r
392 \r
393                         IntPtr windowMonitor = NativeMethods.MonitorFromWindow( game.Window.Handle, WindowConstants.MONITOR_DEFAULTTOPRIMARY );\r
394 \r
395                         DeviceSettings newSettings = CurrentSettings.Clone();\r
396                         int adapterOrdinal = GetAdapterOrdinal( windowMonitor );\r
397                         if( adapterOrdinal == -1 )\r
398                                 return;\r
399                         newSettings.Direct3D9.AdapterOrdinal = adapterOrdinal;\r
400 \r
401                         newSettings.BackBufferWidth = 0;                                                                // #23510 2010.11.1 add yyagi to avoid to reset to 640x480 for the first time in XP.\r
402                         newSettings.BackBufferHeight = 0;                                                               //\r
403                         newSettings.Direct3D9.PresentParameters.BackBufferWidth = 640;  //\r
404                         newSettings.Direct3D9.PresentParameters.BackBufferHeight = 480; //\r
405 \r
406                         CreateDevice(newSettings);\r
407                 }\r
408 \r
409                 void game_FrameEnd( object sender, EventArgs e )\r
410                 {\r
411                         Result result = SlimDX.Direct3D9.ResultCode.Success;\r
412                         try\r
413                         {\r
414                                 result = Direct3D9.Device.Present();\r
415                         }\r
416                         catch (Direct3D9Exception)                              // #23842 2011.1.6 yyagi: catch D3D9Exception to avoid unexpected termination by changing VSyncWait in fullscreen.\r
417                         {\r
418                                 deviceLost = true;\r
419                         }\r
420                         if( result == SlimDX.Direct3D9.ResultCode.DeviceLost )\r
421                                 deviceLost = true;\r
422                 }\r
423         void game_FrameStart(object sender, CancelEventArgs e)\r
424         {\r
425             if (Direct3D9.Device == null )\r
426             {\r
427                 e.Cancel = true;\r
428                 return;\r
429             }\r
430 \r
431 //            if (!game.IsActive || deviceLost)         // #23568 2010.11.3 yyagi: separate conditions to support valiable sleep value when !IsActive.\r
432                         if (deviceLost)\r
433                                 Thread.Sleep(50);\r
434                         else if (!game.IsActive && !this.CurrentSettings.EnableVSync)   // #23568 2010.11.4 yyagi: Don't add sleep() while VSync is enabled.\r
435                                 Thread.Sleep(this.game.InactiveSleepTime.Milliseconds);\r
436 \r
437             if (deviceLost)\r
438             {\r
439                 Result result = Direct3D9.Device.TestCooperativeLevel();\r
440                 if (result == SlimDX.Direct3D9.ResultCode.DeviceLost)\r
441                 {\r
442                     e.Cancel = true;\r
443                     return;\r
444                 }\r
445 \r
446                 // if we are windowed, check the adapter format to see if the user\r
447                 // changed the desktop format, causing a lost device\r
448                 if (IsWindowed)\r
449                 {\r
450                     DisplayMode displayMode = GraphicsDeviceManager.Direct3D9Object.GetAdapterDisplayMode(CurrentSettings.Direct3D9.AdapterOrdinal);\r
451                     if (CurrentSettings.Direct3D9.AdapterFormat != displayMode.Format)\r
452                     {\r
453                         DeviceSettings newSettings = CurrentSettings.Clone();\r
454                         ChangeDevice(newSettings);\r
455                         e.Cancel = true;\r
456                         return;\r
457                     }\r
458                 }\r
459 \r
460                 result = ResetDevice();\r
461                 if (result.IsFailure)\r
462                 {\r
463                     e.Cancel = true;\r
464                     return;\r
465                 }\r
466             }\r
467 \r
468             deviceLost = false;\r
469         }\r
470 \r
471                 bool CanDeviceBeReset( DeviceSettings oldSettings, DeviceSettings newSettings )\r
472                 {\r
473                         if( oldSettings == null )\r
474                                 return false;\r
475 \r
476                         return Direct3D9.Device != null &&\r
477                                 oldSettings.Direct3D9.AdapterOrdinal == newSettings.Direct3D9.AdapterOrdinal &&\r
478                                 oldSettings.Direct3D9.DeviceType == newSettings.Direct3D9.DeviceType &&\r
479                                 oldSettings.Direct3D9.CreationFlags == newSettings.Direct3D9.CreationFlags;\r
480                 }\r
481 \r
482         void InitializeDevice()\r
483         {\r
484                         try\r
485                         {\r
486                                 EnsureD3D9();\r
487 \r
488 #if TEST_Direct3D9Ex\r
489                                 // 2011.4.26 yyagi\r
490                                 // Direct3D9.DeviceExを呼ぶ際(IDirect3D9Ex::CreateDeviceExを呼ぶ際)、\r
491                                 // フルスクリーンモードで初期化する場合はDisplayModeEx(D3DDISPLAYMODEEX *pFullscreenDisplayMode)に\r
492                                 // 適切な値を設定する必要あり。\r
493                                 // 一方、ウインドウモードで初期化する場合は、D3DDISPLAYMODEEXをNULLにする必要があるが、\r
494                                 // DisplayModeExがNULL不可と定義されているため、DeviceExのoverloadの中でDisplayModeExを引数に取らないものを\r
495                                 // 使う。(DeviceEx側でD3DDISPLAYMODEEXをNULLにしてくれる)\r
496                                 // 結局、DeviceExの呼び出しの際に、フルスクリーンかどうかで場合分けが必要となる。\r
497                                 if ( CurrentSettings.Direct3D9.PresentParameters.Windowed == false )\r
498                                 {\r
499                                         DisplayModeEx fullScreenDisplayMode = new DisplayModeEx();\r
500                                         fullScreenDisplayMode.Width = CurrentSettings.Direct3D9.PresentParameters.BackBufferWidth;\r
501                                         fullScreenDisplayMode.Height = CurrentSettings.Direct3D9.PresentParameters.BackBufferHeight;\r
502                                         fullScreenDisplayMode.RefreshRate = CurrentSettings.Direct3D9.PresentParameters.FullScreenRefreshRateInHertz;\r
503                                         fullScreenDisplayMode.Format = CurrentSettings.Direct3D9.PresentParameters.BackBufferFormat;\r
504 \r
505                                         Direct3D9.Device = new SlimDX.Direct3D9.DeviceEx( Direct3D9Object, CurrentSettings.Direct3D9.AdapterOrdinal,\r
506                                                 CurrentSettings.Direct3D9.DeviceType, game.Window.Handle,\r
507                                                 CurrentSettings.Direct3D9.CreationFlags, CurrentSettings.Direct3D9.PresentParameters, fullScreenDisplayMode );\r
508                                 }\r
509                                 else\r
510                                 {\r
511                                         Direct3D9.Device = new SlimDX.Direct3D9.DeviceEx( Direct3D9Object, CurrentSettings.Direct3D9.AdapterOrdinal,\r
512                                                 CurrentSettings.Direct3D9.DeviceType, game.Window.Handle,\r
513                                                 CurrentSettings.Direct3D9.CreationFlags, CurrentSettings.Direct3D9.PresentParameters );\r
514                                 }\r
515 #else\r
516                                 Direct3D9.Device = new SlimDX.Direct3D9.Device( Direct3D9Object, CurrentSettings.Direct3D9.AdapterOrdinal,\r
517                                         CurrentSettings.Direct3D9.DeviceType, game.Window.Handle,\r
518                                         CurrentSettings.Direct3D9.CreationFlags, CurrentSettings.Direct3D9.PresentParameters );\r
519 #endif\r
520                                 if ( Result.Last == SlimDX.Direct3D9.ResultCode.DeviceLost )\r
521                                 {\r
522                                         deviceLost = true;\r
523                                         return;\r
524                                 }\r
525 #if TEST_Direct3D9Ex\r
526                                 Direct3D9.Device.MaximumFrameLatency = 0;                       // yyagi\r
527 #endif\r
528                         }\r
529                         catch( Exception e )\r
530                         {\r
531                                 throw new DeviceCreationException( "Could not create graphics device.", e );\r
532                         }\r
533 \r
534             PropogateSettings();\r
535 \r
536             UpdateDeviceStats();\r
537 \r
538             game.Initialize();\r
539             game.LoadContent();\r
540         }\r
541 \r
542                 Result ResetDevice()\r
543                 {\r
544                         game.UnloadContent();\r
545 \r
546                         Result result = Direct3D9.Device.Reset( CurrentSettings.Direct3D9.PresentParameters );\r
547                         if( result == SlimDX.Direct3D9.ResultCode.DeviceLost )\r
548                                 return result;\r
549 \r
550                         PropogateSettings();\r
551                         UpdateDeviceStats();\r
552                         game.LoadContent();\r
553 \r
554                         return Result.Last;\r
555                 }\r
556 \r
557                 void ReleaseDevice()\r
558         {\r
559             ReleaseDevice9();\r
560         }\r
561         void ReleaseDevice9()\r
562         {\r
563             if (Direct3D9.Device == null)\r
564                 return;\r
565 \r
566             if (game != null)\r
567             {\r
568                 game.UnloadContent();\r
569                 game.Dispose(true);\r
570             }\r
571 \r
572                         try\r
573                         {\r
574                                 Direct3D9.Device.Dispose();\r
575                         }\r
576                         catch( ObjectDisposedException )\r
577                         {\r
578                                 // 時々発生するのでキャッチしておく。\r
579                         }\r
580             Direct3D9Object.Dispose();\r
581 \r
582             Direct3D9Object = null;\r
583             Direct3D9.Device = null;\r
584         }\r
585                 void PropogateSettings()\r
586                 {\r
587                         CurrentSettings.BackBufferCount = CurrentSettings.Direct3D9.PresentParameters.BackBufferCount;\r
588                         CurrentSettings.BackBufferWidth = CurrentSettings.Direct3D9.PresentParameters.BackBufferWidth;\r
589                         CurrentSettings.BackBufferHeight = CurrentSettings.Direct3D9.PresentParameters.BackBufferHeight;\r
590                         CurrentSettings.BackBufferFormat = CurrentSettings.Direct3D9.PresentParameters.BackBufferFormat;\r
591                         CurrentSettings.DepthStencilFormat = CurrentSettings.Direct3D9.PresentParameters.AutoDepthStencilFormat;\r
592                         CurrentSettings.DeviceType = CurrentSettings.Direct3D9.DeviceType;\r
593                         CurrentSettings.MultisampleQuality = CurrentSettings.Direct3D9.PresentParameters.MultisampleQuality;\r
594                         CurrentSettings.MultisampleType = CurrentSettings.Direct3D9.PresentParameters.Multisample;\r
595                         CurrentSettings.RefreshRate = CurrentSettings.Direct3D9.PresentParameters.FullScreenRefreshRateInHertz;\r
596                         CurrentSettings.Windowed = CurrentSettings.Direct3D9.PresentParameters.Windowed;\r
597                 }\r
598 \r
599                 void UpdateDeviceInformation()\r
600                 {\r
601                         StringBuilder builder = new StringBuilder();\r
602 \r
603                         if( CurrentSettings.Direct3D9.DeviceType == DeviceType.Hardware )\r
604                                 builder.Append( "HAL" );\r
605                         else if( CurrentSettings.Direct3D9.DeviceType == DeviceType.Reference )\r
606                                 builder.Append( "REF" );\r
607                         else if( CurrentSettings.Direct3D9.DeviceType == DeviceType.Software )\r
608                                 builder.Append( "SW" );\r
609 \r
610                         if( ( CurrentSettings.Direct3D9.CreationFlags & CreateFlags.HardwareVertexProcessing ) != 0 )\r
611                                 if( CurrentSettings.Direct3D9.DeviceType == DeviceType.Hardware )\r
612                                         builder.Append( " (hw vp)" );\r
613                                 else\r
614                                         builder.Append( " (simulated hw vp)" );\r
615                         else if( ( CurrentSettings.Direct3D9.CreationFlags & CreateFlags.MixedVertexProcessing ) != 0 )\r
616                                 if( CurrentSettings.Direct3D9.DeviceType == DeviceType.Hardware )\r
617                                         builder.Append( " (mixed vp)" );\r
618                                 else\r
619                                         builder.Append( " (simulated mixed vp)" );\r
620                         else\r
621                                 builder.Append( " (sw vp)" );\r
622 \r
623                         if( CurrentSettings.Direct3D9.DeviceType == DeviceType.Hardware )\r
624                         {\r
625                                 // loop through each adapter until we find the right one\r
626                                 foreach( AdapterInfo9 adapterInfo in Enumeration9.Adapters )\r
627                                 {\r
628                                         if( adapterInfo.AdapterOrdinal == CurrentSettings.Direct3D9.AdapterOrdinal )\r
629                                         {\r
630                                                 builder.AppendFormat( ": {0}", adapterInfo.Description );\r
631                                                 break;\r
632                                         }\r
633                                 }\r
634                         }\r
635 \r
636                         DeviceInformation = builder.ToString();\r
637                 }\r
638 \r
639                 void UpdateDeviceStats()\r
640                 {\r
641                         StringBuilder builder = new StringBuilder();\r
642 \r
643                         builder.Append( "D3D9 Vsync " );\r
644 \r
645                         if( CurrentSettings.Direct3D9.PresentParameters.PresentationInterval == PresentInterval.Immediate )\r
646                                 builder.Append( "off" );\r
647                         else\r
648                                 builder.Append( "on" );\r
649 \r
650                         builder.AppendFormat( " ({0}x{1}), ", CurrentSettings.Direct3D9.PresentParameters.BackBufferWidth, CurrentSettings.Direct3D9.PresentParameters.BackBufferHeight );\r
651 \r
652                         if( CurrentSettings.Direct3D9.AdapterFormat == CurrentSettings.Direct3D9.PresentParameters.BackBufferFormat )\r
653                                 builder.Append( Enum.GetName( typeof( SlimDX.Direct3D9.Format ), CurrentSettings.Direct3D9.AdapterFormat ) );\r
654                         else\r
655                                 builder.AppendFormat( "backbuf {0}, adapter {1}",\r
656                                         Enum.GetName( typeof( SlimDX.Direct3D9.Format ), CurrentSettings.Direct3D9.AdapterFormat ),\r
657                                         Enum.GetName( typeof( SlimDX.Direct3D9.Format ), CurrentSettings.Direct3D9.PresentParameters.BackBufferFormat ) );\r
658 \r
659                         builder.AppendFormat( " ({0})", Enum.GetName( typeof( SlimDX.Direct3D9.Format ), CurrentSettings.Direct3D9.PresentParameters.AutoDepthStencilFormat ) );\r
660 \r
661                         if( CurrentSettings.Direct3D9.PresentParameters.Multisample == MultisampleType.NonMaskable )\r
662                                 builder.Append( " (Nonmaskable Multisample)" );\r
663                         else if( CurrentSettings.Direct3D9.PresentParameters.Multisample != MultisampleType.None )\r
664                                 builder.AppendFormat( " ({0}x Multisample)", (int) CurrentSettings.Direct3D9.PresentParameters.Multisample );\r
665 \r
666                         DeviceStatistics = builder.ToString();\r
667                 }\r
668 \r
669                 int GetAdapterOrdinal( IntPtr screen )\r
670                 {\r
671                         AdapterInfo9 adapter = null;\r
672                         foreach( AdapterInfo9 a in Enumeration9.Adapters )\r
673                         {\r
674                                 if( Direct3D9Object.GetAdapterMonitor( a.AdapterOrdinal ) == screen )\r
675                                 {\r
676                                         adapter = a;\r
677                                         break;\r
678                                 }\r
679                         }\r
680 \r
681                         if( adapter != null )\r
682                                 return adapter.AdapterOrdinal;\r
683 \r
684                         return -1;\r
685                 }\r
686 \r
687         internal static void EnsureD3D9()\r
688         {\r
689                         if ( Direct3D9Object == null )\r
690 #if TEST_Direct3D9Ex\r
691                                 Direct3D9Object = new Direct3DEx();             // yyagi\r
692 #else\r
693                                 Direct3D9Object = new Direct3D();\r
694 #endif\r
695         }\r
696     }\r
697 }\r