public void Init() { if (!(m_Context is null)) { throw new InvalidOperationException("renderer already initialized"); } m_Context = Context.Instance; CreateBlendStates(); CreateDepthStencilStates(); SetBlend(false); SetDepthTesting(true); SharpDX.DXGI.Device dxgiDev = m_Context.Dev.QueryInterface <SharpDX.DXGI.Device>(); SharpDX.DXGI.AdapterDescription adapterDesc = dxgiDev.Adapter.Description; Console.WriteLine("----------------------------------"); Console.WriteLine(" Direct3D 11:"); Console.WriteLine(" " + adapterDesc.Description); Console.WriteLine(" VRAM: " + adapterDesc.DedicatedVideoMemory / 1024 / 1024 + " MB"); Console.WriteLine("----------------------------------"); dxgiDev.Dispose(); }
internal static void InitializeDirect2D() { lock (s_initLock) { if (s_initialized) { return; } #if DEBUG try { s_d2D1Factory = new SharpDX.Direct2D1.Factory1(SharpDX.Direct2D1.FactoryType.MultiThreaded, SharpDX.Direct2D1.DebugLevel.Error); } catch { // } #endif s_dwfactory = new SharpDX.DirectWrite.Factory(); s_imagingFactory = new SharpDX.WIC.ImagingFactory(); if (s_d2D1Factory == null) { s_d2D1Factory = new SharpDX.Direct2D1.Factory1(SharpDX.Direct2D1.FactoryType.MultiThreaded, SharpDX.Direct2D1.DebugLevel.None); } var featureLevels = new[] { SharpDX.Direct3D.FeatureLevel.Level_11_1, SharpDX.Direct3D.FeatureLevel.Level_11_0, SharpDX.Direct3D.FeatureLevel.Level_10_1, SharpDX.Direct3D.FeatureLevel.Level_10_0, SharpDX.Direct3D.FeatureLevel.Level_9_3, SharpDX.Direct3D.FeatureLevel.Level_9_2, SharpDX.Direct3D.FeatureLevel.Level_9_1, }; using (var d3dDevice = new SharpDX.Direct3D11.Device( SharpDX.Direct3D.DriverType.Hardware, SharpDX.Direct3D11.DeviceCreationFlags.BgraSupport | SharpDX.Direct3D11.DeviceCreationFlags.VideoSupport, featureLevels)) { s_dxgiDevice = d3dDevice.QueryInterface <SharpDX.DXGI.Device>(); } using (var factory1 = s_d2D1Factory.QueryInterface <SharpDX.Direct2D1.Factory1>()) { s_d2D1Device = new SharpDX.Direct2D1.Device(factory1, s_dxgiDevice); } s_initialized = true; } }
/// <summary> /// <p>Creates a new device object that can be used to create other Microsoft DirectComposition objects.</p> /// </summary> /// <param name = "dxgiDevice"><dd> <p>The DXGI device to use to create DirectComposition surface objects.</p> </dd></param> /// <param name = "iid"><dd> <p>The identifier of the interface to retrieve. </p> </dd></param> /// <param name = "dcompositionDevice"><dd> <p>Receives an interface reference to the newly created device object. The reference is of the type specified by the <em>iid</em> parameter. This parameter must not be <c>null</c>.</p> </dd></param> /// <returns><p>If the function succeeds, it returns <see cref = "SharpDX.Result.Ok"/>. Otherwise, it returns an <strong><see cref = "SharpDX.Result"/></strong> error code. See DirectComposition Error Codes for a list of error codes.</p></returns> /// <remarks> /// <p>A device object serves as the factory for all other DirectComposition objects. It also controls transactional composition through the <strong>IDCompositionDevice::Commit</strong> method.</p><p>The DXGI device specified by <em>dxgiDevice</em> is used to create all DirectComposition surface objects. In particular, the <strong>IDCompositionSurface::BeginDraw</strong> method returns an interface reference to a DXGI surface that belongs to the device specified by the <em>dxgiDevice</em> parameter. </p><p>When creating the DXGI device, developers must specify the <strong>D3D11_CREATE_DEVICE BGRA_SUPPORT</strong> or <strong>D3D10_CREATE_DEVICE_BGRA_SUPPORT</strong> flag for Direct2D interoperability with Microsoft Direct3D resources.</p><p>The <em>iid</em> parameter must be <code>__uuidof(<see cref = "SharpDX.DirectComposition.Device"/>)</code>, and the <em>dcompositionDevice</em> parameter receives a reference to an <strong><see cref = "SharpDX.DirectComposition.Device"/></strong> interface. /// </p> /// </remarks> /// <doc-id>hh437359</doc-id> /// <unmanaged>HRESULT DCompositionCreateDevice([In, Optional] IDXGIDevice* dxgiDevice,[In] const GUID& iid,[Out] void** dcompositionDevice)</unmanaged> /// <unmanaged-short>DCompositionCreateDevice</unmanaged-short> internal static unsafe void CreateDevice(SharpDX.DXGI.Device dxgiDevice, System.Guid iid, out System.IntPtr dcompositionDevice) { System.IntPtr dxgiDevice_ = System.IntPtr.Zero; SharpDX.Result __result__; dxgiDevice_ = SharpDX.CppObject.ToCallbackPtr <SharpDX.DXGI.Device>(dxgiDevice); fixed(void *dcompositionDevice_ = &dcompositionDevice) __result__ = DCompositionCreateDevice_((void *)dxgiDevice_, &iid, dcompositionDevice_); __result__.CheckError(); }
/// <summary> /// <p>Creates a new device object that can be used to create other Microsoft DirectComposition objects.</p> /// </summary> /// <param name="dxgiDevice"><dd> <p>The DXGI device to use to create DirectComposition surface objects.</p> </dd></param> /// <param name="iid"><dd> <p>The identifier of the interface to retrieve. </p> </dd></param> /// <param name="dcompositionDevice"><dd> <p>Receives an interface reference to the newly created device object. The reference is of the type specified by the <em>iid</em> parameter. This parameter must not be <c>null</c>.</p> </dd></param> /// <returns><p>If the function succeeds, it returns <see cref="SharpDX.Result.Ok"/>. Otherwise, it returns an <strong><see cref="SharpDX.Result"/></strong> error code. See DirectComposition Error Codes for a list of error codes.</p></returns> /// <remarks> /// <p>A device object serves as the factory for all other DirectComposition objects. It also controls transactional composition through the <strong><see cref="SharpDX.DirectComposition.Device.Commit"/></strong> method.</p><p>The DXGI device specified by <em>dxgiDevice</em> is used to create all DirectComposition surface objects. In particular, the <strong><see cref="SharpDX.DirectComposition.Surface.BeginDraw"/></strong> method returns an interface reference to a DXGI surface that belongs to the device specified by the <em>dxgiDevice</em> parameter. </p><p>When creating the DXGI device, developers must specify the <strong>D3D11_CREATE_DEVICE BGRA_SUPPORT</strong> or <strong>D3D10_CREATE_DEVICE_BGRA_SUPPORT</strong> flag for Direct2D interoperability with Microsoft Direct3D resources.</p><p>The <em>iid</em> parameter must be <code>__uuidof(<see cref="SharpDX.DirectComposition.Device"/>)</code>, and the <em>dcompositionDevice</em> parameter receives a reference to an <strong><see cref="SharpDX.DirectComposition.Device"/></strong> interface. /// </p> /// </remarks> /// <include file='.\..\Documentation\CodeComments.xml' path="/comments/comment[@id='DCompositionCreateDevice']/*"/> /// <msdn-id>hh437359</msdn-id> /// <unmanaged>HRESULT DCompositionCreateDevice([In, Optional] IDXGIDevice* dxgiDevice,[In] const GUID& iid,[Out] void** dcompositionDevice)</unmanaged> /// <unmanaged-short>DCompositionCreateDevice</unmanaged-short> internal static void CreateDevice(SharpDX.DXGI.Device dxgiDevice, System.Guid iid, out System.IntPtr dcompositionDevice) { unsafe { SharpDX.Result __result__; fixed(void *dcompositionDevice_ = &dcompositionDevice) __result__ = DCompositionCreateDevice_((void *)((dxgiDevice == null)?IntPtr.Zero:dxgiDevice.NativePointer), &iid, dcompositionDevice_); __result__.CheckError(); } }
public override void Dispose() { this.d3d11Device?.Dispose(); this.d3d11Device = null; this.dxgiDevice?.Dispose(); this.dxgiDevice = null; this.swapChain?.Dispose(); this.swapChain = null; this.swapChainBuffer?.Dispose(); d2dDevice3.Dispose(); deviceContext3.Dispose(); swapChainBuffer.Dispose(); }
/// <summary> /// <p>Creates a new Direct2D device associated with the provided DXGI device. </p> /// </summary> /// <param name = "dxgiDevice"><dd> <p>The DXGI device the Direct2D device is associated with.</p> </dd></param> /// <param name = "creationProperties"><dd> <p>The properties to apply to the Direct2D device.</p> </dd></param> /// <param name = "d2dDevice"><dd> <p>When this function returns, contains the address of a reference to a Direct2D device.</p> </dd></param> /// <returns><p>The function returns an <strong><see cref = "SharpDX.Result"/></strong>. Possible values include, but are not limited to, those in the following table.</p><table> <tr><th><see cref = "SharpDX.Result"/></th><th>Description</th></tr> <tr><td><see cref = "SharpDX.Result.Ok"/></td><td>No error occurred.</td></tr> <tr><td>E_OUTOFMEMORY</td><td>Direct2D could not allocate sufficient memory to complete the call.</td></tr> <tr><td>E_INVALIDARG</td><td>An invalid value was passed to the method.</td></tr> </table><p>?</p></returns> /// <remarks> /// <p>This function will also create a new <strong><see cref = "SharpDX.Direct2D1.Factory1"/></strong> that can be retrieved through <strong>ID2D1Resource::GetFactory</strong>.</p><p>If the creation properties are not specified, then <em>d2dDevice</em> will inherit its threading mode from <em>dxgiDevice</em> and debug tracing will not be enabled.</p> /// </remarks> /// <doc-id>hh404272</doc-id> /// <unmanaged>HRESULT D2D1CreateDevice([In] IDXGIDevice* dxgiDevice,[In, Optional] const D2D1_CREATION_PROPERTIES* creationProperties,[Out, Fast] ID2D1Device** d2dDevice)</unmanaged> /// <unmanaged-short>D2D1CreateDevice</unmanaged-short> public static unsafe void CreateDevice(SharpDX.DXGI.Device dxgiDevice, SharpDX.Direct2D1.CreationProperties?creationProperties, SharpDX.Direct2D1.Device d2dDevice) { System.IntPtr dxgiDevice_ = System.IntPtr.Zero; SharpDX.Direct2D1.CreationProperties creationProperties_; System.IntPtr d2dDevice_ = System.IntPtr.Zero; SharpDX.Result __result__; dxgiDevice_ = SharpDX.CppObject.ToCallbackPtr <SharpDX.DXGI.Device>(dxgiDevice); if (creationProperties != null) { creationProperties_ = creationProperties.Value; } __result__ = D2D1CreateDevice_((void *)dxgiDevice_, creationProperties == null ? (void *)0 : &creationProperties_, &d2dDevice_); (d2dDevice).NativePointer = d2dDevice_; __result__.CheckError(); }
/// <summary> /// <p>Creates a new Direct2D device associated with the provided DXGI device. </p> /// </summary> /// <param name="dxgiDevice"><dd> <p>The DXGI device the Direct2D device is associated with.</p> </dd></param> /// <param name="creationProperties"><dd> <p>The properties to apply to the Direct2D device.</p> </dd></param> /// <param name="d2dDevice"><dd> <p>When this function returns, contains the address of a reference to a Direct2D device.</p> </dd></param> /// <returns><p>The function returns an <strong><see cref="SharpDX.Result"/></strong>. Possible values include, but are not limited to, those in the following table.</p><table> <tr><th><see cref="SharpDX.Result"/></th><th>Description</th></tr> <tr><td><see cref="SharpDX.Result.Ok"/></td><td>No error occurred.</td></tr> <tr><td>E_OUTOFMEMORY</td><td>Direct2D could not allocate sufficient memory to complete the call.</td></tr> <tr><td>E_INVALIDARG</td><td>An invalid value was passed to the method.</td></tr> </table><p>?</p></returns> /// <remarks> /// <p>This function will also create a new <strong><see cref="SharpDX.Direct2D1.Factory1"/></strong> that can be retrieved through <strong><see cref="SharpDX.Direct2D1.Resource.GetFactory"/></strong>.</p><p>If the creation properties are not specified, then <em>d2dDevice</em> will inherit its threading mode from <em>dxgiDevice</em> and debug tracing will not be enabled.</p><p><strong>Windows Phone 8.1:</strong> This API is supported.</p> /// </remarks> /// <include file='.\..\Documentation\CodeComments.xml' path="/comments/comment[@id='D2D1CreateDevice']/*"/> /// <msdn-id>hh404272</msdn-id> /// <unmanaged>HRESULT D2D1CreateDevice([In] IDXGIDevice* dxgiDevice,[In, Optional] const D2D1_CREATION_PROPERTIES* creationProperties,[Out, Fast] ID2D1Device** d2dDevice)</unmanaged> /// <unmanaged-short>D2D1CreateDevice</unmanaged-short> public static void CreateDevice(SharpDX.DXGI.Device dxgiDevice, SharpDX.Direct2D1.CreationProperties?creationProperties, SharpDX.Direct2D1.Device d2dDevice) { unsafe { SharpDX.Direct2D1.CreationProperties creationProperties_; if (creationProperties.HasValue) { creationProperties_ = creationProperties.Value; } IntPtr d2dDevice_ = IntPtr.Zero; SharpDX.Result __result__; __result__ = D2D1CreateDevice_((void *)((dxgiDevice == null)?IntPtr.Zero:dxgiDevice.NativePointer), (creationProperties.HasValue)?&creationProperties_:(void *)IntPtr.Zero, &d2dDevice_); ((SharpDX.Direct2D1.Device)d2dDevice).NativePointer = d2dDevice_; __result__.CheckError(); } }
public DUIDeviceContext3(IntPtr handle) { this.d3d11Device = new SharpDX.Direct3D11.Device(SharpDX.Direct3D.DriverType.Hardware, SharpDX.Direct3D11.DeviceCreationFlags.BgraSupport); this.dxgiDevice = d3d11Device.QueryInterface <SharpDX.Direct3D11.Device1>().QueryInterface <SharpDX.DXGI.Device>(); this.d2dDevice3 = new SharpDX.Direct2D1.Device3(dxgiDevice); this.deviceContext3 = new SharpDX.Direct2D1.DeviceContext3(d2dDevice3, SharpDX.Direct2D1.DeviceContextOptions.None); // 创建 DXGI SwapChain。 SharpDX.DXGI.SwapChainDescription swapChainDescription = new SharpDX.DXGI.SwapChainDescription() { BufferCount = 1, Usage = SharpDX.DXGI.Usage.RenderTargetOutput, OutputHandle = handle, IsWindowed = true, // 这里宽度和高度都是 0,表示自动获取。 ModeDescription = new SharpDX.DXGI.ModeDescription(0, 0, new SharpDX.DXGI.Rational(60, 1), SharpDX.DXGI.Format.B8G8R8A8_UNorm), SampleDescription = new SharpDX.DXGI.SampleDescription(1, 0), SwapEffect = SharpDX.DXGI.SwapEffect.Discard }; this.swapChain = new SharpDX.DXGI.SwapChain(dxgiDevice.GetParent <SharpDX.DXGI.Adapter>().GetParent <SharpDX.DXGI.Factory>(), d3d11Device, swapChainDescription); this.swapChainBuffer = SharpDX.DXGI.Surface.FromSwapChain(this.swapChain, 0); this.targetBitmap = new SharpDX.Direct2D1.Bitmap1(this.deviceContext3, this.swapChainBuffer); this.deviceContext3.Target = targetBitmap; }
/// <summary> /// Initializes a new instance of the <see cref="Device"/> class. /// </summary> /// <param name="factory"><para>The <see cref="Factory1"/> object used when creating the <see cref="SharpDX.Direct2D1.Device"/>. </para></param> /// <param name="dxgiDevice"><para>The <see cref="SharpDX.DXGI.Device"/> object used when creating the <see cref="SharpDX.Direct2D1.Device"/>. </para></param> /// <remarks> /// Each call to CreateDevice returns a unique <see cref="SharpDX.Direct2D1.Device"/> object.The <see cref="SharpDX.DXGI.Device"/> object is obtained by calling QueryInterface on an ID3D10Device or an ID3D11Device. /// </remarks> /// <unmanaged>HRESULT ID2D1Factory1::CreateDevice([In] IDXGIDevice* dxgiDevice,[Out] ID2D1Device** d2dDevice)</unmanaged> public Device(Factory1 factory, SharpDX.DXGI.Device device) : base(IntPtr.Zero) { factory.CreateDevice(device, this); }
/// <summary> /// Initializes a new instance of the <see cref="Device"/> class. /// </summary> /// <param name="device">The device.</param> /// <param name="creationProperties">The creation properties.</param> /// <unmanaged>HRESULT D2D1CreateDevice([In] IDXGIDevice* dxgiDevice,[In, Optional] const D2D1_CREATION_PROPERTIES* creationProperties,[Out] ID2D1Device** d2dDevice)</unmanaged> public Device(SharpDX.DXGI.Device device, CreationProperties creationProperties) : base(IntPtr.Zero) { D2D1.CreateDevice(device, creationProperties, this); }
/// <summary> /// Initializes a new instance of the <see cref="Device"/> class. /// </summary> /// <param name="device">The device.</param> /// <unmanaged>HRESULT D2D1CreateDevice([In] IDXGIDevice* dxgiDevice,[In, Optional] const D2D1_CREATION_PROPERTIES* creationProperties,[Out] ID2D1Device** d2dDevice)</unmanaged> public Device(SharpDX.DXGI.Device device) : base(IntPtr.Zero) { D2D1.CreateDevice(device, null, this); }
/// <inheritdoc /> /// <summary> /// Binds a DXGI device to the video codec /// </summary> /// <param name="device">DXGI device object</param> public void BindDevice(Device device) { this.dxgiManager = new DXGIDeviceManager(); this.dxgiManager.ResetDevice(device); }
private static void CreateDevices(int graphicsAdapter) { var deviceCreationFlags = DeviceCreationFlags.BgraSupport; #if DEBUG deviceCreationFlags |= DeviceCreationFlags.Debug; #endif Logger.Info("Attempting to create device."); var adapter = Factory.GetAdapter(graphicsAdapter); var levels = new[] { FeatureLevel.Level_11_1, FeatureLevel.Level_11_0, FeatureLevel.Level_10_1, FeatureLevel.Level_10_0, FeatureLevel.Level_9_3 }; var device = new SharpDX.Direct3D11.Device(adapter, deviceCreationFlags, levels) { DebugName = adapter.Description.Description }; Logger.Info( $"GPU{graphicsAdapter}: {device.DebugName} ({((long)adapter.Description.DedicatedVideoMemory).ToPrettySize()} VRAM)"); Device = device.QueryInterface <DeviceD3D>(); Device.DebugName = device.DebugName; Logger.Info("D3D Device created."); if (deviceCreationFlags.HasFlag(DeviceCreationFlags.Debug)) { DeviceDebug = new DeviceDebug(Device); Logger.Info("Debug device created."); } DxgiDevice = Device.QueryInterface <Device>(); Context = Device.ImmediateContext; Device2D = new DeviceD2D(Factory2D, DxgiDevice); Context2D = new ContextD2D(Device2D, DeviceContextOptions.EnableMultithreadedOptimizations) { TextAntialiasMode = RenderSettings.UseClearTypeRendering ? TextAntialiasMode.Cleartype : (RenderSettings.GuiAntiAliasing ? TextAntialiasMode.Grayscale : TextAntialiasMode.Aliased), AntialiasMode = RenderSettings.GuiAntiAliasing ? AntialiasMode.PerPrimitive : AntialiasMode.Aliased, UnitMode = UnitMode.Pixels }; Logger.Info("D2D Device created."); Logger.Info("Filling out DebugSettings GPU info."); DebugSettings.FillGpuInfo(adapter); #if DEBUG try { DeviceDebug = new DeviceDebug(Device); Logger.Info("Debug device created."); } catch (SharpDXException) { Logger.Warn("DeviceDebug not supported."); } #endif Logger.Info("Renderer initialized."); }
/// <summary> /// Starts the workflow interactively /// </summary> internal async Task StartAsync(HudContainerInfo container) { this.currentContainer = container; Log.Info($"starting {Type} workflow on {container.ContainerType} container"); await AcquireRegionAsync(); if (Region.Size.Width <= Clipper.MinimumWidth || Region.Size.Height <= Clipper.MinimumHeight) { Log.Trace("capture dismissed"); Finish(); return; } if (this.captureDevice == null || !Equals(this.captureDevice.Size.ToTuple(), Region.Size.ToTuple())) { // dispose old video provider if size changed this.captureDevice?.Dispose(); // video provider will capture frames Log.Debug("creating capture device"); this.captureDevice = CaptureDeviceFactory.CreateVideoCaptureDevice( Region.Location.X, Region.Location.Y, Region.Size.Width, Region.Size.Height); // TODO: create and bind transforms } // create destination stream, a MultiStream which will act as some kind of stream multiplexer wrapping multiple // "sub-streams" onto one // TODO: add IImmediateHandler's to the MultiStream this.stream = new MultiStream(); // create codec instance if (Type == WorkflowType.Still) { this.codec = Application.ExtensionManager.CreateObject <StillImageCodec>(Codec.TypeName, Region.Size.Width, Region.Size.Height, this.stream); } else if (Type == WorkflowType.Motion) { this.codec = Application.ExtensionManager.CreateObject <VideoCodec>(Codec.TypeName, Region.Size.Width, Region.Size.Height, this.stream); } // create handlers this.handlers = Handlers.Select(handlerData => { Handler handler = Application.ExtensionManager.CreateObject <Handler>( handlerData.TypeName, this, this.codec, this.stream, handlerData.Options); if (handler is IStreamWrapper streamWrapperHandler) { // add stream wrapper to the multi-stream this.stream.Add(streamWrapperHandler.OutputStream); Log.Trace("added stream wrapper handler: " + handlerData.TypeName); } return(handler); }).ToArray(); if (Type == WorkflowType.Still) { // still image -- we do not need our stream to be filesystem-backed, as still images can't really be *that* // large... I hope this.stream.Add(new MemoryStream()); Log.Info("capturing screen"); this.captureDevice.AcquireFrame(); VideoFrame frame = this.captureDevice.LockFrame(); Log.Info("encoding capture"); this.codec.Start(); this.codec.Feed(frame); this.codec.Dispose(); // unlock and release capture this.captureDevice.UnlockFrame(frame); this.captureDevice.ReleaseFrame(); Finish(); } else { // motion capture -- stand back and don't underestimate my expertise on googling // save output to a temporary file Log.Info("starting recording session"); // create toolbar this.toolbar = new Toolbar(Application.HudManager.GetContainer()); this.clipper?.AttachToolbar(this.toolbar); /* bind toolbar events */ // option events this.toolbar.OnOptionsRequested += delegate(object sender, ToolbarOptionRequestType optionType) { switch (optionType) { case ToolbarOptionRequestType.Generic: try { new OptionsWindow().Show(); } catch { /* already open */ } break; default: throw new NotImplementedException(); } }; // recording control intents this.toolbar.OnRecordingIntentReceived += delegate(object sender, ToolbarRecordingControlIntent controlIntent) { try { Log.Info($"received recording control intent: {controlIntent}"); this.toolbar.SetPrimaryButtonState(enabled: false); switch (controlIntent) { case ToolbarRecordingControlIntent.Start: /* start recording */ if (!(this.motionSession?.Disposed ?? true)) { throw new InvalidOperationException("A previous motion capture session has not been closed"); } if (!(this.codec is VideoCodec)) { throw new NotSupportedException("The current codec does not allow multiple frames"); } // ReSharper disable once ConditionIsAlwaysTrueOrFalse if ( this.captureDevice is DxgiVideoCaptureDevice dxgiCaptureDevice && // make sure our capture device is DXGI-enabled this.codec is IDxgiEnabledVideoCodec dxgiCodec) { // make sure our codec is DXGI-compatible // make sure we have the same D3D device for all sources Device device = dxgiCaptureDevice.Devices.First(); if (dxgiCaptureDevice.Devices.All(d => d == device)) { // set device to be bound to the DXGI device manager // TODO: optimize DxgiVideoProvider so that it only creates one device for each adapter // TODO: allow ID3DCodec's to operate on multiple DXGI devices dxgiCodec.BindDevice(device); Log.Info("bound DXGI device to codec"); } } // create motion capture session and change toolbar button intent this.motionSession = new MotionCaptureSession((VideoCodec)this.codec, this.captureDevice); this.toolbar.SetPrimaryButtonState(ToolbarRecordingControlIntent.Stop); break; case ToolbarRecordingControlIntent.Stop: this.motionSession.Dispose(); Finish(); break; default: throw new NotImplementedException(); } } finally { this.toolbar?.SetPrimaryButtonState(enabled: true); } }; } }