/// <summary> /// Deferres a routine into the OpenAL thread and waits for the execution. /// </summary> /// <param name="routine">The routine to be deferred.</param> public void InvokeOpenAL(DeferredRoutine routine) { if (routine == null) { return; } if (Thread.CurrentThread == this.soundThread) { routine(); } else { var handler = new DeferredRoutineHandler() { Routine = routine, WaitHandle = new ManualResetEvent(false), CreatingMethod = new StackTrace().GetFrame(1).GetMethod() }; this.deferredALRoutines.Enqueue(handler); handler.WaitHandle.WaitOne(); } }
/// <summary> /// Deferres a routine into another thread so the current thread can continue. /// </summary> /// <remarks>Useful for loading assets or resources.</remarks> /// <param name="openGL">Defines if the routine is deferred into the OpenGL thread or not.</param> /// <param name="routine">The routine to be deferred.</param> public WaitHandle DeferRoutine(bool openGL, DeferredRoutine routine) { if (routine == null) { return(null); } var handler = new DeferredRoutineHandler() { Routine = routine, WaitHandle = new ManualResetEvent(false) }; if (openGL) { this.deferredGLRoutines.Enqueue(handler); } else { this.deferredRoutines.Enqueue(handler); } return(handler.WaitHandle); }
/// <summary> /// Starts the game main loop. /// </summary> public void Run() { this.drawThread = Thread.CurrentThread; Game.currentGame.Value = this; var presentation = this.GetPresentationParameters(); using (GameWindow window = new GameWindow( presentation.Resolution.Width, presentation.Resolution.Height, presentation.GraphicsMode, presentation.Title, presentation.IsFullscreen ? GameWindowFlags.Fullscreen : GameWindowFlags.Default, presentation.DisplayDevice ?? DisplayDevice.Default, 4, 1, #if DEBUG GraphicsContextFlags.Default | GraphicsContextFlags.ForwardCompatible | GraphicsContextFlags.Debug)) #else GraphicsContextFlags.Default | GraphicsContextFlags.ForwardCompatible)) #endif { window.VSync = presentation.VSync ? VSyncMode.On : VSyncMode.Off; window.Closing += (s, e) => { this.isRunning = false; }; window.Visible = true; this.input = new InputManager( window.Keyboard, window.Mouse, window.Joysticks.ToArray()); this.Utilities = new GameUtilities(this); this.Assets = new AssetManager(); this.Size = presentation.Resolution; this.isRunning = true; // Start the deferral threads for deferred routines for (int i = 0; i < this.deferralThreads.Length; i++) { this.deferralThreads[i] = new Thread(this.DeferRoutines); this.deferralThreads[i].Name = "OpenWorld Deferred Routines Host"; this.deferralThreads[i].Start(); } // Start the sound thread. this.soundThread = new Thread(this.SoundLoop); this.soundThread.Name = "OpenWorld Sound Thread"; this.soundThread.Start(); // Load everything in the draw thread this.OnLoad(); // Start the update thread. this.updateThread = new Thread(this.UpdateLoop); this.updateThread.Name = "OpenWorld Game Update Thread"; this.updateThread.Start(); Thread.CurrentThread.Name = "OpenWorld Game Render Thread"; while (this.isRunning) { do { DeferredRoutineHandler handler = null; if (this.deferredGLRoutines.TryDequeue(out handler)) { handler.Routine(); handler.WaitHandle.Set(); } Thread.Sleep(0); } while (!this.isRendering); // Process the window, draw everything, then show it. window.ProcessEvents(); if (!window.IsExiting) { this.OnDrawPreState(this.Time); if (this.currentState != null) { this.currentState.Draw(this.Time); } this.OnDrawPostState(this.Time); window.SwapBuffers(); } this.isRendering = false; Thread.Sleep(16); } // Unload everything in the draw thread. this.OnUnload(); for (int i = 0; i < this.deferralThreads.Length; i++) { this.deferralThreads[i].Join(); this.deferralThreads[i] = null; } this.updateThread.Join(); this.input = null; this.Size = new System.Drawing.Size(); if (this.Disposing != null) { this.Disposing(); } this.Assets.CleanUp(); this.Assets = null; } Game.currentGame.Value = null; this.drawThread = null; }