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 | } |