private IDXGIAdapter1 GetHardwareAdapter() { IDXGIAdapter1 adapter = null; IDXGIFactory6 factory6 = Factory.QueryInterfaceOrNull <IDXGIFactory6>(); if (factory6 != null) { for (int adapterIndex = 0; factory6.EnumAdapterByGpuPreference(adapterIndex, GpuPreference.HighPerformance, out adapter) != Vortice.DXGI.ResultCode.NotFound; adapterIndex++) { AdapterDescription1 desc = adapter.Description1; if ((desc.Flags & AdapterFlags.Software) != AdapterFlags.None) { // Don't select the Basic Render Driver adapter. adapter.Dispose(); continue; } return(adapter); } factory6.Dispose(); } if (adapter == null) { for (int adapterIndex = 0; Factory.EnumAdapters1(adapterIndex, out adapter) != Vortice.DXGI.ResultCode.NotFound; adapterIndex++) { AdapterDescription1 desc = adapter.Description1; if ((desc.Flags & AdapterFlags.Software) != AdapterFlags.None) { // Don't select the Basic Render Driver adapter. adapter.Dispose(); continue; } return(adapter); } } return(adapter); }
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); }