/// <summary> /// Acquires a frame from the desktop duplication instance with the specified index /// </summary> /// <param name="index">Index of the desktop duplication instance</param> private void AcquireFrame(int index) { OutputDuplicateFrameInformation info; Resource desktopResource = null; OutputDuplication duplication = this.duplications[index]; do { // release previous frame if last capture attempt failed if (desktopResource != null) { desktopResource.Dispose(); duplication.ReleaseFrame(); } // try to capture a frame duplication.AcquireNextFrame(DuplicationFrameTimeout, out info, out desktopResource); } while (info.TotalMetadataBufferSize == 0); LastPresentTime = info.LastPresentTime; this.devices[index] .ImmediateContext.CopySubresourceRegion(desktopResource.QueryInterface <SharpDX.Direct3D11.Resource>(), 0, this.regions[index], StagingTextures[index], 0); // release resources desktopResource.Dispose(); duplication.ReleaseFrame(); }
private bool RetrieveFrame() { if (_desktopImageTexture == null) { _desktopImageTexture = new Texture2D(_mDevice, _mTextureDesc); } Resource desktopResource = null; _frameInfo = new OutputDuplicateFrameInformation(); try { _mDeskDupl.AcquireNextFrame(500, out _frameInfo, out desktopResource); } catch (SharpDXException ex) { if (ex.ResultCode.Code == ResultCode.WaitTimeout.Result.Code) { return(true); } if (ex.ResultCode.Failure) { //return true; desktopResource?.Dispose(); throw new DesktopDuplicationException("Failed to acquire next frame."); } } using (var tempTexture = desktopResource?.QueryInterface <Texture2D>()) { _mDevice.ImmediateContext.CopyResource(tempTexture, _desktopImageTexture); } desktopResource?.Dispose(); return(false); }
/// <inheritdoc /> /// <summary> /// Acquires a single frame /// </summary> /// <inheritdoc /> /// <summary> /// Acquires a single frame from this provider /// </summary> public override void AcquireFrame() { for (int i = 0; i < this.sources.Length; i++) { DxgiCaptureSource source = this.sources[i]; try { OutputDuplicateFrameInformation info; Resource desktopResource = null; do { // release previous frame if last capture attempt failed if (desktopResource != null) { desktopResource.Dispose(); source.Duplication.ReleaseFrame(); } // try to capture a frame source.Duplication.AcquireNextFrame(DuplicationFrameTimeout, out info, out desktopResource); } while (info.TotalMetadataBufferSize == 0); this.lastPresentTime = info.LastPresentTime; using (var srcResource = desktopResource.QueryInterface <SharpDX.Direct3D11.Resource>()) using (var destResource = source.Texture.QueryInterface <SharpDX.Direct3D11.Resource>()) { // copy the entire screen region to the target texture source.Context.CopySubresourceRegion( srcResource, 0, source.Subregion, destResource, 0); } // release resources desktopResource.Dispose(); source.Duplication.ReleaseFrame(); } catch (SharpDXException exception) when(exception.ResultCode == ResultCode.AccessLost || exception.ResultCode == ResultCode.DeviceHung || exception.ResultCode == ResultCode.DeviceRemoved) { // device has been lost - we can't ignore this and should try to reinitialize the D3D11 device until it's // available again (...) // we'll be receiving black/unsynced frames beyond this point - it is OK until we restore the device while (true) { try { this.sources[i] = DxgiCaptureSource.Recreate(this.virtualRect); break; // successfully restored capture source } catch (SharpDXException) { /* could not restore the capture source - keep trying */ } } } } }
private bool RetrieveFrame() { if (desktopImageTexture == null) { desktopImageTexture = new Texture2D(mDevice, mTextureDesc); } SharpDX.DXGI.Resource desktopResource = null; frameInfo = new OutputDuplicateFrameInformation(); try { if (mDeskDupl == null) { return(true); } mDeskDupl.AcquireNextFrame(-1, out frameInfo, out desktopResource); } catch (SharpDXException ex) { if (ex.ResultCode.Code == SharpDX.DXGI.ResultCode.WaitTimeout.Result.Code) { return(true); } if (ex.ResultCode.Failure) { throw new DesktopDuplicationException("Failed to acquire next frame."); } } using (var tempTexture = desktopResource.QueryInterface <Texture2D>()) mDevice.ImmediateContext.CopyResource(tempTexture, desktopImageTexture); desktopResource.Dispose(); return(false); }
internal bool Snap(BitmapData bitmap, int timeout) { ThrowIfDisposed(); SharpDX.DXGI.Resource screenResource = null; var acquiredFrame = false; try { try { OutputDuplicateFrameInformation dfi; _duplicatedOutput.AcquireNextFrame(timeout, out dfi, out screenResource); acquiredFrame = true; } catch (SharpDXException e) when(e.ResultCode.Code == SharpDX.DXGI.ResultCode.WaitTimeout.Result.Code) { return(false); } using (var queryInterface = screenResource.QueryInterface <SharpDX.Direct3D11.Resource>()) _device.ImmediateContext.CopyResource(queryInterface, _screenTexture); var databox = _device.ImmediateContext.MapSubresource(_screenTexture, 0, MapMode.Read, SharpDX.Direct3D11.MapFlags.None); Render(databox, bitmap); return(true); } finally { _device.ImmediateContext.UnmapSubresource(_screenTexture, 0); screenResource?.Dispose(); if (acquiredFrame) { _duplicatedOutput?.ReleaseFrame(); } } }
IntPtr GetSharedHandle(SharpDX.Direct3D10.Texture2D Texture) { SharpDX.DXGI.Resource resource = Texture.QueryInterface <SharpDX.DXGI.Resource>(); IntPtr result = resource.SharedHandle; resource.Dispose(); return(result); }
public void DisposeSnapshot() { //systemBitmap.Dispose(); //DeleteObject(hBitmap); screenResource.Dispose(); duplicatedOutput.ReleaseFrame(); device.ImmediateContext.UnmapSubresource(screenTexture, 0); }
public void ConstructRenderAndResource(double width, double height) { float dpiX, dpiY; this.GetDpi(out dpiX, out dpiY); D2D.RenderTargetProperties prop = new D2D.RenderTargetProperties( D2D.RenderTargetType.Default, new D2D.PixelFormat(DXGI.Format.B8G8R8A8_UNorm, D2D.AlphaMode.Premultiplied), dpiX, dpiY, D2D.RenderTargetUsage.None, D2D.FeatureLevel.Level_DEFAULT); D3D11.Texture2DDescription desc = new D3D11.Texture2DDescription(); desc.Width = (int)width; desc.Height = (int)height; desc.MipLevels = 1; desc.ArraySize = 1; desc.Format = DXGI.Format.B8G8R8A8_UNorm; desc.SampleDescription = new DXGI.SampleDescription(1, 0); desc.Usage = D3D11.ResourceUsage.Default; desc.BindFlags = D3D11.BindFlags.RenderTarget | D3D11.BindFlags.ShaderResource; desc.CpuAccessFlags = D3D11.CpuAccessFlags.None; desc.OptionFlags = D3D11.ResourceOptionFlags.Shared; this.d3d11Texture = new D3D11.Texture2D(this.device, desc); this.surface = this.d3d11Texture.QueryInterface <DXGI.Surface>(); DXGI.Resource resource = this.d3d11Texture.QueryInterface <DXGI.Resource>(); IntPtr handel = resource.SharedHandle; D3D9.Texture texture = new D3D9.Texture( this.device9, this.d3d11Texture.Description.Width, this.d3d11Texture.Description.Height, 1, D3D9.Usage.RenderTarget, D3D9.Format.A8R8G8B8, D3D9.Pool.Default, ref handel); this.surface9 = texture.GetSurfaceLevel(0); resource.Dispose(); texture.Dispose(); D2D.BitmapProperties bmpProp = new D2D.BitmapProperties(); bmpProp.DpiX = dpiX; bmpProp.DpiY = dpiY; bmpProp.PixelFormat = new D2D.PixelFormat(DXGI.Format.B8G8R8A8_UNorm, D2D.AlphaMode.Premultiplied); this.bmpd2d = new D2D.Bitmap(this.render, this.surface, bmpProp); this.cachedBitMap = new D2D.Bitmap(this.render, new Size2((int)width, (int)height), bmpProp); this.hasCache = false; this.render.Target = this.bmpd2d; this.renderSize = new Size(width, height); }
private void GetDirtyAndMoveRects(ref FrameData data, Resource screenResource, OutputDuplicateFrameInformation duplicateFrameInformation) { //copy resource into memory that can be accessed by the CPU using (var screenTexture2D = screenResource.QueryInterface <Texture2D>()) device.ImmediateContext.CopyResource(screenTexture2D, screenTexture); screenResource.Dispose(); int bufSize = duplicateFrameInformation.TotalMetadataBufferSize; if (bufSize <= 0) { return; } var moveRectangles = new OutputDuplicateMoveRectangle [ (int) Math.Ceiling((double)bufSize / Marshal.SizeOf(typeof(OutputDuplicateMoveRectangle))) ]; Console.WriteLine("Move : {0} {1} {2} {3}", moveRectangles.Length, bufSize, Marshal.SizeOf(typeof(OutputDuplicateMoveRectangle)), bufSize / Marshal.SizeOf(typeof(OutputDuplicateMoveRectangle))); //get move rects if (moveRectangles.Length > 0) { duplicatedOutput.GetFrameMoveRects(bufSize, moveRectangles, out bufSize); } data.MoveRectangles = moveRectangles; data.MoveCount = bufSize; bufSize = duplicateFrameInformation.TotalMetadataBufferSize - bufSize; var dirtyRectangles = new Rectangle[bufSize / Marshal.SizeOf(typeof(Rectangle))]; Console.WriteLine("Dirty : {0} {1} {2} {3}", dirtyRectangles.Length, bufSize, Marshal.SizeOf(typeof(Rectangle)), bufSize / Marshal.SizeOf(typeof(Rectangle))); //get dirty rects if (dirtyRectangles.Length > 0) { duplicatedOutput.GetFrameDirtyRects(bufSize, dirtyRectangles, out bufSize); } data.DirtyRectangles = dirtyRectangles; data.DirtyCount = bufSize; data.Frame = screenTexture; data.FrameInfo = duplicateFrameInformation; }
private void D3DImage_OnRender(IntPtr surface, bool isNewSurface) { if (isNewSurface) { Context.DestroyBuffers(); // Yikes - from https://github.com/microsoft/WPFDXInterop/blob/master/samples/D3D11Image/D3D11Visualization/D3DVisualization.cpp#L384 ComObject res = ComObject.FromPointer <ComObject>(surface); SharpDX.DXGI.Resource resource = res.QueryInterface <SharpDX.DXGI.Resource>(); IntPtr sharedHandle = resource.SharedHandle; resource.Dispose(); SharpDX.Direct3D11.Resource d3dres = Context.Device.OpenSharedResource <SharpDX.Direct3D11.Resource>(sharedHandle); Context.UpdateSize(RenderWidth, RenderHeight, (int width, int height) => d3dres.QueryInterface <Texture2D>()); d3dres.Dispose(); } Context.UpdateScene(0.1f); // TODO: Measure elapsed time! Context.RenderScene(); Render?.Invoke(this, new EventArgs()); Context.ImmediateContext.Flush(); }
public void Dispose() { if (pinnedMemBuffer.IsAllocated) { pinnedMemBuffer.Free(); } TryReleaseFrame(); if (Settings.SettingsHwnd != IntPtr.Zero) // restore window background color { try { device?.ImmediateContext.ClearRenderTargetView(renderTarget, SharpDX.Color.WhiteSmoke); renderWindow?.Present(0, PresentFlags.None); } catch { } } Settings.Model.PropertyChanged -= LedsChanged; fpsCounter?.Dispose(); fpsColor?.Dispose(); fpsFont?.Dispose(); renderOverlay?.Dispose(); renderTarget?.Dispose(); renderTexture?.Dispose(); renderWindow?.Dispose(); try { device?.ImmediateContext?.ClearState(); device?.ImmediateContext?.Flush(); device?.ImmediateContext?.Dispose(); } catch { } adapter?.Dispose(); output?.Dispose(); device?.Dispose(); duplicator?.Dispose(); capture?.Dispose(); scaler?.Dispose(); gpuTexture?.Dispose(); cpuTexture?.Dispose(); }
private void RenderLoop() { while (!threadStop) { SharpDX.DXGI.Resource resource = screenCapture.AcquireFrame(); if (resource == null && OnScreenCaptured != null) { OnScreenCaptured(null, 0, 0, 0); continue; } Texture2D original = resource.QueryInterface <Texture2D>(); cDev.context.CopySubresourceRegion(original, 0, null, mipTexture, 0, 0, 0, 0); original.Dispose(); resource.Dispose(); screenCapture.ReleaseFrame(); cDev.context.GenerateMips(mipView); float scale = topPosition - bottomPosition; float offset = topPosition + bottomPosition - 1f; cDev.context.ClearRenderTargetView(intermediateView, Color4.Black); passThroughFilter.Apply(cDev.context, mipView, intermediateView, scale, offset); cDev.context.CopyResource(intermediateTexture, cpuTexture); cDev.context.ClearRenderTargetView(cDev.renderView, Color.Black); passThroughFilter.Apply(cDev.context, mipView, cDev.renderView, 1f, 0f); cDev.Present(); DataStream stream; DataBox dataBox = cDev.context.MapSubresource(cpuTexture, 0, MapMode.Read, SharpDX.Direct3D11.MapFlags.None, out stream); int count = dataBox.RowPitch / 16 * screenCaptureHeight; System.Numerics.Vector4[] pixels = stream.ReadRange <System.Numerics.Vector4>(count); stream.Dispose(); cDev.context.UnmapSubresource(cpuTexture, 0); if (OnScreenCaptured != null) { OnScreenCaptured(pixels, screenCaptureWidth, screenCaptureHeight, dataBox.RowPitch / 16); } } }
public FragmentedImage Capture() { if (duplicatedOutput == null && !ResetOutputDuplicator()) { return(null); } OutputDuplicateFrameInformation frameInfo; SharpDX.DXGI.Resource screenResource = null; bool success = false; try { int frameDisposeFailures = 0; while (true) { try { screenResource = null; duplicatedOutput.AcquireNextFrame(10000, out frameInfo, out screenResource); if (frameInfo.AccumulatedFrames > 0) { if (screenResource == null) { Logger.Debug("screenResource was null in DxgiOutputDuplicator"); return(null); } // Copy the texture so we can access the pixel data of the copy using (Texture2D screenTexture2D = screenResource.QueryInterface <Texture2D>()) device.ImmediateContext.CopyResource(screenTexture2D, screenTexture); // Learn which rectangles moved OutputDuplicateMoveRectangle[] moveRects = GetMoveRectangles(); // Learn which rectangles were made dirty RawRectangle[] dirtyRects = GetDirtyRectangles(); FragmentedImage img = new FragmentedImage(new MovedImageFragment[moveRects.Length], new DirtyImageFragment[dirtyRects.Length]); int i = 0; foreach (OutputDuplicateMoveRectangle moveRect in moveRects) { img.movedFragments[i++] = new MovedImageFragment( moveRect.DestinationRect.Top , moveRect.DestinationRect.Right , moveRect.DestinationRect.Bottom , moveRect.DestinationRect.Left , moveRect.SourcePoint.X , moveRect.SourcePoint.Y); } // Get the desktop capture pixel data i = 0; DataBox mapSource = device.ImmediateContext.MapSubresource(screenTexture, 0, MapMode.Read, MapFlags.None); foreach (RawRectangle dirtyRect in dirtyRects) { Screenshot screenshot = new Screenshot(dirtyRect.Right - dirtyRect.Left, dirtyRect.Bottom - dirtyRect.Top, 32); IntPtr source = mapSource.DataPointer; source += dirtyRect.Top * mapSource.RowPitch; // Offset source to the correct row source += dirtyRect.Left * 4; // Offset source to the correct column int destOffset = 0; for (int y = dirtyRect.Top; y < dirtyRect.Bottom; y++) { Marshal.Copy(source, screenshot.Buffer, destOffset, screenshot.Stride); source += mapSource.RowPitch; destOffset += screenshot.Stride; } img.dirtyFragments[i++] = new DirtyImageFragment( dirtyRect.Top , dirtyRect.Right , dirtyRect.Bottom , dirtyRect.Left , screenshot); } device.ImmediateContext.UnmapSubresource(screenTexture, 0); //DebugDrawRects(screenshot, moveRects, dirtyRects); success = true; return(img); } } catch (SharpDXException e) { if (e.ResultCode.Code != SharpDX.DXGI.ResultCode.WaitTimeout.Result.Code) { throw e; } } finally { if (screenResource != null) { try { screenResource.Dispose(); duplicatedOutput.ReleaseFrame(); } catch { if (++frameDisposeFailures > 2) { throw; } ResetOutputDuplicator(); } } } } } finally { if (!success) { DestroyOutputDuplicator(); } } // TODO: Delete cursor drawing stuff. //{ // IntPtr dc = _renderSurface.GetDC(new RawBool(true)); // NativeMethods.SelectObject(_hdc, dc); // NativeMethods.BitBlt(dc, 0, 0, bounds.Right - bounds.Left // , bounds.Bottom - bounds.Top, _hdc, bounds.Left // , bounds.Top, System.Drawing.CopyPixelOperation.SourceCopy); // NativeMethods.CURSORINFO pci; // pci.cbSize = NativeMethods.SizeOfCursorInfo; // if (NativeMethods.GetCursorInfo(out pci) && pci.flags > 0) // NativeMethods.DrawIcon(dc, pci.ptScreenPos.X, pci.ptScreenPos.Y, pci.hCursor); // _renderSurface.ReleaseDC(); // return null; //} }
public ErrorCode TryGetScreenTexture(out Texture2D texture, int timeout = 0) { texture = null; ErrorCode Result = ErrorCode.Unexpected; if (!deviceReady) { return(ErrorCode.NotReady); } try { SharpDX.DXGI.Resource desktopResource = null; try { var acquireResult = deskDupl.TryAcquireNextFrame(timeout, out OutputDuplicateFrameInformation frameInfo, out desktopResource); if (acquireResult.Failure) { if (acquireResult == SharpDX.DXGI.ResultCode.WaitTimeout) { return(ErrorCode.Ok); } else { logger.Debug("result.Code " + acquireResult.Code); acquireResult.CheckError(); } } if (duplTexture != null) { duplTexture.Dispose(); duplTexture = null; } duplTexture = desktopResource.QueryInterface <Texture2D>(); #region Update regions info //var frameParams = GetFrameParams(frameInfo); /* * var moveRects = frameParams.MoveRects; * foreach (OutputDuplicateMoveRectangle moveRect in moveRects) * { * //... * var srcPoint = moveRect.SourcePoint; * GDI.Point point = new GDI.Point(srcPoint.X, srcPoint.Y); * * var destRect = moveRect.DestinationRect; * int x = destRect.Left; * int y = destRect.Top; * int width = destRect.Right - destRect.Left; * int height = destRect.Bottom - destRect.Top; * GDI.Rectangle rect = new GDI.Rectangle(x, y, width, height); * * logger.Debug("srcPoint " + point.ToString() + " destRect " + rect.ToString()); * } * var dirtyRects = frameParams.DirtyRects; * foreach (RawRectangle dirtyRect in dirtyRects) * { * int x = dirtyRect.Left; * int y = dirtyRect.Top; * int width = dirtyRect.Right - dirtyRect.Left; * int height = dirtyRect.Bottom - dirtyRect.Top; * GDI.Rectangle rect = new GDI.Rectangle(x, y, width, height); * } */ #endregion UpdateMouseInfo(frameInfo); device.ImmediateContext.CopyResource(duplTexture, screenTexture); device.ImmediateContext.Flush(); if (cursorInfo != null && cursorInfo.Visible && CaptureMouse) { screenTarget.BeginDraw(); //screenTarget.Clear(Color.Green); DrawCursor(screenTarget, cursorInfo); screenTarget.EndDraw(); } texture = screenTexture; //texture = duplTexture; Result = 0; } finally { if (desktopResource != null) { deskDupl.ReleaseFrame(); desktopResource.Dispose(); desktopResource = null; } } } catch (SharpDXException ex) { if (ex.ResultCode == SharpDX.DXGI.ResultCode.WaitTimeout) { return(0); } else { if (ex.ResultCode == SharpDX.DXGI.ResultCode.AccessLost || ex.ResultCode == SharpDX.DXGI.ResultCode.AccessDenied || ex.ResultCode == SharpDX.DXGI.ResultCode.DeviceReset || ex.ResultCode == SharpDX.DXGI.ResultCode.DeviceRemoved || ex.HResult == (int)NativeAPIs.HResult.E_ACCESSDENIED) { logger.Warn(ex.Descriptor.ToString()); Result = ErrorCode.AccessDenied; } else { logger.Error(ex); Result = ErrorCode.Unexpected; } } } return(Result); }
private byte[] ManagedCapture() { SharpDX.DXGI.Resource screenResource = null; OutputDuplicateFrameInformation duplicateFrameInformation; try { try { // Try to get duplicated frame within given time _duplicatedOutput.AcquireNextFrame(_frameCaptureTimeout, out duplicateFrameInformation, out screenResource); if (duplicateFrameInformation.LastPresentTime == 0 && _lastCapturedFrame != null) { return(_lastCapturedFrame); } } catch (SharpDXException ex) { if (ex.ResultCode.Code == SharpDX.DXGI.ResultCode.WaitTimeout.Code && _lastCapturedFrame != null) { return(_lastCapturedFrame); } if (ex.ResultCode.Code == SharpDX.DXGI.ResultCode.AccessLost.Code) { _desktopDuplicatorInvalid = true; } throw ex; } // Check if scaling is used if (CaptureWidth != _width) { // Copy resource into memory that can be accessed by the CPU using (var screenTexture2D = screenResource.QueryInterface <Texture2D>()) _device.ImmediateContext.CopySubresourceRegion(screenTexture2D, 0, null, _smallerTexture, 0); // Generates the mipmap of the screen _device.ImmediateContext.GenerateMips(_smallerTextureView); // Copy the mipmap of smallerTexture (size/ scalingFactor) to the staging texture: 1 for /2, 2 for /4...etc _device.ImmediateContext.CopySubresourceRegion(_smallerTexture, _scalingFactorLog2, null, _stagingTexture, 0); } else { // Copy resource into memory that can be accessed by the CPU using (var screenTexture2D = screenResource.QueryInterface <Texture2D>()) _device.ImmediateContext.CopyResource(screenTexture2D, _stagingTexture); } // Get the desktop capture texture var mapSource = _device.ImmediateContext.MapSubresource(_stagingTexture, 0, MapMode.Read, SharpDX.Direct3D11.MapFlags.None); _lastCapturedFrame = ToRGBArray(mapSource); return(_lastCapturedFrame); } finally { screenResource?.Dispose(); // Fixed OUT_OF_MEMORY issue on AMD Radeon cards. Ignoring all exceptions during unmapping. try { _device.ImmediateContext.UnmapSubresource(_stagingTexture, 0); } catch { }; // Ignore DXGI_ERROR_INVALID_CALL, DXGI_ERROR_ACCESS_LOST errors since capture is already complete try { _duplicatedOutput.ReleaseFrame(); } catch { } } }
/* Код взят с: * https://github.com/sharpdx/SharpDX-Samples/blob/master/Desktop/Direct3D11.1/ScreenCapture/Program.cs * https://github.com/fabsenet/adrilight/blob/master/adrilight/DesktopDuplication/DesktopDuplicator.cs метод ProcessFrame */ public Bitmap GetFrame() { SharpDX.DXGI.Resource desktopResource = null; var frameInfo = new OutputDuplicateFrameInformation(); // Try to get duplicated frame within given time try { outputDuplication.AcquireNextFrame(500, out frameInfo, out desktopResource); } catch (SharpDXException ex) { if (ex.ResultCode.Code == SharpDX.DXGI.ResultCode.WaitTimeout.Result.Code) { return(null); } MessageBox.Show("Невозможно обработать SharpDXException", "Ошибка"); return(null); } // copy resource into memory that can be accessed by the CPU using (var tempTexture = desktopResource.QueryInterface <Texture2D>()) { device.ImmediateContext.CopyResource(tempTexture, desktopImageTexture); } desktopResource.Dispose(); // Get the desktop capture texture var mapSource = device.ImmediateContext.MapSubresource(desktopImageTexture, 0, MapMode.Read, MapFlags.None); // Copy pixels from screen capture Texture to GDI bitmap BitmapData mapDest = image.LockBits(boundsRect, ImageLockMode.WriteOnly, image.PixelFormat); var sourcePtr = mapSource.DataPointer; var destPtr = mapDest.Scan0; if (mapSource.RowPitch == mapDest.Stride) { // Fast copy Utilities.CopyMemory(destPtr, sourcePtr, height * mapDest.Stride); } else { // Safe copy 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 image.UnlockBits(mapDest); device.ImmediateContext.UnmapSubresource(desktopImageTexture, 0); desktopResource.Dispose(); outputDuplication.ReleaseFrame(); return(image); }
private Bitmap GetDX11ScreenShot() { try { screenShot = null; screenShot = new Bitmap(WIDTH, HEIGHT, this.pixelFormat); if (dx11DuplicatedOutput != null) { dx11DuplicatedOutput.AcquireNextFrame(NEXT_FRAME_TIMEOUT, out dx11DuplFrameInfo, out dx11ScreenResource); dx11Device.ImmediateContext .CopyResource(dx11ScreenResource.QueryInterface <SharpDX.Direct3D11.Resource>(), dx11ScreenTexture); // cast from texture to surface, so we can access its bytes dx11ScreenSurface = dx11ScreenTexture.QueryInterface <SharpDX.DXGI.Surface>(); // map the resource to access it dx11Map = dx11ScreenSurface.Map(SharpDX.DXGI.MapFlags.Read); bmpData = screenShot.LockBits(boundsRect, ImageLockMode.WriteOnly, screenShot.PixelFormat); var sourcePtr = dx11Map.DataPointer; var destPtr = bmpData.Scan0; for (int y = 0; y < HEIGHT; y++) { // Copy a single line Utilities.CopyMemory(destPtr, sourcePtr, ARGB_WIDTH); // Advance pointers sourcePtr = IntPtr.Add(sourcePtr, dx11Map.Pitch); destPtr = IntPtr.Add(destPtr, bmpData.Stride); } dx11Device.ImmediateContext.UnmapSubresource(dx11ScreenTexture, 0); screenShot.UnlockBits(bmpData); dx11ScreenSurface.Unmap(); dx11ScreenSurface.Dispose(); dx11ScreenResource.Dispose(); dx11DuplicatedOutput.ReleaseFrame(); } else { return(screenShot = null); } dx11ScreenSurface = null; bmpData = null; GC.Collect(); return(screenShot); } catch (SharpDX.SharpDXException e) { if (e.ResultCode.Code == SharpDX.DXGI.ResultCode.WaitTimeout.Result.Code) { //screen does not changed LdpLog.Warning("DX11 surface timeout.. Recursion is coming:)"); return(GetDX11ScreenShot()); } else { return(screenShot = null); } } catch (Exception ex) { LdpLog.Error("GetDX11ScreenShot\n" + ex.Message); return(screenShot = null); } }
public override async Task Run() { await base.Run(); bool captureDone = false; while (!captureDone) { SharpDX.DXGI.Resource screenResource = null; OutputDuplicateFrameInformation duplicateFrameInformation; try { // Try to get duplicated frame within given time duplicatedOutput.AcquireNextFrame(targetCaptureTime, out duplicateFrameInformation, out screenResource); // 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); var boundsRect = new Rectangle(0, 0, width / Zoom, height / Zoom); await Task.Run(() => { int nWidth = width / Zoom; int nHeight = height / Zoom; int middleX = (int)mousePos.X - nWidth / 2; int startX = Math.Max(Math.Min(middleX, width - nWidth - 1), 0); int middleY = (int)mousePos.Y - nHeight / 2; int startY = Math.Max(Math.Min(middleY, height - nHeight - 1), 0); try { // Create Drawing.Bitmap var bitmap = new Bitmap(nWidth, nHeight, PixelFormat.Format32bppArgb); // 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; sourcePtr = IntPtr.Add(sourcePtr, mapSource.RowPitch *startY + startX * 4); for (int y = startY; y < nHeight + startY && y < height; y++) { // Copy a single line Utilities.CopyMemory(destPtr, sourcePtr, nWidth * 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); // Save the output Display = (Bitmap)bitmap.Clone(); // Capture done captureDone = true; } catch (Exception e) { targetCaptureTime++; } }); } catch (SharpDXException e) { if (e.ResultCode.Code != SharpDX.DXGI.ResultCode.WaitTimeout.Result.Code) { throw e; } else { targetCaptureTime++; } } finally { if (screenResource != null) { screenResource.Dispose(); screenResource = null; duplicatedOutput.ReleaseFrame(); } } } }
public System.Drawing.Bitmap Capture() { isInCapture = true; try { // init bool captureDone = false; bitmap = new System.Drawing.Bitmap(captureRect.Width, captureRect.Height, PixelFormat.Format32bppArgb); // the capture needs some time for (int i = 0; !captureDone; i++) { try { //capture duplicatedOutput.AcquireNextFrame(-1, out duplicateFrameInformation, out screenResource); // only for wait if (i > 0) { using (var screenTexture2D = screenResource.QueryInterface <Texture2D>()) device.ImmediateContext.CopyResource(screenTexture2D, screenTexture); mapSource = device.ImmediateContext.MapSubresource(screenTexture, 0, MapMode.Read, MapFlags.None); mapDest = bitmap.LockBits(new System.Drawing.Rectangle(0, 0, captureRect.Width, captureRect.Height), ImageLockMode.WriteOnly, bitmap.PixelFormat); sourcePtr = mapSource.DataPointer; destPtr = mapDest.Scan0; // set x position offset to rect.x int rowPitch = mapSource.RowPitch - offsetX; // set pointer to y position sourcePtr = IntPtr.Add(sourcePtr, mapSource.RowPitch * captureRect.Y); for (int y = 0; y < captureRect.Height; y++) // needs to speed up!! { // set pointer to x position sourcePtr = IntPtr.Add(sourcePtr, offsetX); // copy pixel to bmp Utilities.CopyMemory(destPtr, sourcePtr, pWidth); // incement pointert to next line sourcePtr = IntPtr.Add(sourcePtr, rowPitch); destPtr = IntPtr.Add(destPtr, mapDest.Stride); } bitmap.UnlockBits(mapDest); device.ImmediateContext.UnmapSubresource(screenTexture, 0); captureDone = true; } screenResource.Dispose(); duplicatedOutput.ReleaseFrame(); } catch//(Exception ex) // catch (SharpDXException e) { //if (e.ResultCode.Code != SharpDX.DXGI.ResultCode.WaitTimeout.Result.Code) //{ // // throw e; //} return(new Bitmap(captureRect.Width, captureRect.Height, PixelFormat.Format32bppArgb)); } } } catch { return(new Bitmap(captureRect.Width, captureRect.Height, PixelFormat.Format32bppArgb)); } isInCapture = false; return(bitmap); }
private static void CaptureMain(Int32 adapterIndex, Int32 displayIndex) { Resource screenResource = null; try { using (Factory1 factory1 = new Factory1()) { using (Adapter1 adapter1 = factory1.GetAdapter1(adapterIndex)) { using (Device device = new Device(adapter1)) { using (Output output = adapter1.GetOutput(displayIndex)) { using (Output1 output1 = output.QueryInterface <Output1>()) { Int32 width = output1.Description.DesktopBounds.Right - output1.Description.DesktopBounds.Left; Int32 height = output1.Description.DesktopBounds.Bottom - output1.Description.DesktopBounds.Top; Rectangle bounds = new Rectangle(Point.Empty, new Size(width, height)); Texture2DDescription texture2DDescription = 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 }; using (Texture2D texture2D = new Texture2D(device, texture2DDescription)) { using (OutputDuplication outputDuplication = output1.DuplicateOutput(device)) { status = Status.Active; Int32 frameNumber = 0; do { try { Result result = outputDuplication.TryAcquireNextFrame(100, out _, out screenResource); if (result.Success) { frameNumber += 1; using (Texture2D screenTexture2D = screenResource.QueryInterface <Texture2D>()) { device.ImmediateContext.CopyResource(screenTexture2D, texture2D); DataBox dataBox = device.ImmediateContext.MapSubresource(texture2D, 0, MapMode.Read, MapFlags.None); Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppRgb); BitmapData bitmapData = bitmap.LockBits(bounds, ImageLockMode.WriteOnly, bitmap.PixelFormat); IntPtr dataBoxPointer = dataBox.DataPointer; IntPtr bitmapDataPointer = bitmapData.Scan0; for (Int32 y = 0; y < height; y++) { Utilities.CopyMemory(bitmapDataPointer, dataBoxPointer, width * 4); dataBoxPointer = IntPtr.Add(dataBoxPointer, dataBox.RowPitch); bitmapDataPointer = IntPtr.Add(bitmapDataPointer, bitmapData.Stride); } bitmap.UnlockBits(bitmapData); device.ImmediateContext.UnmapSubresource(texture2D, 0); while (SkipFrames && bitmapQueue.Count > 1) { bitmapQueue.TryDequeue(out Bitmap dequeuedBitmap); dequeuedBitmap.Dispose(); } if (frameNumber > 1 || SkipFirstFrame == false) { bitmapQueue.Enqueue(bitmap); waitHandle.Set(); } } } else { if (ResultDescriptor.Find(result).ApiCode != Result.WaitTimeout.ApiCode) { result.CheckError(); } } } finally { screenResource?.Dispose(); try { outputDuplication.ReleaseFrame(); } catch { } } } while (status == Status.Active); } } } } } } } } catch (Exception exception) { globalException = exception; status = Status.Stops; } finally { callbackThread.Join(); Exception exception = globalException; while (bitmapQueue.Count > 0) { bitmapQueue.TryDequeue(out Bitmap dequeuedBitmap); dequeuedBitmap.Dispose(); } globalException = null; waitHandle = null; bitmapQueue = null; captureThread = null; callbackThread = null; status = Status.Inactive; if (OnCaptureStop != null) { OnCaptureStop(null, new OnCaptureStopEventArgs(exception != null ? new Exception(exception.Message, exception) : null)); } else { if (exception != null) { ExceptionDispatchInfo.Capture(exception).Throw(); } } } }