/// <summary> /// Renders one frame. /// </summary> /// <remarks> /// Updates all the render targets automatically and then returns, raising frame events before and after. /// </remarks> /// <returns>True if execution should continue, false if a quit was requested.</returns> public void RenderOneFrame() { // If we're capping the maximum frame rate, check to see // if we should sleep if (microsecondsPerFrame != 0) { long current = CaptureCurrentTime(); long diff = Math.Abs(current - lastFrameStartTime); float microsecondsSinceLastFrame = diff * microsecondsPerTick; float mdiff = microsecondsPerFrame - microsecondsSinceLastFrame; // If the difference is greater than 500usec and less // than 1000 ms, sleep if (mdiff > 500f && mdiff < 1000000f) { Thread.Sleep((int)(Math.Min(mdiff / 1000f, 200f))); lastFrameStartTime = CaptureCurrentTime(); } else { lastFrameStartTime = current; } } if (queuedEnd) { // bail out before continuing return; } // Stop rendering if frame callback says so oneFrameMeter.Enter(); oneFrameStartedMeter.Enter(); OnFrameStarted(); oneFrameStartedMeter.Exit(); if (!queuedEnd && !dontUpdateRenderTargets) { // update all current render targets updateRenderTargetsMeter.Enter(); UpdateAllRenderTargets(); updateRenderTargetsMeter.Exit(); } // Stop rendering if frame callback says so oneFrameEndedMeter.Enter(); OnFrameEnded(); oneFrameEndedMeter.Exit(); oneFrameMeter.Exit(); }
/// <summary> /// Starts the default rendering loop. /// </summary> public void StartRendering() { bool cachedMeterLongestFrame = false; int frameStartTime = 0; Debug.Assert(activeRenderSystem != null, "Engine cannot start rendering without an active RenderSystem."); activeRenderSystem.InitRenderTargets(); // initialize the vars lastStartTime = lastEndTime = timer.Milliseconds; // reset to false so that rendering can begin queuedEnd = false; while (!queuedEnd) { // Make sure we're collecting if it's called for if (meterFrameCount > 0) { MeterManager.Collecting = true; } else if (meterLongestFrame) { cachedMeterLongestFrame = true; MeterManager.Collecting = true; frameStartTime = System.Environment.TickCount; } // allow OS events to process (if the platform requires it frameMeter.Enter(); eventMeter.Enter(); PlatformManager.Instance.DoEvents(); eventMeter.Exit(); if (suspendRendering) { Thread.Sleep(100); frameMeter.Exit(); continue; } renderMeter.Enter(); RenderOneFrame(); renderMeter.Exit(); if (activeRenderSystem.RenderTargetCount == 0) { QueueEndRendering(); } frameMeter.Exit(); // Turn metering on or off, and generate the report if // we're done if (meterFrameCount > 0) { meterFrameCount--; if (meterFrameCount == 0) { MeterManager.Collecting = false; MeterManager.Report("Frame Processing"); } } else if (pendingMeterFrameCount > 0) { // We'll start metering next frame meterFrameCount = pendingMeterFrameCount; pendingMeterFrameCount = 0; } else if (cachedMeterLongestFrame) { MeterManager.Collecting = false; int frameTime = System.Environment.TickCount - frameStartTime; if (frameTime > longestFrameTime) { longestFrameTime = frameTime; longestFrameMeterEvents = MeterManager.ReturnEvents(); } else { MeterManager.ClearEvents(); } } } }