/// <summary>
        /// Initializes a new instance of the <see cref="EngineAdapterInfo" /> class.
        /// </summary>
        internal EngineAdapterInfo(int adapterIndex, IDXGIAdapter1 adapter)
        {
            this.Outputs      = new List <EngineOutputInfo>();
            this.AdapterIndex = adapterIndex;

            _adapterDescription    = adapter.Description;
            this.IsSoftwareAdapter =
                _adapterDescription.Description == "Microsoft Basic Render Driver" ||
                !string.IsNullOrEmpty(_adapterDescription.Description) && _adapterDescription.Description.Contains("Software") ||
                !string.IsNullOrEmpty(_adapterDescription.Description) && _adapterDescription.Description.Contains("Microsoft Basic Render Driver");
            _d3d11FeatureLevel = D3D11.D3D11.GetSupportedFeatureLevel(adapter);

            //Query for output information
            var lastResult = Result.Ok;
            var actIndex   = 0;

            do
            {
                lastResult = adapter.EnumOutputs(actIndex, out var actOutput);
                if (lastResult.Success)
                {
                    this.Outputs.Add(new EngineOutputInfo(adapterIndex, actIndex, actOutput));
                }
                actIndex++;
            }while (lastResult.Success);
        }
Пример #2
0
        public static int Main()
        {
            int result;

            using (IDXGIFactory1 factory1 = new DXGIFactory1())
            {
                LinkedList <IDXGIAdapter1> adapters = new LinkedList <IDXGIAdapter1>();

                uint adapterId = 0;
                while ((result = factory1.EnumAdapters1(adapterId, out IDXGIAdapter1 currentAdapter)) == 0)
                {
                    adapterId++;
                    result = currentAdapter.GetDesc1(out DXGIAdapterDescription1 adapterDescription);

                    if (result != 0)
                    {
                        foreach (IDXGIAdapter1 dxgiAdapter1 in adapters)
                        {
                            dxgiAdapter1.Dispose();
                        }

                        return(1);
                    }

                    if ((adapterDescription.Flags & DXGIAdapterFlag.Software) != 0)
                    {
                        currentAdapter.Dispose();
                        continue;
                    }

                    adapters.AddLast(currentAdapter);
                }

                if (adapters.Count == 0)
                {
                    foreach (IDXGIAdapter1 dxgiAdapter1 in adapters)
                    {
                        dxgiAdapter1.Dispose();
                    }

                    return(2);
                }

                FeatureLevel[] featureLevels =
                {
                    FeatureLevel.Level_12_1,
                    FeatureLevel.Level_12_0,
                    FeatureLevel.Level_11_1,
                    FeatureLevel.Level_11_0,
                    FeatureLevel.Level_10_1,
                    FeatureLevel.Level_10_0,
                    FeatureLevel.Level_9_3,
                    FeatureLevel.Level_9_2,
                    FeatureLevel.Level_9_1
                };

                result = DXGINativeMethods.D3D11CreateDevice
                         (
                    adapters.First.Value,
                    DriverType.Unknown,
                    IntPtr.Zero,
                    0x2,
                    featureLevels,
                    7u,
                    out IUnknown d3d11Device,
                    out FeatureLevel selectedLevel,
                    out IUnknown d3d11DeviceContext
                         );

                if (result != 0)
                {
                    foreach (IDXGIAdapter1 dxgiAdapter1 in adapters)
                    {
                        dxgiAdapter1.Dispose();
                    }

                    return(3);
                }

                using (d3d11Device)
                {
                    using (IDXGIAdapter1 adapter = adapters.First.Value)
                    {
                        using (d3d11DeviceContext)
                        {
                            result = adapter.EnumOutputs(0, out IDXGIOutput output);

                            if (result != 0)
                            {
                                foreach (IDXGIAdapter1 dxgiAdapter1 in adapters)
                                {
                                    dxgiAdapter1.Dispose();
                                }

                                return(4);
                            }

                            using (output)
                            {
                                result = output.QueryInterface(typeof(IDXGIOutput1).GUID, out IntPtr output1Ptr);
                                if (result != 0)
                                {
                                    foreach (IDXGIAdapter1 dxgiAdapter1 in adapters)
                                    {
                                        dxgiAdapter1.Dispose();
                                    }

                                    return(5);
                                }

                                using (IDXGIOutput1 output1 = new DXGIOutput1(output1Ptr))
                                {
                                    result = output1.DuplicateOutput(d3d11Device,
                                                                     out IDXGIOutputDuplication duplicationOutput);

                                    if (result != 0)
                                    {
                                        foreach (IDXGIAdapter1 dxgiAdapter1 in adapters)
                                        {
                                            dxgiAdapter1.Dispose();
                                        }

                                        return(6);
                                    }

                                    duplicationOutput.GetDesc(out DXGIOutDuplDescription duplDescription);

                                    duplicationOutput.ReleaseFrame();
                                    duplicationOutput.Dispose();
                                }
                            }
                        }
                    }
                }
            }

            return(result);
        }
            public static DesktopDuplicatorInternal CreateDesktopDuplicator(ILogger logger, int adapterIndex, int outputDeviceIndex)
            {
                var dd = new DesktopDuplicatorInternal
                {
                    _outputDeviceIndex = outputDeviceIndex
                };

                var createFactoryResult = DXGI.CreateDXGIFactory1(out IDXGIFactory1 factory);

                if (!createFactoryResult.Success)
                {
                    throw new DesktopDuplicationException("Couldn't create a DXGI Factory.");
                }

                IDXGIAdapter1 adapter = null;
                IDXGIOutput   output  = null;

                try
                {
                    var result = factory.EnumAdapters1(adapterIndex, out adapter);
                    if (result.Failure)
                    {
                        throw new DesktopDuplicationException($"An error occurred attempting to retrieve the adapter at the specified index ({adapterIndex}): {result}");
                    }

                    if (adapter == null)
                    {
                        throw new DesktopDuplicationException($"An adapter was not found at the specified index ({adapterIndex}).");
                    }

                    logger.LogInformation($"Using adapter at index {adapterIndex} - {adapter.Description.Description}");

                    var createD3dDeviceResult = D3D11.D3D11CreateDevice(adapter, DriverType.Unknown, DeviceCreationFlags.None, null, out dd._d3dDevice, out dd._immediateContext);
                    if (!createD3dDeviceResult.Success)
                    {
                        throw new DesktopDuplicationException("Couldn't create a D3D device from the specified adapter.");
                    }

                    using var device = dd._d3dDevice.QueryInterface <IDXGIDevice>();
                    var outputResult = adapter.EnumOutputs(outputDeviceIndex, out output);
                    if (outputResult.Failure)
                    {
                        throw new DesktopDuplicationException($"An error occurred attempting to retrieve the output device at the specified index ({outputDeviceIndex}): {outputResult}");
                    }

                    if (output == null)
                    {
                        throw new DesktopDuplicationException($"An output was not found at the specified index ({outputDeviceIndex}).");
                    }

                    logger.LogInformation($"Using output device on adapter {adapterIndex} at index {outputDeviceIndex}.");

                    var output6 = output.QueryInterface <IDXGIOutput6>();
                    try
                    {
                        // Copy the values to a new rect.
                        var rectTemp = output6.Description.DesktopCoordinates;
                        dd._desktopRect = new RawRect(rectTemp.Left, rectTemp.Top, rectTemp.Right, rectTemp.Bottom);

                        dd._outputDuplication = output6.DuplicateOutput(device);

                        var stagingTexture = new Texture2DDescription()
                        {
                            CpuAccessFlags    = CpuAccessFlags.Read,
                            BindFlags         = BindFlags.None,
                            Format            = dd._outputDuplication.Description.ModeDescription.Format,
                            Width             = Math.Abs(dd._desktopRect.Right - dd._desktopRect.Left),
                            Height            = Math.Abs(dd._desktopRect.Bottom - dd._desktopRect.Top),
                            OptionFlags       = ResourceOptionFlags.None,
                            MipLevels         = 1,
                            ArraySize         = 1,
                            SampleDescription = { Count = 1, Quality = 0 },
                            Usage             = Usage.Staging // << can be read by CPU
                        };

                        // Initialize the Output Duplication -- If this isn't done occassionally an 'Unsupported' result will occur with DuplicationOutput1
                        dd._desktopImageTexture = dd._d3dDevice.CreateTexture2D(stagingTexture);
                    }
                    catch (SharpGenException ex)
                    {
                        if (ex.Descriptor.NativeApiCode == "DXGI_ERROR_UNSUPPORTED")
                        {
                            throw new DesktopDuplicationException("Unsupported desktop mode or scenario.");
                        }
                        else if (ex.Descriptor.NativeApiCode == "DXGI_ERROR_NOT_CURRENTLY_AVAILABLE")
                        {
                            throw new DesktopDuplicationException("There is already the maximum number of applications using the Desktop Duplication API running, please close one of the applications and try again.");
                        }
                        else
                        {
                            throw;
                        }
                    }
                }
                finally
                {
                    if (output != null)
                    {
                        output.Dispose();
                    }

                    if (adapter != null)
                    {
                        adapter.Dispose();
                    }

                    if (factory != null)
                    {
                        factory.Dispose();
                    }
                }

                return(dd);
            }