Advertisement
kkc0923

SwapChainTargetBase

Nov 25th, 2012
209
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 12.85 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. using SharpDX;
  7. using SharpDX.DXGI;
  8.  
  9. namespace NovelReader.DirectX
  10. {
  11.     /// <summary>
  12.     /// Base class to render to a SwapChain.
  13.     /// </summary>
  14.     /// <remarks>
  15.     /// This class is the base class for <see cref="CoreWindowTarget"/>
  16.     /// and <see cref="SwapChainBackgroundPanelTarget"/>.
  17.     /// </remarks>
  18.     public abstract class SwapChainTargetBase : TargetBase
  19.     {
  20.         SharpDX.DXGI.SwapChain1 swapChain;
  21.  
  22.         /// <summary>
  23.         /// Initializes this instance.
  24.         /// </summary>
  25.         protected SwapChainTargetBase()
  26.         {
  27.             OnSizeChanged += CreateSizeDependentResources;
  28.         }
  29.  
  30.         /// <summary>
  31.         /// Width of the swap chain to create or resize.
  32.         /// </summary>
  33.         protected virtual int Width
  34.         {
  35.             get
  36.             {
  37.                 return (int)(ControlBounds.Width * DeviceManager.Dpi / 96.0);
  38.             }
  39.         }
  40.  
  41.         /// <summary>
  42.         /// Height of the swap chain to create or resize.
  43.         /// </summary>
  44.         protected virtual int Height
  45.         {
  46.             get
  47.             {
  48.                 return (int)(ControlBounds.Height * DeviceManager.Dpi / 96.0);
  49.             }
  50.         }
  51.  
  52.         public SwapChain1 SwapChain
  53.         {
  54.             get { return swapChain; }
  55.         }
  56.  
  57.         /// <summary>
  58.         /// Present the results to the swap chain.
  59.         /// </summary>
  60.         public virtual void Present()
  61.         {
  62.             // The application may optionally specify "dirty" or "scroll" rects to improve efficiency
  63.             // in certain scenarios.  In this sample, however, we do not utilize those features.
  64.             var parameters = new SharpDX.DXGI.PresentParameters();
  65.  
  66.             try
  67.             {
  68.                 // The first argument instructs DXGI to block until VSync, putting the application
  69.                 // to sleep until the next VSync. This ensures we don't waste any cycles rendering
  70.                 // frames that will never be displayed to the screen.
  71.                 swapChain.Present(1, SharpDX.DXGI.PresentFlags.None, parameters);
  72.             }
  73.             catch (SharpDX.SharpDXException ex)
  74.             {
  75.                 // TODO PLUG CODE HERE TO REINITIALIZE
  76.  
  77.                 // If the device was removed either by a disconnect or a driver upgrade, we
  78.                 // must completely reinitialize the renderer.
  79.                 if (ex.ResultCode == SharpDX.DXGI.ResultCode.DeviceRemoved
  80.                     || ex.ResultCode == SharpDX.DXGI.ResultCode.DeviceReset)
  81.                     DeviceManager.Initialize(DeviceManager.Dpi);
  82.                 else
  83.                     throw;
  84.             }
  85.         }
  86.  
  87.         protected virtual void CreateSizeDependentResources(TargetBase renderBase)
  88.         {
  89.             var d3dDevice = DeviceManager.DeviceDirect3D;
  90.             var d3dContext = DeviceManager.ContextDirect3D;
  91.             var d2dContext = DeviceManager.ContextDirect2D;
  92.  
  93.             d2dContext.Target = null;
  94.             RemoveAndDispose(ref renderTargetView);
  95.             RemoveAndDispose(ref depthStencilView);
  96.             RemoveAndDispose(ref bitmapTarget);
  97.             RemoveAndDispose(ref backBuffer);
  98.  
  99.             // If the swap chain already exists, resize it.
  100.             if (swapChain != null)
  101.             {
  102.                 swapChain.ResizeBuffers(2, Width, Height, SharpDX.DXGI.Format.B8G8R8A8_UNorm, SharpDX.DXGI.SwapChainFlags.None);
  103.             }
  104.             // Otherwise, create a new one.
  105.             else
  106.             {
  107.                 // SwapChain description
  108.                 var desc = CreateSwapChainDescription();
  109.  
  110.                 // Once the desired swap chain description is configured, it must be created on the same adapter as our D3D Device
  111.  
  112.                 // First, retrieve the underlying DXGI Device from the D3D Device.
  113.                 // Creates the swap chain
  114.                 using (var dxgiDevice2 = d3dDevice.QueryInterface<SharpDX.DXGI.Device2>())
  115.                 using (var dxgiAdapter = dxgiDevice2.Adapter)
  116.                 using (var dxgiFactory2 = dxgiAdapter.GetParent<SharpDX.DXGI.Factory2>())
  117.                 {
  118.                     swapChain = ToDispose(CreateSwapChain(dxgiFactory2, d3dDevice, desc));
  119.  
  120.                     // Ensure that DXGI does not queue more than one frame at a time. This both reduces
  121.                     // latency and ensures that the application will only render after each VSync, minimizing
  122.                     // power consumption.
  123.                     dxgiDevice2.MaximumFrameLatency = 1;
  124.                 }
  125.             }
  126.  
  127.             // Obtain the backbuffer for this window which will be the final 3D rendertarget.
  128.             backBuffer = ToDispose(SharpDX.Direct3D11.Texture2D.FromSwapChain<SharpDX.Direct3D11.Texture2D>(swapChain, 0));
  129.             {
  130.                 // Create a view interface on the rendertarget to use on bind.
  131.                 renderTargetView = ToDispose(new SharpDX.Direct3D11.RenderTargetView(d3dDevice, BackBuffer));
  132.  
  133.                 // Cache the rendertarget dimensions in our helper class for convenient use.
  134.                 var backBufferDesc = BackBuffer.Description;
  135.                 RenderTargetBounds = new Windows.Foundation.Rect(0, 0, backBufferDesc.Width, backBufferDesc.Height);
  136.             }
  137.  
  138.             // Create a descriptor for the depth/stencil buffer.
  139.             // Allocate a 2-D surface as the depth/stencil buffer.
  140.             // Create a DepthStencil view on this surface to use on bind.
  141.             using (var depthBuffer = new SharpDX.Direct3D11.Texture2D(d3dDevice, new SharpDX.Direct3D11.Texture2DDescription()
  142.             {
  143.                 Format = SharpDX.DXGI.Format.D24_UNorm_S8_UInt,
  144.                 ArraySize = 1,
  145.                 MipLevels = 1,
  146.                 Width = (int)RenderTargetSize.Width,
  147.                 Height = (int)RenderTargetSize.Height,
  148.                 SampleDescription = new SharpDX.DXGI.SampleDescription(1, 0),
  149.                 BindFlags = SharpDX.Direct3D11.BindFlags.DepthStencil,
  150.             }))
  151.                 depthStencilView = ToDispose(new SharpDX.Direct3D11.DepthStencilView(d3dDevice, depthBuffer, new SharpDX.Direct3D11.DepthStencilViewDescription() { Dimension = SharpDX.Direct3D11.DepthStencilViewDimension.Texture2D }));
  152.  
  153.             // Create a viewport descriptor of the full window size.
  154.             var viewport = new SharpDX.Direct3D11.Viewport((float)RenderTargetBounds.X, (float)RenderTargetBounds.Y, (float)RenderTargetBounds.Width, (float)RenderTargetBounds.Height, 0.0f, 1.0f);
  155.  
  156.             // Set the current viewport using the descriptor.
  157.             d3dContext.Rasterizer.SetViewports(viewport);
  158.  
  159.             // Now we set up the Direct2D render target bitmap linked to the swapchain.
  160.             // Whenever we render to this bitmap, it will be directly rendered to the
  161.             // swapchain associated with the window.
  162.             var bitmapProperties = new SharpDX.Direct2D1.BitmapProperties1(
  163.                 new SharpDX.Direct2D1.PixelFormat(SharpDX.DXGI.Format.B8G8R8A8_UNorm, SharpDX.Direct2D1.AlphaMode.Premultiplied),
  164.                 DeviceManager.Dpi,
  165.                 DeviceManager.Dpi,
  166.                 SharpDX.Direct2D1.BitmapOptions.Target | SharpDX.Direct2D1.BitmapOptions.CannotDraw);
  167.  
  168.             // Direct2D needs the dxgi version of the backbuffer surface pointer.
  169.             // Get a D2D surface from the DXGI back buffer to use as the D2D render target.
  170.             using (var dxgiBackBuffer = swapChain.GetBackBuffer<SharpDX.DXGI.Surface>(0))
  171.                 bitmapTarget = ToDispose(new SharpDX.Direct2D1.Bitmap1(d2dContext, dxgiBackBuffer, bitmapProperties));
  172.  
  173.             // So now we can set the Direct2D render target.
  174.             d2dContext.Target = BitmapTarget2D;
  175.  
  176.             // Set D2D text anti-alias mode to Grayscale to ensure proper rendering of text on intermediate surfaces.
  177.             d2dContext.TextAntialiasMode = SharpDX.Direct2D1.TextAntialiasMode.Grayscale;
  178.         }
  179.  
  180.         /// <summary>
  181.         /// Creates the swap chain description.
  182.         /// </summary>
  183.         /// <returns>A swap chain description</returns>
  184.         /// <remarks>
  185.         /// This method can be overloaded in order to modify default parameters.
  186.         /// </remarks>
  187.         protected virtual SharpDX.DXGI.SwapChainDescription1 CreateSwapChainDescription()
  188.         {
  189.             // SwapChain description
  190.             var desc = new SharpDX.DXGI.SwapChainDescription1()
  191.             {
  192.                 // Automatic sizing
  193.                 Width = Width,
  194.                 Height = Height,
  195.                 Format = SharpDX.DXGI.Format.B8G8R8A8_UNorm,
  196.                 Stereo = false,
  197.                 SampleDescription = new SharpDX.DXGI.SampleDescription(1, 0),
  198.                 Usage = SharpDX.DXGI.Usage.BackBuffer | SharpDX.DXGI.Usage.RenderTargetOutput,
  199.                 // Use two buffers to enable flip effect.
  200.                 BufferCount = 2,
  201.                 Scaling = SharpDX.DXGI.Scaling.None,
  202.                 SwapEffect = SharpDX.DXGI.SwapEffect.FlipSequential,
  203.             };
  204.             return desc;
  205.         }
  206.  
  207.         /// <summary>
  208.         /// Creates the swap chain.
  209.         /// </summary>
  210.         /// <param name="factory">The DXGI factory</param>
  211.         /// <param name="device">The D3D11 device</param>
  212.         /// <param name="desc">The swap chain description</param>
  213.         /// <returns>An instance of swap chain</returns>
  214.         protected abstract SharpDX.DXGI.SwapChain1 CreateSwapChain(SharpDX.DXGI.Factory2 factory, SharpDX.Direct3D11.Device1 device, SharpDX.DXGI.SwapChainDescription1 desc);
  215.     }
  216. }
  217.  
  218. namespace CommonDX
  219. {
  220.     /// <summary>
  221.     /// Target to render to a <see cref="SwapChainBackgroundPanel"/>.
  222.     /// </summary>
  223.     /// <remarks>
  224.     /// This class should be use when efficient DirectX-XAML interop is required.
  225.     /// </remarks>
  226.     public class SwapChainBackgroundPanelTarget : SwapChainTargetBase
  227.     {
  228.         private SwapChainBackgroundPanel panel;
  229.         private ISwapChainBackgroundPanelNative nativePanel;
  230.  
  231.         /// <summary>
  232.         /// Initializes a new <see cref="SwapChainBackgroundPanelTarget"/> instance
  233.         /// </summary>
  234.         /// <param name="panel">The <see cref="SwapChainBackgroundPanel"/> to render to</param>
  235.         public SwapChainBackgroundPanelTarget(SwapChainBackgroundPanel panel)
  236.         {
  237.             this.panel = panel;
  238.  
  239.             // Gets the native panel
  240.             nativePanel = ComObject.As<ISwapChainBackgroundPanelNative>(panel);
  241.  
  242.             // Register event on Window Size Changed
  243.             // So that resources dependent size can be resized
  244.             Window.Current.CoreWindow.SizeChanged += CoreWindow_SizeChanged;
  245.         }
  246.  
  247.         void CoreWindow_SizeChanged(CoreWindow sender, WindowSizeChangedEventArgs args)
  248.         {
  249.             UpdateForSizeChange();
  250.         }
  251.  
  252.         protected override Windows.Foundation.Rect CurrentControlBounds
  253.         {
  254.             get { return new Windows.Foundation.Rect(0, 0, panel.RenderSize.Width, panel.RenderSize.Height); }
  255.         }
  256.  
  257.         protected override int Width
  258.         {
  259.             get
  260.             {
  261.                 // Unlike CoreWindow, Width/Height of the SwapChain must be specified
  262.                 var currentWindow = Window.Current.CoreWindow;
  263.                 return (int)(currentWindow.Bounds.Width * DeviceManager.Dpi / 96.0);
  264.             }
  265.         }
  266.  
  267.         protected override int Height
  268.         {
  269.             get
  270.             {
  271.                 // Unlike CoreWindow, Width/Height of the SwapChain must be specified
  272.                 var currentWindow = Window.Current.CoreWindow;
  273.                 return (int)(currentWindow.Bounds.Height * DeviceManager.Dpi / 96.0); // Returns 0 to fill the CoreWindow
  274.             }
  275.         }
  276.  
  277.         protected override SwapChainDescription1 CreateSwapChainDescription()
  278.         {
  279.             // Get the default descirption.
  280.             var desc = base.CreateSwapChainDescription();
  281.  
  282.             // Apart for the width and height, the other difference
  283.             // in the SwapChainDescription is that Scaling must be
  284.             // set to Stretch for XAML Composition
  285.             desc.Scaling = Scaling.Stretch;
  286.             return desc;
  287.         }
  288.  
  289.         protected override SharpDX.DXGI.SwapChain1 CreateSwapChain(SharpDX.DXGI.Factory2 factory, SharpDX.Direct3D11.Device1 device, SharpDX.DXGI.SwapChainDescription1 desc)
  290.         {
  291.             // Creates the swap chain for XAML composition
  292.             var swapChain = factory.CreateSwapChainForComposition(device, ref desc, null);
  293.  
  294.             // Associate the SwapChainBackgroundPanel with the swap chain
  295.             nativePanel.SwapChain = swapChain;
  296.  
  297.             // Returns the new swap chain
  298.             return swapChain;
  299.         }
  300.     }
  301. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement