Beispiel #1
0
        public static DXGI_MODE_DESC1?FindClosestMatchingMode1(this IDXGIOutput1 output, DXGI_MODE_DESC1 modeToMatch, object concernedDevice)
        {
            if (output == null)
            {
                throw new ArgumentNullException(nameof(output));
            }

            var closest = new DXGI_MODE_DESC1();

            if (output.FindClosestMatchingMode1(ref modeToMatch, out closest, ComObject.Unwrap(concernedDevice)).IsError)
            {
                return(null);
            }

            return(closest);
        }
Beispiel #2
0
        public static ComObject <IDXGIOutputDuplication> DuplicateOutput(this IDXGIOutput1 output, object device, bool throwOnError = true)
        {
            if (output == null)
            {
                throw new ArgumentNullException(nameof(output));
            }

            if (device == null)
            {
                throw new ArgumentNullException(nameof(device));
            }

            device = ComObject.Unwrap(device);

            // this wonderful magic (mess) is because of a horrible bug in DXGI
            // https://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/0c28328a-100a-4d6f-9a08-44a452d3ca6a/idxgioutputduplication-implementation-bug?forum=windowssdk#0c28328a-100a-4d6f-9a08-44a452d3ca6a
            output.DuplicateOutput(device, out var unk).ThrowOnError(throwOnError);
            if (unk == IntPtr.Zero)
            {
                return(null);
            }

            // we copy the original COM's vtable to our process
            var vtablePtr = Marshal.ReadIntPtr(unk);
            var vtable    = new IDXGIOutputDuplicationVTable();

            Marshal.PtrToStructure(vtablePtr, vtable);

            // patch QueryInterface so it works (route to our code)
            var wrapper = new Wrapper(unk);

            vtable.QueryInterfacePtr = Marshal.GetFunctionPointerForDelegate <QueryInterfaceFn>(wrapper.QueryInterface);
            using (var newVtablePtr = new ComMemory(Marshal.SizeOf <IDXGIOutputDuplicationVTable>()))
            {
                Marshal.StructureToPtr(vtable, newVtablePtr.Pointer, false);

                // create a new vtable for the CLR
                using (var newUnk = new ComMemory(IntPtr.Size))
                {
                    Marshal.WriteIntPtr(newUnk.Pointer, newVtablePtr.Pointer);

                    var dup = (IDXGIOutputDuplication)Marshal.GetObjectForIUnknown(newUnk.Pointer);
                    return(new ComObject <IDXGIOutputDuplication>(dup));
                }
            }
        }