View difference between Paste ID: q7w14DQD and 7hDYDmTG
SHOW: | | - or go back to the newest paste.
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
218+
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
}