Commit 3bdb84c6 authored by Jérémy VIGNELLES's avatar Jérémy VIGNELLES Committed by Martin Finkel

Code cleanup + improved errors management

parent 705af2a1
using Windows.UI.Xaml;
namespace LibVLCSharp.Platforms.UWP
namespace LibVLCSharp.Platforms.UWP
{
using LibVLCSharp.Shared;
using SharpDX;
......@@ -9,8 +7,8 @@ namespace LibVLCSharp.Platforms.UWP
using SharpDX.Mathematics.Interop;
using System;
using System.Runtime.InteropServices;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Device3 = SharpDX.DXGI.Device3;
/// <summary>
/// The VideoView implementation for UWP applications
......@@ -18,10 +16,10 @@ namespace LibVLCSharp.Platforms.UWP
public class VideoView : UserControl, IVideoView
{
SwapChainPanel _panel;
SharpDX.Direct3D11.Device _d3d11Device;
SharpDX.Direct3D11.Device _d3D11Device;
SharpDX.DXGI.Device1 _device;
Device3 _device3;
SwapChain2 _swapchain2;
SharpDX.DXGI.Device3 _device3;
SwapChain2 _swapChain2;
SwapChain1 _swapChain;
bool _loaded;
......@@ -33,8 +31,8 @@ namespace LibVLCSharp.Platforms.UWP
{
_panel = new SwapChainPanel();
Content = _panel;
Loaded += (s, e) => OnLoad();
Unloaded += (s, e) => OnUnload();
Loaded += (s, e) => CreateSwapChain();
Unloaded += (s, e) => DestroySwapChain();
Application.Current.Suspending += (s, e) => { Trim(); };
......@@ -71,141 +69,193 @@ namespace LibVLCSharp.Platforms.UWP
return new string[]
{
$"--winrt-d3dcontext=0x{_d3d11Device.ImmediateContext.NativePointer.ToString("x")}",
$"--winrt-d3dcontext=0x{_d3D11Device.ImmediateContext.NativePointer.ToString("x")}",
$"--winrt-swapchain=0x{_swapChain.NativePointer.ToString("x")}"
};
}
void OnLoad()
/// <summary>
/// Initializes the SwapChain for use with LibVLC
/// </summary>
void CreateSwapChain()
{
SharpDX.DXGI.Factory2 dxgiFactory;
DeviceCreationFlags deviceCreationFlags = DeviceCreationFlags.BgraSupport | DeviceCreationFlags.VideoSupport;
#if DEBUG
deviceCreationFlags |= DeviceCreationFlags.Debug;
SharpDX.DXGI.Factory2 dxgiFactory = null;
try
{
dxgiFactory = new SharpDX.DXGI.Factory2(true);
}
catch (SharpDXException)
{
dxgiFactory = new SharpDX.DXGI.Factory2(false);
}
#else
dxgiFactory = new SharpDX.DXGI.Factory2(false);
#endif
_d3d11Device = null;
foreach (var adapter in dxgiFactory.Adapters)
{
DeviceCreationFlags deviceCreationFlags =
DeviceCreationFlags.BgraSupport | DeviceCreationFlags.VideoSupport;
#if DEBUG
deviceCreationFlags |= DeviceCreationFlags.Debug;
try
{
_d3d11Device = new SharpDX.Direct3D11.Device(adapter, deviceCreationFlags);
break;
dxgiFactory = new SharpDX.DXGI.Factory2(true);
}
catch (SharpDXException)
{
dxgiFactory = new SharpDX.DXGI.Factory2(false);
}
#else
dxgiFactory = new SharpDX.DXGI.Factory2(false);
#endif
_d3D11Device = null;
foreach (var adapter in dxgiFactory.Adapters)
{
try
{
_d3D11Device = new SharpDX.Direct3D11.Device(adapter, deviceCreationFlags);
break;
}
catch (SharpDXException)
{
}
}
}
if (_d3d11Device is null)
{
throw new Exception("Could not D3D11CreateDevice");
}
if (_d3D11Device is null)
{
throw new VLCException("Could not create Direct3D11 device : No compatible adapter found.");
}
_device = _d3d11Device.QueryInterface<SharpDX.DXGI.Device1>();
_device = _d3D11Device.QueryInterface<SharpDX.DXGI.Device1>();
//Create the swapchain
var swapChainDescription = new SharpDX.DXGI.SwapChainDescription1
{
Width = (int)(this._panel.ActualWidth * this._panel.CompositionScaleX),
Height = (int)(this._panel.ActualHeight * this._panel.CompositionScaleY),
Format = SharpDX.DXGI.Format.B8G8R8A8_UNorm,
Stereo = false,
SampleDescription =
//Create the swapchain
var swapChainDescription = new SharpDX.DXGI.SwapChainDescription1
{
Count = 1,
Quality = 0
},
Usage = Usage.RenderTargetOutput,
BufferCount = 2,
SwapEffect = SwapEffect.FlipSequential,
Flags = SwapChainFlags.None,
AlphaMode = AlphaMode.Unspecified
};
_swapChain = new SharpDX.DXGI.SwapChain1(dxgiFactory, _d3d11Device, ref swapChainDescription);
Width = (int) (_panel.ActualWidth * _panel.CompositionScaleX),
Height = (int) (_panel.ActualHeight * _panel.CompositionScaleY),
Format = SharpDX.DXGI.Format.B8G8R8A8_UNorm,
Stereo = false,
SampleDescription =
{
Count = 1,
Quality = 0
},
Usage = Usage.RenderTargetOutput,
BufferCount = 2,
SwapEffect = SwapEffect.FlipSequential,
Flags = SwapChainFlags.None,
AlphaMode = AlphaMode.Unspecified
};
_swapChain = new SharpDX.DXGI.SwapChain1(dxgiFactory, _d3D11Device, ref swapChainDescription);
_device.MaximumFrameLatency = 1;
//TODO: perform the next 2 calls on the UI thread
using (var panelNative = ComObject.As<ISwapChainPanelNative>(_panel))
{
panelNative.SwapChain = _swapChain;
}
_device.MaximumFrameLatency = 1;
// This is necessary so we can call Trim() on suspend
_device3 = _device.QueryInterface<SharpDX.DXGI.Device3>();
if (_device3 == null)
{
throw new VLCException("Failed to query interface \"Device3\"");
}
//TODO: perform the next 2 calls on the UI thread
var panelNative = ComObject.As<ISwapChainPanelNative>(this._panel);
panelNative.SwapChain = _swapChain;
_swapChain2 = _swapChain.QueryInterface<SharpDX.DXGI.SwapChain2>();
if (_swapChain2 == null)
{
throw new VLCException("Failed to query interface \"SwapChain2\"");
}
// This is necessary so we can call Trim() on suspend
this._device3 = _device.QueryInterface<SharpDX.DXGI.Device3>();
if (_device3 == null)
throw new Exception();
this._swapchain2 = _swapChain.QueryInterface<SharpDX.DXGI.SwapChain2>();
if (_swapchain2 == null)
throw new Exception();
UpdateScale();
UpdateSize();
_loaded = true;
}
catch (Exception ex)
{
DestroySwapChain();
if (ex is SharpDXException)
{
throw new VLCException("SharpDX operation failed, see InnerException for details", ex);
}
UpdateScale();
UpdateSize();
this._loaded = true;
throw;
}
finally
{
dxgiFactory?.Dispose();
}
}
void OnUnload()
/// <summary>
/// Destroys the SwapChain and all related instances.
/// </summary>
void DestroySwapChain()
{
this._swapchain2?.Dispose();
this._swapchain2 = null;
_swapChain2?.Dispose();
_swapChain2 = null;
this._device3?.Dispose();
this._device3 = null;
_device3?.Dispose();
_device3 = null;
this._swapChain?.Dispose();
this._swapChain = null;
_swapChain?.Dispose();
_swapChain = null;
this._device?.Dispose();
this._device = null;
_device?.Dispose();
_device = null;
this._d3d11Device?.Dispose();
this._d3d11Device = null;
_d3D11Device?.Dispose();
_d3D11Device = null;
}
readonly Guid SWAPCHAIN_WIDTH = new Guid(0xf1b59347, 0x1643, 0x411a, 0xad, 0x6b, 0xc7, 0x80, 0x17, 0x7a, 0x6, 0xb6);
readonly Guid SWAPCHAIN_HEIGHT = new Guid(0x6ea976a0, 0x9d60, 0x4bb7, 0xa5, 0xa9, 0x7d, 0xd1, 0x18, 0x7f, 0xc9, 0xbd);
/// <summary>
/// Associates width/height private data into the SwapChain, so that VLC knows at which size to render its video.
/// </summary>
void UpdateSize()
{
IntPtr width = Marshal.AllocHGlobal(sizeof(int));
IntPtr height = Marshal.AllocHGlobal(sizeof(int));
var w = (int)(this._panel.ActualWidth * this._panel.CompositionScaleX);
var h = (int)(this._panel.ActualHeight * this._panel.CompositionScaleY);
Marshal.WriteInt32(width, w);
Marshal.WriteInt32(height, h);
try
{
var w = (int)(_panel.ActualWidth * _panel.CompositionScaleX);
var h = (int)(_panel.ActualHeight * _panel.CompositionScaleY);
_swapChain.SetPrivateData(SWAPCHAIN_WIDTH, sizeof(int), width);
_swapChain.SetPrivateData(SWAPCHAIN_HEIGHT, sizeof(int), height);
Marshal.WriteInt32(width, w);
Marshal.WriteInt32(height, h);
Marshal.FreeHGlobal(width);
Marshal.FreeHGlobal(height);
_swapChain.SetPrivateData(SWAPCHAIN_WIDTH, sizeof(int), width);
_swapChain.SetPrivateData(SWAPCHAIN_HEIGHT, sizeof(int), height);
}
finally
{
Marshal.FreeHGlobal(width);
Marshal.FreeHGlobal(height);
}
}
/// <summary>
/// Updates the MatrixTransform of the SwapChain.
/// </summary>
void UpdateScale()
{
_swapchain2.MatrixTransform = new RawMatrix3x2 { M11 = 1.0f / this._panel.CompositionScaleX, M22 = 1.0f / this._panel.CompositionScaleY };
_swapChain2.MatrixTransform = new RawMatrix3x2 { M11 = 1.0f / _panel.CompositionScaleX, M22 = 1.0f / _panel.CompositionScaleY };
}
/// <summary>
/// When the app is suspended, UWP apps should call Trim so that the DirectX data is cleaned.
/// </summary>
void Trim()
{
_device3?.Trim();
}
/// <summary>
/// When the media player is attached to the view.
/// </summary>
void Attach()
{
}
/// <summary>
/// When the media player is detached from the view.
/// </summary>
void Detach()
{
}
......@@ -213,7 +263,7 @@ namespace LibVLCSharp.Platforms.UWP
MediaPlayer _mediaPlayer;
/// <summary>
/// The MediaPlayer object attached to this VideoView. Use this to manage playback and more
/// MediaPlayer object connected to the view
/// </summary>
public MediaPlayer MediaPlayer
{
......
......@@ -7,5 +7,12 @@ namespace LibVLCSharp.Shared
public VLCException(string message = ""):base(message)
{
}
/// <summary>
/// Creates a <see cref="VLCException" /> with a message and an inner exeption
/// </summary>
public VLCException(string message, Exception innerException) : base(message, innerException)
{
}
}
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment