コード例 #1
0
        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();
        }
コード例 #2
0
        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;
            }
        }
コード例 #3
0
        /// <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&amp; 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();
        }
コード例 #4
0
        /// <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&amp; 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();
            }
        }
コード例 #5
0
ファイル: DUIDeviceContext3.cs プロジェクト: scjjcs/DirectUI
 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();
 }
コード例 #6
0
 /// <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();
 }
コード例 #7
0
 /// <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();
     }
 }
コード例 #8
0
ファイル: DUIDeviceContext3.cs プロジェクト: scjjcs/DirectUI
 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;
 }
コード例 #9
0
 /// <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);
 }
コード例 #10
0
 /// <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);
 }
コード例 #11
0
 /// <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);
 }
コード例 #12
0
 /// <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);
 }
コード例 #13
0
ファイル: Renderer.cs プロジェクト: gitter-badger/dEngine
        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.");
        }
コード例 #14
0
        /// <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);
                    }
                };
            }
        }