private void OnGraphicsDeviceResetting(object sender, EventArgs eventArgs) { RenderTargetPool.Clear(); // Reset the texture stages. If a floating point texture is set, we get exceptions // when a sampler with bilinear filtering is set. GraphicsDevice.ResetTextures(); }
//private void OnGraphicsDeviceReset(object sender, EventArgs eventArgs) //{ //} private void OnGraphicsDeviceDisposing(object sender, EventArgs eventArgs) { // Clean up resources. RenderTargetPool.Clear(); // Dispose custom data. - Don't do this. Because the device will be // reset and automatically recreated when the game window moves between // screens for example... //foreach(var entry in Data) // if (entry.Value is IDisposable) // ((IDisposable)entry.Value).Dispose(); }
public GraphicsManager(GraphicsDevice graphicsDevice, GameWindow gameWindow, ContentManager content) { if (graphicsDevice == null) { throw new ArgumentNullException("graphicsDevice"); } if (content == null) { throw new ArgumentNullException("content"); } GraphicsDevice = graphicsDevice; graphicsDevice.DeviceResetting += OnGraphicsDeviceResetting; //graphicsDevice.DeviceReset += OnGraphicsDeviceReset; GraphicsDevice.Disposing += OnGraphicsDeviceDisposing; Content = content; RenderTargetPool = new RenderTargetPool(this); Screens = new GraphicsScreenCollection(); if (gameWindow != null) { GameForm = PlatformHelper.GetForm(gameWindow.Handle); } PresentationTargets = new PresentationTargetCollection(); PresentationTargets.CollectionChanged += OnPresentationTargetsChanged; EffectInterpreters = new EffectInterpreterCollection { new StockEffectInterpreter(), new DefaultEffectInterpreter(), new SceneEffectInterpreter(), #if !WINDOWS_PHONE && !XBOX360 new TerrainEffectInterpreter(), #endif new Dxsas08EffectInterpreter(), }; EffectBinders = new EffectBinderCollection { new StockEffectBinder(), new DefaultEffectBinder(this), new SceneEffectBinder(), #if !WINDOWS_PHONE && !XBOX360 new TerrainEffectBinder(), #endif }; Data = new Dictionary <string, object>(); Frame = -1; ShapeMeshCache = new ShapeMeshCache(this); }
/// <summary> /// Releases the unmanaged resources used by an instance of the <see cref="GraphicsManager"/> class /// and optionally releases the managed resources. /// </summary> /// <param name="disposing"> /// <see langword="true"/> to release both managed and unmanaged resources; /// <see langword="false"/> to release only unmanaged resources. /// </param> protected virtual void Dispose(bool disposing) { if (!IsDisposed) { if (disposing) { RenderTargetPool.Dispose(); ShapeMeshCache.Dispose(); } IsDisposed = true; } }
/// <summary> /// Updates the graphics service and the registered graphics screens. /// </summary> /// <param name="deltaTime">The elapsed time since the last update.</param> /// <remarks> /// <para> /// This methods /// </para> /// <list type="bullet"> /// <item>updates <see cref="DeltaTime"/>,</item> /// <item>increments <see cref="Frame"/>,</item> /// <item> /// updates the graphics screens, i.e. calls <see cref="GraphicsScreen.Update"/> of all graphics /// screens registered in the <see cref="Screens"/> collection /// </item> /// <item>and performs other internal tasks.</item> /// </list> /// <para> /// This method needs to be called once per frame before calling <see cref="Render(bool)"/>. /// </para> /// </remarks> public void Update(TimeSpan deltaTime) { ThrowIfDisposed(); if (_context == null) { _context = CreateRenderContext(); } DeltaTime = deltaTime; Time += deltaTime; _context.DeltaTime = deltaTime; _context.Time = Time; Frame = (Frame < int.MaxValue) ? Frame + 1 : 0; _context.Frame = Frame; try { // Create temporary list because original collection may be modified during update. CopyScreens(Screens, _tempScreens); // Update graphics screens. int numberOfScreens = _tempScreens.Count; for (int i = numberOfScreens - 1; i >= 0; i--) { var screen = _tempScreens[i]; screen.Update(deltaTime); if (screen.IsVisible && screen.Coverage == GraphicsScreenCoverage.Full && !screen.RenderPreviousScreensToTexture) { // The current screen occludes all screens in the background. break; } } RenderTargetPool.Update(); ShapeMeshCache.Update(); } finally { // If GraphicsScreen.Update() throws, let's at least clear _tempScreens, so we can try again // in the next frame. _tempScreens.Clear(); } }
/// <summary> /// Renders all visible <see cref="GraphicsScreen" />s. /// </summary> /// <param name="screens">The graphics screens.</param> private void RenderScreens(IList <GraphicsScreen> screens) { if (GraphicsDevice == null || GraphicsDevice.IsDisposed) { return; } // Create temporary list because original collection may be modified during update. try { CopyScreens(screens, _tempScreens); // ----- Render screens from back to front. var finalViewport = _context.Viewport; var finalRenderTarget = _context.RenderTarget; GraphicsScreen screenThatRequiresSourceTexture = null; // The next screen that needs the previous screens as source. int numberOfScreens = _tempScreens.Count; for (int i = GetIndexOfFirstVisibleScreen(_tempScreens); i < numberOfScreens; i++) { var screen = _tempScreens[i]; if (screen == screenThatRequiresSourceTexture) { Debug.Assert(_context.RenderTarget != null, "Previous graphics screens should have been rendered into an off-screen render target."); Debug.Assert(_context.SourceTexture == null, "The RenderContext.SourceTexture should have been recycled."); _context.SourceTexture = _context.RenderTarget; _context.RenderTarget = finalRenderTarget; screenThatRequiresSourceTexture = null; } if (screenThatRequiresSourceTexture == null) { // Check if one of the next screens needs the current output in an off-screen render target. for (int j = i + 1; j < numberOfScreens; j++) { var topScreen = _tempScreens[j]; if (topScreen.IsVisible && topScreen.RenderPreviousScreensToTexture) { screenThatRequiresSourceTexture = topScreen; var format = topScreen.SourceTextureFormat; // If not specified, choose default values for width and height. if (!format.Width.HasValue) { format.Width = finalViewport.Width; } if (!format.Height.HasValue) { format.Height = finalViewport.Height; } _context.RenderTarget = RenderTargetPool.Obtain2D(format); break; } } } GraphicsDevice.SetRenderTarget(_context.RenderTarget); // For the back buffer we use the special viewport. Off-screen render targets // always use the full size. if (_context.RenderTarget == finalRenderTarget) { GraphicsDevice.Viewport = finalViewport; } // Make sure the viewport in the render context is up-to-date. // (Note: SetRenderTarget() always resets GraphicsDevice.Viewport.) _context.Viewport = GraphicsDevice.Viewport; screen.Render(_context); if (_context.SourceTexture != null) { RenderTargetPool.Recycle(_context.SourceTexture as RenderTarget2D); _context.SourceTexture = null; } } Debug.Assert(_context.SourceTexture == null, "The RenderContext.SourceTexture should have been recycled."); Debug.Assert(_context.RenderTarget == finalRenderTarget, "The last graphics screen must render into the back buffer."); } finally { // If GraphicsScreen.Render() throws, let's at least clear _tempScreens, so we can try again // in the next frame. _tempScreens.Clear(); } }