/// <summary>
        /// Initializes all adapters with the specified factory.
        /// </summary>
        internal static void InitializeInternal()
        {
            staticCollector.Dispose();

#if DIRECTX11_1
            using (var factory = new Factory1())
                NativeFactory = factory.QueryInterface <Factory2>();
#elif SILICONSTUDIO_PLATFORM_UWP
            // Maybe this will become default code for everybody if we switch to DX 11.1/11.2 SharpDX dll?
            NativeFactory = new Factory2();
#else
            NativeFactory = new Factory1();
#endif

            staticCollector.Add(NativeFactory);

            int countAdapters = NativeFactory.GetAdapterCount1();
            var adapterList   = new List <GraphicsAdapter>();
            for (int i = 0; i < countAdapters; i++)
            {
                var adapter = new GraphicsAdapter(NativeFactory, i);
                staticCollector.Add(adapter);
                adapterList.Add(adapter);
            }

            defaultAdapter = adapterList.Count > 0 ? adapterList[0] : null;
            adapters       = adapterList.ToArray();
        }
        public void getCaps()
        {
            Factory1        fac         = new Factory1();
            int             numAdapters = fac.GetAdapterCount1();
            List <Adapter1> adapts      = new List <Adapter1>();

            for (int i = 0; i < numAdapters; i++)
            {
                adapts.Add(fac.GetAdapter1(i));
            }

            Output outp = adapts[0].GetOutput(0);

            List <Format> formats = new List <Format>();

            foreach (Format format in Enum.GetValues(typeof(Format)))
            {
                formats.Add(format);
            }

            //List<ReadOnlyCollection<ModeDescription>> ll = new List<ReadOnlyCollection<ModeDescription>>();
            List <ModeDescription[]> ll = new List <ModeDescription[]>();

            for (int i = 0; i < formats.Count - 1; i++)
            {
                //ReadOnlyCollection<ModeDescription> mdl;
                ModeDescription[] mdl;
                mdl = outp.GetDisplayModeList(formats[i], DisplayModeEnumerationFlags.Interlaced);
                ll.Add(mdl);
                if (mdl != null)
                {
                    Console.WriteLine(formats[i].ToString());
                }
            }
        }
Пример #3
0
        public DesktopDuplicator(IntPtr window)
        {
            User32.GetWindowRect(window, out var rectNative);
            var windowRect = rectNative.ToRect();

            // Search all outputs on all adapters and find the window rect.
            var factory = new Factory1();

            for (var j = 0; j < factory.GetAdapterCount1(); j++)
            {
                var adapter = factory.GetAdapter1(j);

                for (var i = 0; i < adapter.GetOutputCount(); i++)
                {
                    var output = adapter.GetOutput(i);
                    var bounds = output.Description.DesktopBounds.ToRectangle();
                    if (bounds.Contains(windowRect))
                    {
                        Initialize(0, i);
                        return;
                    }
                }
            }

            throw new Exception($"Didn't find the {window} window on any display output.");
        }
Пример #4
0
        /// <summary>
        /// 最適グラフィックスアダプタを返す
        /// </summary>
        /// <returns></returns>
        static Adapter GetAdapter(Factory1 factory)
        {
            // 優先順
            string[] vender_string = new string[] {
                "nvidia",
                "ati",
            };
            Adapter1 result       = factory.GetAdapter1(0);
            int      adapterCount = factory.GetAdapterCount1();

            for (int i = 1; i < adapterCount; i++)
            {
                Adapter1 adapter     = factory.GetAdapter1(i);
                var      device_name = adapter.Description.Description.ToLower();
                for (int j = 0; j < vender_string.Length; j++)
                {
                    if (device_name.Contains(vender_string[j]))
                    {
                        result = adapter;
                    }
                }
            }

            return(result);
        }
        /// <inheritdoc />
        /// <summary>
        ///   Class constructor
        /// </summary>
        /// <param name="x">Horizontal coordinate, in pixels, for the virtual capture location</param>
        /// <param name="y">Vertical coordinate, in pixels, for the virtual cpature location</param>
        /// <param name="width">Width, in pixels, for the captured region</param>
        /// <param name="height">Height, in pixels, for the captured region</param>
        public DxgiVideoCaptureDevice(int x, int y, int width, int height) : base(x, y, width, height)
        {
            // we'll need the system timer frequency in order to convert the output duplication present time to ticks
            Kernel32.QueryPerformanceFrequency(out this.perfFreq);
            this.virtualRect = new Rectangle(x, y, width, height);

            // obtain a list of capture sources
            // obtain a list of capture sources
            using (var factory = new Factory1()) {
                if (factory.GetAdapterCount1() == 0)
                {
                    throw new NotSupportedException("No suitable video adapters found");
                }

                var captureSources = new List <DxgiCaptureSource>();

                foreach (Adapter1 adapter in factory.Adapters1)
                {
                    Debug.WriteLine($"+ {adapter.Description1.Description}");

                    foreach (Output output in adapter.Outputs)
                    {
                        Debug.Write($"+   {output.Description.DeviceName} ");
                        var intersection = Rectangle.Intersect(this.virtualRect, output.Description.DesktopBounds);
                        if (intersection.Width > 0 && intersection.Height > 0)
                        {
                            try {
                                Debug.WriteLine($"[XSECT: {intersection}]");
                                captureSources.Add(new DxgiCaptureSource(adapter,
                                                                         output,
                                                                         new Rectangle(intersection.X,
                                                                                       intersection.Y,
                                                                                       intersection.Width,
                                                                                       intersection.Height)));
                            } catch (NotSupportedException exception)
                                when(exception.InnerException?.HResult == ResultCode.Unsupported.Result)
                                {
                                    // HACK: when Captain itself is running on the dGPU, DDA calls fail with DXGI_ERROR_UNSPUPORTED
                                    //       if the main desktop is not bound to it (see https://support.microsoft.com/en-us/kb/3019314).
                                    //       We fix this by trying the next adapter
                                }
                        }
                        else
                        {
                            Debug.WriteLine("[MISMATCH]");
                        }
                    }
                }

                this.sources = captureSources.ToArray();
            }
        }
Пример #6
0
        private Tuple <int, int>[] GetCapturedOutputs()
        {
            var ret = new List <Tuple <int, int> >(6);//most cases

            for (var adapterIndex = _factory.GetAdapterCount1() - 1; adapterIndex >= 0; adapterIndex--)
            {
                using (var adapter = _factory.GetAdapter1(adapterIndex))
                    for (var outputIndex = adapter.GetOutputCount() - 1; outputIndex >= 0; outputIndex--)
                    {
                        using (var output = adapter.GetOutput(outputIndex))
                            if (output.Description.DesktopBounds.ToGDIRect().IntersectsWith(_sourceRect.Value))
                            {
                                ret.Add(new Tuple <int, int>(adapterIndex, outputIndex));
                            }
                    }
            }
            return(ret.ToArray());
        }
        /// <inheritdoc />
        /// <summary>
        ///   Class constructor
        /// </summary>
        /// <param name="x">Horizontal coordinate, in pixels, for the virtual capture location</param>
        /// <param name="y">Vertical coordinate, in pixels, for the virtual cpature location</param>
        /// <param name="width">Width, in pixels, for the captured region</param>
        /// <param name="height">Height, in pixels, for the captured region</param>
        public DxgiVideoCaptureDevice(int x, int y, int width, int height) : base(x, y, width, height)
        {
            // we'll need the system timer frequency in order to convert the output duplication present time to ticks
            Kernel32.QueryPerformanceFrequency(out this.perfFreq);
            this.virtualRect = new Rectangle(x, y, width, height);

            // obtain a list of capture sources
            // obtain a list of capture sources
            using (var factory = new Factory1()) {
                if (factory.GetAdapterCount1() == 0)
                {
                    throw new NotSupportedException("No suitable video adapters found");
                }

                var captureSources = new List <DxgiCaptureSource>();

                foreach (Adapter1 adapter in factory.Adapters1)
                {
                    foreach (Output output in adapter.Outputs)
                    {
                        Rectangle intersection = Rectangle.Intersect(this.virtualRect, output.Description.DesktopBounds);

                        if (intersection.Width > 0 && intersection.Height > 0)
                        {
                            captureSources.Add(new DxgiCaptureSource(adapter,
                                                                     output,
                                                                     new Rectangle(intersection.X,
                                                                                   intersection.Y,
                                                                                   intersection.Width,
                                                                                   intersection.Height)));
                        }

                        output.Dispose();
                    }

                    adapter.Dispose();
                }

                this.sources = captureSources.ToArray();
            }
        }
Пример #8
0
        private static void QueryAdapters()
        {
            var adapt = new Dictionary <string, string>();
            var displ = new Dictionary <string, List <string> >();

            using (var factory = new Factory1())
            {
                var acount = factory.GetAdapterCount1();
                for (var i = 0; i < acount; i++)
                {
                    using (var adapter = factory.GetAdapter1(i))
                    {
                        var adesc = adapter.Description1;
                        if (adesc.Flags.HasFlag(AdapterFlags.Software))
                        {
                            continue;
                        }

                        var disp = new List <string>();
                        displ.Add(adesc.DeviceId.ToString(), disp);
                        adapt.Add(adesc.DeviceId.ToString(), adesc.Description);

                        var ocount = adapter.GetOutputCount();
                        for (var j = 0; j < ocount; j++)
                        {
                            using (var output = adapter.GetOutput(i))
                            {
                                var odesc  = output.Description;
                                var width  = odesc.DesktopBounds.Right - odesc.DesktopBounds.Left;
                                var height = odesc.DesktopBounds.Bottom - odesc.DesktopBounds.Top;
                                disp.Add($"{odesc.DeviceName} ({width} x {height})");
                            }
                        }
                    }
                }
            }
            adapters = adapt;
            displays = displ;
        }
Пример #9
0
 internal static Adapter1 GetAdapter(int deviceId)
 {
     using (var factory = new Factory1())
     {
         var      count   = factory.GetAdapterCount1();
         Adapter1 adapter = null;
         for (var i = 0; i < count; i++)
         {
             try {
                 adapter = factory.GetAdapter1(i);
                 if (adapter.Description1.DeviceId == deviceId)
                 {
                     return(adapter);
                 }
                 adapter.Dispose();
             }
             catch {
                 adapter?.Dispose();
             }
         }
     }
     throw new ArgumentException($"Invalid adapter {deviceId}");
 }
Пример #10
0
        /// <summary>
        ///   Creates a capture source with the same properties as this one
        /// </summary>
        /// <param name="bounds">Target screen bounds</param>
        /// <returns>A new <see cref="DxgiCaptureSource"/> instance</returns>
        internal static DxgiCaptureSource Recreate(Rectangle bounds)
        {
            DxgiCaptureSource source = null;

            using (var factory = new Factory1()) {
                if (factory.GetAdapterCount1() == 0)
                {
                    throw new NotSupportedException("No suitable video adapters found");
                }

                foreach (Adapter1 adapter in factory.Adapters1)
                {
                    foreach (Output output in adapter.Outputs)
                    {
                        var intersection = Rectangle.Intersect(bounds, output.Description.DesktopBounds);
                        if (intersection.Width > 0 && intersection.Height > 0)
                        {
                            source = new DxgiCaptureSource(adapter, output, new Rectangle(intersection.X,
                                                                                          intersection.Y,
                                                                                          intersection.Width,
                                                                                          intersection.Height));
                            break;
                        }

                        output.Dispose();
                    }

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

            return(source ?? throw new Exception("No suitable capture sources were found"));
        }
Пример #11
0
        /// <summary>
        /// Initializes all adapters with the specified factory.
        /// </summary>
        /// <param name="factory1">The factory1.</param>
        internal static void Initialize(Factory1 factory1)
        {
            if (staticCollector != null)
            {
                staticCollector.Dispose();
            }

            staticCollector = new DisposeCollector();
            defaultFactory  = factory1;
            staticCollector.Collect(defaultFactory);

            int countAdapters = defaultFactory.GetAdapterCount1();
            var adapterList   = new List <GraphicsAdapter>();

            for (int i = 0; i < countAdapters; i++)
            {
                var adapter = new GraphicsAdapter(i);
                staticCollector.Collect(adapter);
                adapterList.Add(adapter);
            }

            defaultAdapter = adapterList.Count > 0 ? adapterList[0] : null;
            adapters       = adapterList.ToArray();
        }
Пример #12
0
        /// <summary>
        /// Initializes all adapters with the specified factory.
        /// </summary>
        /// <param name="factory1">The factory1.</param>
        internal static void Initialize(Factory1 factory1)
        {
            if (staticCollector != null)
            {
                staticCollector.Dispose();
            }

            staticCollector = new DisposeCollector();
            Factory         = factory1;
            staticCollector.Collect(Factory);

            int countAdapters = Factory.GetAdapterCount1();
            var adapters      = new List <GraphicsAdapter>();

            for (int i = 0; i < countAdapters; i++)
            {
                var adapter = new GraphicsAdapter(i);
                staticCollector.Collect(adapter);
                adapters.Add(adapter);
            }

            Default  = adapters[0];
            Adapters = adapters.ToArray();
        }
Пример #13
0
        /// <inheritdoc />
        /// <summary>
        ///   Class constructor
        /// </summary>
        /// <param name="rect">Screen region</param>
        /// <exception cref="NotSupportedException">Thrown when no video adapters were found</exception>
        /// <exception cref="ArgumentOutOfRangeException">Thrown when the capture region is empty</exception>
        internal DxgiVideoProvider(Rectangle rect)
        {
            Log.WriteLine(LogLevel.Debug, "creating DXGI video provider");

            var factory       = new Factory1();
            var intersections = new List <(Adapter Adapter, Output Output, Rectangle Rectangle, Rectangle Bounds)>();

            // enumerate outputs
            if (factory.GetAdapterCount1() == 0)
            {
                throw new NotSupportedException("No suitable video adapters found");
            }

            foreach (Adapter adapter in factory.Adapters)
            {
                intersections.AddRange(from output in adapter.Outputs
                                       let outputRect = new Rectangle(output.Description.DesktopBounds.Left,
                                                                      output.Description.DesktopBounds.Top,
                                                                      output.Description.DesktopBounds.Right -
                                                                      output.Description.DesktopBounds.Left,
                                                                      output.Description.DesktopBounds.Bottom -
                                                                      output.Description.DesktopBounds.Top)
                                                        let intersection = Rectangle.Intersect(rect, outputRect)
                                                                           where intersection.Width > 0 && intersection.Height > 0
                                                                           select(adapter, output, intersection, outputRect));
            }

            // make sure we do not capture out of bounds
            //this.rect = triples.Select(t => Rectangle.Union(this.rect, t.Rectangle)).Last();
            CaptureBounds = rect;
            if (CaptureBounds.IsEmpty)
            {
                throw new ArgumentOutOfRangeException(nameof(rect));
            }

            // create adapter, output arrays
            this.adapters = intersections.Select(t => t.Adapter).ToArray();
            this.outputs  = intersections.Select(t => t.Output).ToArray();

            // set rectangles for each output
            this.rects   = intersections.Select(t => t.Rectangle).ToArray();
            this.regions = intersections.Select(t => {
                var region = new ResourceRegion(t.Rectangle.X - t.Bounds.X,
                                                t.Rectangle.Y - t.Bounds.Y,
                                                0,
                                                t.Rectangle.Width,
                                                t.Rectangle.Height,
                                                1);

                region.Right  += region.Left;
                region.Bottom += region.Top;

                return(region);
            })
                           .ToArray();

            // create devices for each adapter
            this.devices = this.adapters.Select((a, i) => {
                var flags = DeviceCreationFlags.VideoSupport;
#if DEBUG
                flags |= DeviceCreationFlags.Debug;
#endif
                var device = new Device(a, flags, FeatureLevel.Level_12_1, FeatureLevel.Level_12_0, FeatureLevel.Level_11_0)
                {
#if DEBUG
                    DebugName = $"[#{i}] {a.Description.Description}"
#endif
                };

                device.QueryInterface <Multithread>().SetMultithreadProtected(new RawBool(true));
                return(device);
            })
                           .ToArray();

            // create the shared texture in this device
            StagingTextures = this.devices.Select((d, i) => new Texture2D(d,
                                                                          new Texture2DDescription {
                CpuAccessFlags    = CpuAccessFlags.Read,
                BindFlags         = BindFlags.None,
                Format            = Format.B8G8R8A8_UNorm,
                Width             = intersections[i].Rectangle.Width,
                Height            = intersections[i].Rectangle.Height,
                OptionFlags       = ResourceOptionFlags.None,
                MipLevels         = 1,
                ArraySize         = 1,
                SampleDescription = { Count = 1, Quality = 0 },
                Usage             = ResourceUsage.Staging
            }))
                              .ToArray();

            // let video encoders use the screen texture if a single monitor is being captured
            // TODO: implement D3D12 multi-adapter support

            /*if (...) {
             * // create full capture texture
             * SharedTexture = new Texture2D(this.devices[0],
             *  new Texture2DDescription {
             *    CpuAccessFlags = CpuAccessFlags.Read | CpuAccessFlags.Write,
             *    BindFlags = BindFlags.None,
             *    Format = Format.B8G8R8A8_UNorm,
             *    Width = CaptureBounds.Width,
             *    Height = CaptureBounds.Height,
             *    OptionFlags = ResourceOptionFlags.None,
             *    MipLevels = 1,
             *    ArraySize = 1,
             *    SampleDescription = {Count = 1, Quality = 0},
             *    Usage = ResourceUsage.Staging
             *  });
             * } else*/
            if (StagingTextures.Length == 1)
            {
                SharedTexture = StagingTextures[0];
            }

            // duplicate desktops
            this.duplications = this.outputs.Select((o, i) => {
                try {
                    // attempt to use DuplicateOutput1 for improved performance and SRGB support
                    Format[] formats = { Format.B8G8R8A8_UNorm };
                    return(o.QueryInterface <Output6>().DuplicateOutput1(this.devices[i], 0, formats.Length, formats));
                } catch (SharpDXException exception1) when(exception1.HResult ==
                                                           ResultCode.Unsupported.Result)
                {
                    try { return(o.QueryInterface <Output1>().DuplicateOutput(this.devices[i])); } catch (SharpDXException
                                                                                                          exception) when(exception.HResult ==
                                                                                                                          ResultCode.Unsupported.Result ||
                                                                                                                          exception.HResult == NotImplementedHResult)
                    {
                        throw new NotSupportedException("Platform is not supported");
                    }
                }
            })
                                .ToArray();
        }
Пример #14
0
        /// <summary>
        /// Function to perform an enumeration of the video devices attached to the system.
        /// </summary>
        /// <param name="enumerateWARPDevice">TRUE to enumerate the WARP software device.  FALSE to exclude it.</param>
        /// <param name="enumerateReferenceDevice">TRUE to enumerate the reference device.  FALSE to exclude it.</param>
        /// <remarks>This method will populate the <see cref="GorgonLibrary.Graphics.GorgonVideoDeviceEnumerator">GorgonVideoDeviceEnumerator</see> with information about the video devices
        /// installed in the system.
        /// <para>You may include the WARP device, which is a software based device that emulates most of the functionality of a video device, by setting the <paramref name="enumerateWARPDevice"/> to TRUE.</para>
        /// <para>You may include the reference device, which is a software based device that all the functionality of a video device, by setting the <paramref name="enumerateReferenceDevice"/> to TRUE.
        /// If a reference device is used in rendering, the performance will be poor and as such, this device is only useful to diagnosing issues with video drivers.</para>
        /// <para>The reference device is a DEBUG only device, and as such, it will only appear under the following conditions:
        /// <list type="bullet">
        ///		<item>
        ///			<description>The DEBUG version of the Gorgon library is used.</description>
        ///			<description>The Direct 3D SDK is installed.  The reference rasterizer is only included with the SDK.</description>
        ///		</item>
        /// </list>
        /// </para>
        /// </remarks>
        public static void Enumerate(bool enumerateWARPDevice, bool enumerateReferenceDevice)
        {
#if DEBUG
            // Turn on object tracking if it's not already enabled.
            if (!DX.Configuration.EnableObjectTracking)
            {
                DX.Configuration.EnableObjectTracking = true;
            }
#endif
            try
            {
                // Create the DXGI factory object used to gather the information.
                if (Interlocked.Increment(ref _lockIncr) > 1)
                {
                    return;
                }

                List <GorgonVideoDevice> devices;

                using (var factory = new Factory1())
                {
                    int adapterCount = factory.GetAdapterCount1();

                    devices = new List <GorgonVideoDevice>(adapterCount + 2);

                    Gorgon.Log.Print("Enumerating video devices...", LoggingLevel.Simple);

                    // Begin gathering device information.
                    for (int i = 0; i < adapterCount; i++)
                    {
                        // Get the video device information.
                        using (var adapter = factory.GetAdapter1(i))
                        {
                            // Only enumerate local devices.
                            int outputCount = adapter.GetOutputCount();

                            if (((adapter.Description1.Flags & AdapterFlags.Remote) != 0) || (outputCount <= 0))
                            {
                                continue;
                            }

                            var videoDevice = new GorgonVideoDevice(adapter, VideoDeviceType.Hardware, i);

                            // Don't allow unsupported devices.
                            if (videoDevice.HardwareFeatureLevel == DeviceFeatureLevel.Unsupported)
                            {
                                continue;
                            }

                            // We create a D3D device here to filter out unsupported video modes from the format list.
                            using (var D3DDevice = new D3D.Device(adapter))
                            {
                                D3DDevice.DebugName = "Output enumerator device.";
                                PrintLog(videoDevice);

                                GetOutputs(videoDevice, D3DDevice, adapter, outputCount, false);

                                // Ensure we actually have outputs to use.
                                if (videoDevice.Outputs.Count > 0)
                                {
                                    devices.Add(videoDevice);
                                }
                                else
                                {
                                    Gorgon.Log.Print("Video device {0} has no outputs!",
                                                     LoggingLevel.Verbose, videoDevice.Name);
                                }
                            }
                        }
                    }

                    // Get software devices.
                    if (enumerateWARPDevice)
                    {
                        var device = GetWARPSoftwareDevice(devices.Count);

                        if (device.Outputs.Count > 0)
                        {
                            devices.Add(device);
                        }
                    }

#if DEBUG
                    if (enumerateReferenceDevice)
                    {
                        var device = GetRefSoftwareDevice(devices.Count);

                        if (device.Outputs.Count > 0)
                        {
                            devices.Add(device);
                        }
                    }
#endif
                }

                VideoDevices = new GorgonNamedObjectReadOnlyCollection <GorgonVideoDevice>(false, devices);

                if (devices.Count == 0)
                {
                    throw new GorgonException(GorgonResult.CannotEnumerate, Resources.GORGFX_DEVICE_CANNOT_FIND_DEVICES);
                }

                Gorgon.Log.Print("Found {0} video devices.", LoggingLevel.Simple, VideoDevices.Count);
            }
            finally
            {
                Interlocked.Decrement(ref _lockIncr);
            }
        }