private static void PlatformInitializeAdapters(out ReadOnlyCollection <GraphicsAdapter> adapters) { var factory = new SharpDX.DXGI.Factory1(); var adapterCount = factory.GetAdapterCount(); var adapterList = new List <GraphicsAdapter>(adapterCount); for (var i = 0; i < adapterCount; i++) { var device = factory.GetAdapter1(i); var monitorCount = device.GetOutputCount(); for (var j = 0; j < monitorCount; j++) { var monitor = device.GetOutput(j); var adapter = CreateAdapter(device, monitor); adapterList.Add(adapter); monitor.Dispose(); } } factory.Dispose(); adapters = new ReadOnlyCollection <GraphicsAdapter>(adapterList); }
public void TestDXGI() { // Force to load DXGI assembly var factory = new Factory1(); factory.Dispose(); // Look for DXGI descriptor SharpDX.DXGI.ResultCode.DeviceRemoved var descriptor = ResultDescriptor.Find(0x887A0005); Assert.AreEqual(descriptor.NativeApiCode, "DXGI_ERROR_DEVICE_REMOVED"); }
public override void Dispose() { if (dx11Device != null) { dx11Device.Dispose(); } if (dx11Factory != null) { dx11Factory.Dispose(); } if (dx11Output != null) { dx11Output.Dispose(); } if (dx11DuplicatedOutput != null) { dx11DuplicatedOutput.Dispose(); } if (dx11ScreenTexture != null) { dx11ScreenTexture.Dispose(); } if (dx11ScreenResource != null) { dx11ScreenResource.Dispose(); } if (dx11ScreenSurface != null) { dx11ScreenSurface.Dispose(); } if (screenShot != null) { screenShot.Dispose(); } dx11Device = null; dx11Factory = null; dx11Output = null; dx11DuplicatedOutput = null; dx11ScreenTexture = null; dx11ScreenResource = null; dx11ScreenSurface = null; screenShot = null; bmpData = null; GC.SuppressFinalize(this); }
public void Dispose() { d2dContext.Target = null; bitmap.Dispose(); d2dContext.Dispose(); d2dDevice.Dispose(); d2dFactory.Dispose(); dxgiSurface.Dispose(); swapChain.Dispose(); dxgiFactory.Dispose(); dxgiDevice.Dispose(); d3dDevice.Dispose(); form.Dispose(); }
public static Bitmap CaptureScreen() { // # of graphics card adapter const int numAdapter = 0; // # of output device (i.e. monitor) const int numOutput = 1; // Create DXGI Factory1 var factory = new Factory1(); var adapter = factory.GetAdapter1(numAdapter); // Create device from Adapter var device = new Device(adapter); // Get DXGI.Output var output = adapter.GetOutput(numOutput); var output1 = output.QueryInterface<Output1>(); // Width/Height of desktop to capture int width = ((Rectangle)output.Description.DesktopBounds).Width; //width = 1024; int height = ((Rectangle)output.Description.DesktopBounds).Height; //height = 1024; // Create Staging texture CPU-accessible var textureDesc = new Texture2DDescription { CpuAccessFlags = CpuAccessFlags.Read, BindFlags = BindFlags.None, Format = Format.B8G8R8A8_UNorm, Width = width, Height = height, OptionFlags = ResourceOptionFlags.None, MipLevels = 1, ArraySize = 1, SampleDescription = { Count = 1, Quality = 0 }, Usage = ResourceUsage.Staging }; var screenTexture = new Texture2D(device, textureDesc); // Duplicate the output var duplicatedOutput = output1.DuplicateOutput(device); bool captureDone = false; Bitmap bitmap = null; for (int i = 0; !captureDone; i++) { try { SharpDX.DXGI.Resource screenResource; OutputDuplicateFrameInformation duplicateFrameInformation; // Try to get duplicated frame within given time duplicatedOutput.AcquireNextFrame(10000, out duplicateFrameInformation, out screenResource); if (i > 0) { // copy resource into memory that can be accessed by the CPU using (var screenTexture2D = screenResource.QueryInterface<Texture2D>()) device.ImmediateContext.CopyResource(screenTexture2D, screenTexture); // Get the desktop capture texture var mapSource = device.ImmediateContext.MapSubresource(screenTexture, 0, MapMode.Read, MapFlags.None); // Create Drawing.Bitmap bitmap = new System.Drawing.Bitmap(width, height, PixelFormat.Format32bppArgb); var boundsRect = new System.Drawing.Rectangle(0, 0, width, height); // Copy pixels from screen capture Texture to GDI bitmap var mapDest = bitmap.LockBits(boundsRect, ImageLockMode.WriteOnly, bitmap.PixelFormat); var sourcePtr = mapSource.DataPointer; var destPtr = mapDest.Scan0; for (int y = 0; y < height; y++) { // Copy a single line Utilities.CopyMemory(destPtr, sourcePtr, width * 4); // Advance pointers sourcePtr = IntPtr.Add(sourcePtr, mapSource.RowPitch); destPtr = IntPtr.Add(destPtr, mapDest.Stride); } // Release source and dest locks bitmap.UnlockBits(mapDest); device.ImmediateContext.UnmapSubresource(screenTexture, 0); // Capture done captureDone = true; } screenResource.Dispose(); duplicatedOutput.ReleaseFrame(); } catch (SharpDXException e) { if (e.ResultCode.Code != SharpDX.DXGI.ResultCode.WaitTimeout.Result.Code) { throw e; } } } duplicatedOutput.Dispose(); screenTexture.Dispose(); output1.Dispose(); output.Dispose(); device.Dispose(); adapter.Dispose(); factory.Dispose(); return bitmap; }
public void Init() { logger.Debug("DesktopDuplicationManager::Init(...)"); CaptureMouse = true; this.AllScreensRect = SystemInformation.VirtualScreen; //var rawRect = new RawRectangle //{ // Left = AllScreensRect.Left, // Right = AllScreensRect.Right, // Top = AllScreensRect.Top, // Bottom = AllScreensRect.Bottom, //}; // SetupRegions(rawRect, ) SharpDX.DXGI.Factory1 dxgiFactory = null; Adapter1 adapter = null; Output output = null; try { dxgiFactory = new SharpDX.DXGI.Factory1(); logger.Info(MediaFoundation.DxTool.LogDxAdapters(dxgiFactory.Adapters1)); if (adapter == null) {// первым идет адаптер с которому подключен primary монитор adapter = dxgiFactory.GetAdapter1(0); } AdapterId = adapter.Description.Luid; //logger.Info("Screen source info: " + adapter.Description.Description + " " + output.Description.DeviceName); var deviceCreationFlags = //DeviceCreationFlags.Debug | DeviceCreationFlags.VideoSupport | DeviceCreationFlags.BgraSupport; device = new Device(adapter, deviceCreationFlags); using (var multiThread = device.QueryInterface <SharpDX.Direct3D11.Multithread>()) { multiThread.SetMultithreadProtected(true); } if (deskDupls != null) { //... } deskDupls = new List <_DesktopDuplicator>(); foreach (var _output in adapter.Outputs) { var descr = _output.Description; var desktopBounds = descr.DesktopBounds; var desktopRect = new GDI.Rectangle { X = desktopBounds.Left, Y = desktopBounds.Top, Width = desktopBounds.Right - desktopBounds.Left, Height = desktopBounds.Bottom - desktopBounds.Top, }; _DesktopDuplicator deskDupl = new _DesktopDuplicator(device); deskDupl.Init(_output, desktopRect); deskDupl.CaptureMouse = this.CaptureMouse; deskDupls.Add(deskDupl); //var rect = GDI.Rectangle.Intersect(desktopRect, SrcRect); //if (rect.Width > 0 && rect.Height > 0) //{ // logger.Info("Screen source info: " + adapter.Description.Description + " " + descr.DeviceName); // DesktopDuplicator deskDupl = new DesktopDuplicator(device); // deskDupl.Init(_output, SrcRect); // deskDupl.CaptureMouse = this.CaptureMouse; // deskDupls.Add(deskDupl); //} //else //{ // logger.Debug("No common area: " + descr.DeviceName + " " + SrcRect.ToString()); // continue; //} _output.Dispose(); } } finally { if (adapter != null) { adapter.Dispose(); adapter = null; } if (output != null) { output.Dispose(); output = null; } if (dxgiFactory != null) { dxgiFactory.Dispose(); dxgiFactory = null; } } compositionTexture = new Texture2D(device, new Texture2DDescription { CpuAccessFlags = CpuAccessFlags.None, BindFlags = BindFlags.ShaderResource, Format = Format.B8G8R8A8_UNorm, Width = AllScreensRect.Width, Height = AllScreensRect.Height, MipLevels = 1, ArraySize = 1, SampleDescription = { Count = 1, Quality = 0 }, Usage = ResourceUsage.Default, }); initialized = true; }
public void Dispose() { _swapChain?.Dispose(); _factory?.Dispose(); }
public void Run() { var form = new RenderForm("2d and 3d combined...it's like magic"); form.KeyDown += (sender, args) => { if (args.KeyCode == Keys.Escape) form.Close(); }; // DirectX DXGI 1.1 factory var factory1 = new Factory1(); // The 1st graphics adapter var adapter1 = factory1.GetAdapter1(0); // --------------------------------------------------------------------------------------------- // Setup direct 3d version 11. It's context will be used to combine the two elements // --------------------------------------------------------------------------------------------- var description = new SwapChainDescription { BufferCount = 1, ModeDescription = new ModeDescription(0, 0, new Rational(60, 1), Format.R8G8B8A8_UNorm), IsWindowed = true, OutputHandle = form.Handle, SampleDescription = new SampleDescription(1, 0), SwapEffect = SwapEffect.Discard, Usage = Usage.RenderTargetOutput, Flags = SwapChainFlags.AllowModeSwitch }; Device11 device11; SwapChain swapChain; Device11.CreateWithSwapChain(adapter1, DeviceCreationFlags.None, description, out device11, out swapChain); // create a view of our render target, which is the backbuffer of the swap chain we just created RenderTargetView renderTargetView; using (var resource = Resource.FromSwapChain<Texture2D>(swapChain, 0)) renderTargetView = new RenderTargetView(device11, resource); // setting a viewport is required if you want to actually see anything var context = device11.ImmediateContext; var viewport = new Viewport(0.0f, 0.0f, form.ClientSize.Width, form.ClientSize.Height); context.OutputMerger.SetTargets(renderTargetView); context.Rasterizer.SetViewports(viewport); // // Create the DirectX11 texture2D. This texture will be shared with the DirectX10 device. // // The DirectX10 device will be used to render text onto this texture. // DirectX11 will then draw this texture (blended) onto the screen. // The KeyedMutex flag is required in order to share this resource between the two devices. var textureD3D11 = new Texture2D(device11, new Texture2DDescription { Width = form.ClientSize.Width, Height = form.ClientSize.Height, MipLevels = 1, ArraySize = 1, Format = Format.B8G8R8A8_UNorm, SampleDescription = new SampleDescription(1, 0), Usage = ResourceUsage.Default, BindFlags = BindFlags.RenderTarget | BindFlags.ShaderResource, CpuAccessFlags = CpuAccessFlags.None, OptionFlags = ResourceOptionFlags.SharedKeyedmutex }); // --------------------------------------------------------------------------------------------- // Setup a direct 3d version 10.1 adapter // --------------------------------------------------------------------------------------------- var device10 = new Device10(adapter1, SharpDX.Direct3D10.DeviceCreationFlags.BgraSupport, FeatureLevel.Level_10_0); // --------------------------------------------------------------------------------------------- // Setup Direct 2d // --------------------------------------------------------------------------------------------- // Direct2D Factory var factory2D = new SharpDX.Direct2D1.Factory(FactoryType.SingleThreaded, DebugLevel.Information); // Here we bind the texture we've created on our direct3d11 device through the direct3d10 // to the direct 2d render target.... var sharedResource = textureD3D11.QueryInterface<SharpDX.DXGI.Resource>(); var textureD3D10 = device10.OpenSharedResource<SharpDX.Direct3D10.Texture2D>(sharedResource.SharedHandle); var surface = textureD3D10.AsSurface(); var rtp = new RenderTargetProperties { MinLevel = SharpDX.Direct2D1.FeatureLevel.Level_10, Type = RenderTargetType.Hardware, PixelFormat = new PixelFormat(Format.Unknown, AlphaMode.Premultiplied) }; var renderTarget2D = new RenderTarget(factory2D, surface, rtp); var solidColorBrush = new SolidColorBrush(renderTarget2D, Colors.Red); // --------------------------------------------------------------------------------------------------- // Setup the rendering data // --------------------------------------------------------------------------------------------------- // Load Effect. This includes both the vertex and pixel shaders. // Also can include more than one technique. ShaderBytecode shaderByteCode = ShaderBytecode.CompileFromFile( "effectDx11.fx", "fx_5_0", ShaderFlags.EnableStrictness); var effect = new Effect(device11, shaderByteCode); // create triangle vertex data, making sure to rewind the stream afterward var verticesTriangle = new DataStream(VertexPositionColor.SizeInBytes * 3, true, true); verticesTriangle.Write(new VertexPositionColor(new Vector3(0.0f, 0.5f, 0.5f),new Color4(1.0f, 0.0f, 0.0f, 1.0f))); verticesTriangle.Write(new VertexPositionColor(new Vector3(0.5f, -0.5f, 0.5f),new Color4(0.0f, 1.0f, 0.0f, 1.0f))); verticesTriangle.Write(new VertexPositionColor(new Vector3(-0.5f, -0.5f, 0.5f),new Color4(0.0f, 0.0f, 1.0f, 1.0f))); verticesTriangle.Position = 0; // create the triangle vertex layout and buffer var layoutColor = new InputLayout(device11, effect.GetTechniqueByName("Color").GetPassByIndex(0).Description.Signature, VertexPositionColor.inputElements); var vertexBufferColor = new Buffer(device11, verticesTriangle, (int)verticesTriangle.Length, ResourceUsage.Default, BindFlags.VertexBuffer, CpuAccessFlags.None, ResourceOptionFlags.None, 0); verticesTriangle.Close(); // create overlay vertex data, making sure to rewind the stream afterward // Top Left of screen is -1, +1 // Bottom Right of screen is +1, -1 var verticesText = new DataStream(VertexPositionTexture.SizeInBytes * 4, true, true); verticesText.Write(new VertexPositionTexture(new Vector3(-1, 1, 0),new Vector2(0, 0f))); verticesText.Write(new VertexPositionTexture(new Vector3(1, 1, 0),new Vector2(1, 0))); verticesText.Write(new VertexPositionTexture(new Vector3(-1, -1, 0),new Vector2(0, 1))); verticesText.Write(new VertexPositionTexture(new Vector3(1, -1, 0),new Vector2(1, 1))); verticesText.Position = 0; // create the overlay vertex layout and buffer var layoutOverlay = new InputLayout(device11, effect.GetTechniqueByName("Overlay").GetPassByIndex(0).Description.Signature, VertexPositionTexture.inputElements); var vertexBufferOverlay = new Buffer(device11, verticesText, (int)verticesText.Length, ResourceUsage.Default, BindFlags.VertexBuffer, CpuAccessFlags.None, ResourceOptionFlags.None, 0); verticesText.Close(); // Think of the shared textureD3D10 as an overlay. // The overlay needs to show the 2d content but let the underlying triangle (or whatever) // show thru, which is accomplished by blending. var bsd = new BlendStateDescription(); bsd.RenderTarget[0].IsBlendEnabled = true; bsd.RenderTarget[0].SourceBlend = BlendOption.SourceColor; bsd.RenderTarget[0].DestinationBlend = BlendOption.BlendFactor; bsd.RenderTarget[0].BlendOperation = BlendOperation.Add; bsd.RenderTarget[0].SourceAlphaBlend = BlendOption.One; bsd.RenderTarget[0].DestinationAlphaBlend = BlendOption.Zero; bsd.RenderTarget[0].AlphaBlendOperation = BlendOperation.Add; bsd.RenderTarget[0].RenderTargetWriteMask = ColorWriteMaskFlags.All; var blendStateTransparent = new BlendState(device11, bsd); // --------------------------------------------------------------------------------------------------- // Create and tesselate an ellipse // --------------------------------------------------------------------------------------------------- var center = new DrawingPointF(form.ClientSize.Width/2.0f, form.ClientSize.Height/2.0f); var ellipse = new EllipseGeometry(factory2D, new Ellipse(center, form.ClientSize.Width / 2.0f, form.ClientSize.Height / 2.0f)); // Populate a PathGeometry from Ellipse tessellation var tesselatedGeometry = new PathGeometry(factory2D); _geometrySink = tesselatedGeometry.Open(); // Force RoundLineJoin otherwise the tesselated looks buggy at line joins _geometrySink.SetSegmentFlags(PathSegment.ForceRoundLineJoin); // Tesselate the ellipse to our TessellationSink ellipse.Tessellate(1, this); _geometrySink.Close(); // --------------------------------------------------------------------------------------------------- // Acquire the mutexes. These are needed to assure the device in use has exclusive access to the surface // --------------------------------------------------------------------------------------------------- var device10Mutex = textureD3D10.QueryInterface<KeyedMutex>(); var device11Mutex = textureD3D11.QueryInterface<KeyedMutex>(); // --------------------------------------------------------------------------------------------------- // Main rendering loop // --------------------------------------------------------------------------------------------------- bool first = true; RenderLoop .Run(form, () => { if(first) { form.Activate(); first = false; } // clear the render target to black context.ClearRenderTargetView(renderTargetView, Colors.DarkSlateGray); // Draw the triangle context.InputAssembler.InputLayout = layoutColor; context.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList; context.InputAssembler.SetVertexBuffers(0, new VertexBufferBinding(vertexBufferColor, VertexPositionColor.SizeInBytes, 0)); context.OutputMerger.BlendState = null; var currentTechnique = effect.GetTechniqueByName("Color"); for (var pass = 0; pass < currentTechnique.Description.PassCount; ++pass) { using (var effectPass = currentTechnique.GetPassByIndex(pass)) { System.Diagnostics.Debug.Assert(effectPass.IsValid, "Invalid EffectPass"); effectPass.Apply(context); } context.Draw(3, 0); }; // Draw Ellipse on the shared Texture2D device10Mutex.Acquire(0, 100); renderTarget2D.BeginDraw(); renderTarget2D.Clear(Colors.Black); renderTarget2D.DrawGeometry(tesselatedGeometry, solidColorBrush); renderTarget2D.DrawEllipse(new Ellipse(center, 200, 200), solidColorBrush, 20, null); renderTarget2D.EndDraw(); device10Mutex.Release(0); // Draw the shared texture2D onto the screen, blending the 2d content in device11Mutex.Acquire(0, 100); var srv = new ShaderResourceView(device11, textureD3D11); effect.GetVariableByName("g_Overlay").AsShaderResource().SetResource(srv); context.InputAssembler.InputLayout = layoutOverlay; context.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleStrip; context.InputAssembler.SetVertexBuffers(0, new VertexBufferBinding(vertexBufferOverlay, VertexPositionTexture.SizeInBytes, 0)); context.OutputMerger.BlendState = blendStateTransparent; currentTechnique = effect.GetTechniqueByName("Overlay"); for (var pass = 0; pass < currentTechnique.Description.PassCount; ++pass) { using (var effectPass = currentTechnique.GetPassByIndex(pass)) { System.Diagnostics.Debug.Assert(effectPass.IsValid, "Invalid EffectPass"); effectPass.Apply(context); } context.Draw(4, 0); } srv.Dispose(); device11Mutex.Release(0); swapChain.Present(0, PresentFlags.None); }); // dispose everything vertexBufferColor.Dispose(); vertexBufferOverlay.Dispose(); layoutColor.Dispose(); layoutOverlay.Dispose(); effect.Dispose(); shaderByteCode.Dispose(); renderTarget2D.Dispose(); swapChain.Dispose(); device11.Dispose(); device10.Dispose(); textureD3D10.Dispose(); textureD3D11.Dispose(); factory1.Dispose(); adapter1.Dispose(); sharedResource.Dispose(); factory2D.Dispose(); surface.Dispose(); solidColorBrush.Dispose(); blendStateTransparent.Dispose(); device10Mutex.Dispose(); device11Mutex.Dispose(); }
public ScreenDublicator() { Adapter adapter = null; Output output = null; Output1 output1 = null; try { //Адаптер adapter = new Factory1().GetAdapter1(this.ADAPTER); //Устройство this._device = new Device(adapter); output = adapter.GetOutput(this.MONITOR); //Выход output1 = output.QueryInterface<Output1>(); this._outputDesc = output.Description; this._width = this._outputDesc.DesktopBounds.Right - this._outputDesc.DesktopBounds.Left; this._height = this._outputDesc.DesktopBounds.Bottom - this._outputDesc.DesktopBounds.Top; this._textureDesc = new Texture2DDescription() { CpuAccessFlags = CpuAccessFlags.Read, BindFlags = BindFlags.None, Format = Format.B8G8R8A8_UNorm, Width = this._width, Height = this._height, OptionFlags = ResourceOptionFlags.None, MipLevels = 1, ArraySize = 1, SampleDescription = { Count = 1, Quality = 0 }, Usage = ResourceUsage.Staging }; this._outputDublication = output1.DuplicateOutput(this._device); //Текстура this._desktopTexture = new Texture2D(this._device, this._textureDesc); } catch(SharpDXException sdxex) { if (sdxex.ResultCode.Code == SharpDX.DXGI.ResultCode.NotCurrentlyAvailable.Result.Code) { throw new ScreenDublicatorException("Достигнут предел приложений, работающих с API)"); } else { string message = String.Format("Не удалось создать дублирующий выход"); Debug.WriteLine(message + "\n{0}\n{1}", sdxex.Message, sdxex.StackTrace); throw new ScreenDublicatorException(message); } } catch(Exception ex) { string message = String.Format("Ошибка при инициализации объекта\n{0}\n{1}", ex.Message, ex.StackTrace); throw new ScreenDublicatorException(message); } finally { if(adapter != null) { adapter.Dispose(); } if(output != null) { output.Dispose(); } if(output1 != null) { output1.Dispose(); } } }