/// <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 void ProcessScreen(SharpDX.DXGI.Resource screenResource, int depth, int saturation) { try { using (var screenTexture2D = screenResource.QueryInterface <Texture2D>()) _wiring.Device.ImmediateContext.CopyResource(screenTexture2D, _wiring.Texture); var mapSource = _wiring.Device.ImmediateContext.MapSubresource(_wiring.Texture, 0, MapMode.Read, MapFlags.None); var sidePtr = mapSource.DataPointer; var tasks = new Task <int[, ]>[4] { ProcessHorizontal(mapSource.DataPointer, mapSource.RowPitch, depth, saturation), ProcessHorizontal(IntPtr.Add(mapSource.DataPointer, mapSource.RowPitch * (_wiring.Height - depth)), mapSource.RowPitch, depth, saturation), ProcessVertical(mapSource.DataPointer, mapSource.RowPitch, depth, saturation), ProcessVertical(IntPtr.Add(mapSource.DataPointer, _wiring.Width * 4 - depth * 4), mapSource.RowPitch, depth, saturation) }; Task.WaitAll(tasks); var messages = new List <RangeMessage>(); messages.AddRange(BuildHorizontalMessages(tasks[0].Result, Strip.Top)); messages.AddRange(BuildHorizontalMessages(tasks[1].Result, Strip.Bottom)); messages.AddRange(BuildVerticalMessages(tasks[2].Result, Strip.Left)); messages.AddRange(BuildVerticalMessages(tasks[3].Result, Strip.Right)); if (_running) { _packageHandler.SendRange(messages); } } finally { _wiring.Device.ImmediateContext.UnmapSubresource(_wiring.Texture, 0); } }
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); }
/// <summary> /// Gets the handle that can be used for resource sharing. /// </summary> /// <param name="Texture">The texture to be shared.</param> private IntPtr GetSharedHandle(D3D11.Texture2D Texture) { using (DXGI.Resource resource = Texture.QueryInterface <DXGI.Resource>()) { return(resource.SharedHandle); } }
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); }
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); }
/// <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(); }
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(); } } }
public (int x, int y) Capture() { while (true) { try { using (SharpDX.DXGI.Resource screenResource = BeginCapture(out var pointerPos)) { // 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); // Copy pixels from screen capture Texture to GDI bitmap var sourcePtr = mapSource.DataPointer; // Save the output if (SaveScreenshot) { using (Bitmap bmp = new Bitmap(width, height, PixelFormat.Format32bppArgb)) { var bmpData = bmp.LockBits(new System.Drawing.Rectangle(System.Drawing.Point.Empty, bmp.Size), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); unsafe { GPUColorBGRA *dst = (GPUColorBGRA *)bmpData.Scan0; GPUColorBGRA *src = (GPUColorBGRA *)sourcePtr; for (int i = 0; i < width * height; i++, dst++, src++) { *dst = *src; } } bmp.UnlockBits(bmpData); bmp.Save(OutputFileName); } } _gpu.CopyToDevice(sourcePtr, 0, rgbValues, 0, width * height); device.ImmediateContext.UnmapSubresource(screenTexture, 0); // Capture done duplicatedOutput.ReleaseFrame(); return(pointerPos.X, pointerPos.Y); }; } catch (SharpDXException e) { if (e.ResultCode.Code != SharpDX.DXGI.ResultCode.WaitTimeout.Result.Code) { throw e; } } } }
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 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; }
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); }
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(); }
private void CaptureFrame(object sender, DoWorkEventArgs ea) { SharpDX.DXGI.Resource screenResource = null; try { OutputDuplicateFrameInformation duplicateFrameInformation; // Try to get duplicated frame within given time this.duplicatedOutput.AcquireNextFrame(1000, out duplicateFrameInformation, out screenResource); // copy resource into memory that can be accessed by the CPU using (Texture2D screenTexture2D = screenResource.QueryInterface <Texture2D>()) device.ImmediateContext.CopyResource(screenTexture2D, screenTexture); DataBox mapSource = device.ImmediateContext.MapSubresource(screenTexture, 0, MapMode.Read, SharpDX.Direct3D11.MapFlags.None); int size = RLocalUtils.GetSizeBGRA(DisplayWidth, DisplayHeight); Marshal.Copy(mapSource.DataPointer, FrameBytes, 0, size); duplicatedOutput.ReleaseFrame(); } catch (SharpDXException e) { if (e.ResultCode.Code != SharpDX.DXGI.ResultCode.WaitTimeout.Result.Code) { throw e; } } catch (Exception e) { throw e; } framesCapped++; }
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); } } }
void RenderLoop() { while (true) { lock (renderLock) { var deviceContext = device.ImmediateContext; // render user view deviceContext.ClearRenderTargetView(userViewRenderTargetView, Color4.Black); deviceContext.ClearDepthStencilView(userViewDepthStencilView, DepthStencilClearFlags.Depth, 1, 0); SharpDX.Vector3 headPosition = new SharpDX.Vector3(0f, 1.1f, -1.4f); // may need to change this default if (localHeadTrackingEnabled) { float distanceSquared = 0; lock (headCameraSpacePointLock) { headPosition = new SharpDX.Vector3(headCameraSpacePoint.X, headCameraSpacePoint.Y, headCameraSpacePoint.Z); float dx = handLeftCameraSpacePoint.X - handRightCameraSpacePoint.X; float dy = handLeftCameraSpacePoint.Y - handRightCameraSpacePoint.Y; float dz = handLeftCameraSpacePoint.Z - handRightCameraSpacePoint.Z; distanceSquared = dx * dx + dy * dy + dz * dz; } var transform = SharpDX.Matrix.RotationY((float)Math.PI) * SharpDX.Matrix.Translation(0, 0.45f, 0); headPosition = SharpDX.Vector3.TransformCoordinate(headPosition, transform); if (trackingValid && (distanceSquared < 0.02f) && (alpha > 1)) { alpha = 0; } //Console.WriteLine(distanceSquared); } var userView = GraphicsTransforms.LookAt(headPosition, headPosition + SharpDX.Vector3.UnitZ, SharpDX.Vector3.UnitY); userView.Transpose(); //Console.WriteLine("headPosition = " + headPosition); float aspect = (float)userViewTextureWidth / (float)userViewTextureHeight; var userProjection = GraphicsTransforms.PerspectiveFov(55.0f / 180.0f * (float)Math.PI, aspect, 0.001f, 1000.0f); userProjection.Transpose(); // smooth depth images foreach (var camera in ensemble.cameras) { var cameraDeviceResource = cameraDeviceResources[camera]; if (cameraDeviceResource.depthImageChanged) { fromUIntPS.Render(deviceContext, cameraDeviceResource.depthImageTextureRV, cameraDeviceResource.floatDepthImageRenderTargetView); for (int i = 0; i < 1; i++) { bilateralFilter.Render(deviceContext, cameraDeviceResource.floatDepthImageRV, cameraDeviceResource.floatDepthImageRenderTargetView2); bilateralFilter.Render(deviceContext, cameraDeviceResource.floatDepthImageRV2, cameraDeviceResource.floatDepthImageRenderTargetView); } cameraDeviceResource.depthImageChanged = false; } } // wobble effect if (wobbleEffectEnabled) { foreach (var camera in ensemble.cameras) { var cameraDeviceResource = cameraDeviceResources[camera]; var world = new SharpDX.Matrix(); for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { world[i, j] = (float)camera.pose[i, j]; } } world.Transpose(); // view and projection matrix are post-multiply var userWorldViewProjection = world * userView * userProjection; depthAndColorShader.SetConstants(deviceContext, camera.calibration, userWorldViewProjection); depthAndColorShader.Render(deviceContext, cameraDeviceResource.floatDepthImageRV, cameraDeviceResource.colorImageTextureRV, cameraDeviceResource.vertexBuffer, userViewRenderTargetView, userViewDepthStencilView, userViewViewport); } } // 3d object if (threeDObjectEnabled) { var world = SharpDX.Matrix.Scaling(1.0f) * SharpDX.Matrix.RotationY(90.0f / 180.0f * (float)Math.PI) * SharpDX.Matrix.RotationX(-40.0f / 180.0f * (float)Math.PI) * SharpDX.Matrix.Translation(0, 0.7f, 0.0f); var pointLight = new PointLight(); pointLight.position = new Vector3(0, 2, 0); pointLight.Ia = new Vector3(0.1f, 0.1f, 0.1f); meshShader.SetVertexShaderConstants(deviceContext, world, userView * userProjection, pointLight.position); meshShader.Render(deviceContext, meshDeviceResources, pointLight, userViewRenderTargetView, userViewDepthStencilView, userViewViewport); } // wobble effect if (wobbleEffectEnabled) { alpha += 0.05f; if (alpha > 1) { radialWobbleShader.SetConstants(deviceContext, 0); } else { radialWobbleShader.SetConstants(deviceContext, alpha); } radialWobbleShader.Render(deviceContext, userViewSRV, filteredUserViewRenderTargetView); } // desktop duplication if (desktopDuplicationEnabled) { // update the desktop texture; this will block until there is some change var outputDuplicateFrameInformation = default(OutputDuplicateFrameInformation); SharpDX.DXGI.Resource resource = null; outputDuplication.AcquireNextFrame(1000, out outputDuplicateFrameInformation, out resource); var texture = resource.QueryInterface <Texture2D>(); // pick up the window under the cursor var cursorPos = new POINT(); GetCursorPos(out cursorPos); var hwnd = WindowFromPoint(cursorPos); var rect = new RECT(); GetWindowRect(hwnd, out rect); // adjust bounds so falls within source texture if (rect.Left < 0) { rect.Left = 0; } if (rect.Top < 0) { rect.Top = 0; } if (rect.Right > texture.Description.Width - 1) { rect.Right = texture.Description.Width; } if (rect.Bottom > texture.Description.Height - 1) { rect.Bottom = texture.Description.Height; } int width = rect.Right - rect.Left; int height = rect.Bottom - rect.Top; // resize our texture if necessary if ((desktopTexture == null) || (desktopTexture.Description.Width != width) || (desktopTexture.Description.Height != height)) { if (desktopTexture != null) { desktopTextureSRV.Dispose(); desktopTexture.Dispose(); } var desktopTextureDesc = new Texture2DDescription() { Width = width, Height = height, MipLevels = 1, // revisit this; we may benefit from mipmapping? ArraySize = 1, Format = SharpDX.DXGI.Format.B8G8R8A8_UNorm, SampleDescription = new SharpDX.DXGI.SampleDescription(1, 0), Usage = ResourceUsage.Default, BindFlags = BindFlags.ShaderResource, CpuAccessFlags = CpuAccessFlags.None, }; desktopTexture = new Texture2D(device, desktopTextureDesc); desktopTextureSRV = new ShaderResourceView(device, desktopTexture); } // copy the winodw region into our texture var sourceRegion = new ResourceRegion() { Left = rect.Left, Right = rect.Right, Top = rect.Top, Bottom = rect.Bottom, Front = 0, Back = 1, }; deviceContext.CopySubresourceRegion(texture, 0, sourceRegion, desktopTexture, 0); texture.Dispose(); } // render user view to seperate form passThroughShader.viewport = new Viewport(0, 0, userViewForm.videoPanel1.Width, userViewForm.videoPanel1.Height); // TODO: clean this up by simply using a pointer to the userViewSRV if (threeDObjectEnabled) { passThroughShader.Render(deviceContext, userViewSRV, userViewForm.renderTargetView); } if (wobbleEffectEnabled) { passThroughShader.Render(deviceContext, filteredUserViewSRV, userViewForm.renderTargetView); } if (desktopDuplicationEnabled) { passThroughShader.Render(deviceContext, desktopTextureSRV, userViewForm.renderTargetView); } userViewForm.swapChain.Present(0, PresentFlags.None); // projection puts x and y in [-1,1]; adjust to obtain texture coordinates [0,1] // TODO: put this in SetContants? userProjection[0, 0] /= 2; userProjection[1, 1] /= -2; // y points down userProjection[2, 0] += 0.5f; userProjection[2, 1] += 0.5f; // projection mapping for each projector foreach (var form in projectorForms) { deviceContext.ClearRenderTargetView(form.renderTargetView, Color4.Black); deviceContext.ClearDepthStencilView(form.depthStencilView, DepthStencilClearFlags.Depth, 1, 0); foreach (var camera in ensemble.cameras) { var cameraDeviceResource = cameraDeviceResources[camera]; var world = new SharpDX.Matrix(); for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { world[i, j] = (float)camera.pose[i, j]; } } world.Transpose(); var projectorWorldViewProjection = world * form.view * form.projection; var userWorldViewProjection = world * userView * userProjection; projectiveTexturingShader.SetConstants(deviceContext, userWorldViewProjection, projectorWorldViewProjection); // TODO: clean this up by simply using a pointer to the userViewSRV if (wobbleEffectEnabled) { projectiveTexturingShader.Render(deviceContext, cameraDeviceResource.floatDepthImageRV, filteredUserViewSRV, cameraDeviceResource.vertexBuffer, form.renderTargetView, form.depthStencilView, form.viewport); } if (threeDObjectEnabled) { projectiveTexturingShader.Render(deviceContext, cameraDeviceResource.floatDepthImageRV, userViewSRV, cameraDeviceResource.vertexBuffer, form.renderTargetView, form.depthStencilView, form.viewport); } if (desktopDuplicationEnabled) { projectiveTexturingShader.Render(deviceContext, cameraDeviceResource.floatDepthImageRV, desktopTextureSRV, cameraDeviceResource.vertexBuffer, form.renderTargetView, form.depthStencilView, form.viewport); } } form.swapChain.Present(1, PresentFlags.None); } if (desktopDuplicationEnabled) { outputDuplication.ReleaseFrame(); } //Console.WriteLine(stopwatch.ElapsedMilliseconds); stopwatch.Restart(); } } }
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 { } } }
void RenderLoop() { while (true) { lock (renderLock) { var deviceContext = device.ImmediateContext; // render user view deviceContext.ClearRenderTargetView(userViewRenderTargetView, Color4.Black); deviceContext.ClearDepthStencilView(userViewDepthStencilView, DepthStencilClearFlags.Depth, 1, 0); SharpDX.Vector3 headPosition = new SharpDX.Vector3(0f, 1.1f, -1.4f); // may need to change this default if (localHeadTrackingEnabled) { float distanceSquared = 0; lock (headCameraSpacePointLock) { headPosition = new SharpDX.Vector3(headCameraSpacePoint.X, headCameraSpacePoint.Y, headCameraSpacePoint.Z); float dx = handLeftCameraSpacePoint.X - handRightCameraSpacePoint.X; float dy = handLeftCameraSpacePoint.Y - handRightCameraSpacePoint.Y; float dz = handLeftCameraSpacePoint.Z - handRightCameraSpacePoint.Z; distanceSquared = dx * dx + dy * dy + dz * dz; } var transform = SharpDX.Matrix.RotationY((float)Math.PI) * SharpDX.Matrix.Translation(-0.25f, 0.45f, 0); headPosition = SharpDX.Vector3.TransformCoordinate(headPosition, transform); if (trackingValid && (distanceSquared < 0.02f) && (alpha > 1)) { alpha = 0; } //Console.WriteLine(distanceSquared); } var userView = GraphicsTransforms.LookAt(headPosition, headPosition + SharpDX.Vector3.UnitZ, SharpDX.Vector3.UnitY); userView.Transpose(); //Console.WriteLine("headPosition = " + headPosition); float aspect = (float)userViewTextureWidth / (float)userViewTextureHeight; var userProjection = GraphicsTransforms.PerspectiveFov(55.0f / 180.0f * (float)Math.PI, aspect, 0.001f, 1000.0f); userProjection.Transpose(); // smooth depth images foreach (var camera in ensemble.cameras) { var cameraDeviceResource = cameraDeviceResources[camera]; if (cameraDeviceResource.depthImageChanged) { fromUIntPS.Render(deviceContext, cameraDeviceResource.depthImageTextureRV, cameraDeviceResource.floatDepthImageRenderTargetView); for (int i = 0; i < 1; i++) { bilateralFilter.Render(deviceContext, cameraDeviceResource.floatDepthImageRV, cameraDeviceResource.floatDepthImageRenderTargetView2); bilateralFilter.Render(deviceContext, cameraDeviceResource.floatDepthImageRV2, cameraDeviceResource.floatDepthImageRenderTargetView); } cameraDeviceResource.depthImageChanged = false; } } // wobble effect if (wobbleEffectEnabled) { foreach (var camera in ensemble.cameras) { var cameraDeviceResource = cameraDeviceResources[camera]; var world = new SharpDX.Matrix(); for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { world[i, j] = (float)camera.pose[i, j]; } } world.Transpose(); // view and projection matrix are post-multiply var userWorldViewProjection = world * userView * userProjection; depthAndColorShader.SetConstants(deviceContext, camera.calibration, userWorldViewProjection); depthAndColorShader.Render(deviceContext, cameraDeviceResource.floatDepthImageRV, cameraDeviceResource.colorImageTextureRV, cameraDeviceResource.vertexBuffer, userViewRenderTargetView, userViewDepthStencilView, userViewViewport); } } // 3d object if (threeDObjectEnabled) { var world = SharpDX.Matrix.Scaling(1.0f) * SharpDX.Matrix.RotationY(90.0f / 180.0f * (float)Math.PI) * SharpDX.Matrix.RotationX(-40.0f / 180.0f * (float)Math.PI) * SharpDX.Matrix.Translation(0, 0.7f, 0.0f); var pointLight = new PointLight(); pointLight.position = new Vector3(0, 2, 0); pointLight.Ia = new Vector3(0.1f, 0.1f, 0.1f); meshShader.SetVertexShaderConstants(deviceContext, world, userView * userProjection, pointLight.position); meshShader.Render(deviceContext, meshDeviceResources, pointLight, userViewRenderTargetView, userViewDepthStencilView, userViewViewport); } // wobble effect if (wobbleEffectEnabled) { alpha += 0.05f; if (alpha > 1) { radialWobbleShader.SetConstants(deviceContext, 0); } else { radialWobbleShader.SetConstants(deviceContext, alpha); } radialWobbleShader.Render(deviceContext, userViewSRV, filteredUserViewRenderTargetView); } // desktop duplication if (desktopDuplicationEnabled) { var outputDuplicateFrameInformation = default(OutputDuplicateFrameInformation); SharpDX.DXGI.Resource resource = null; outputDuplication.AcquireNextFrame(1000, out outputDuplicateFrameInformation, out resource); var texture = resource.QueryInterface <Texture2D>(); var rect = new RECT(); GetWindowRect(windowPtr, out rect); var sourceRegion = new ResourceRegion() { Left = rect.Left + leftNudge, Right = rect.Right + rightNudge, Top = rect.Top + topNudge, Bottom = rect.Bottom + bottomNudge, Front = 0, Back = 1, }; deviceContext.CopySubresourceRegion(texture, 0, sourceRegion, desktopTexture, 0); texture.Dispose(); } // render user view to seperate form passThroughShader.viewport = new Viewport(0, 0, userViewForm.Width, userViewForm.Height); // TODO: clean this up by simply using a pointer to the userViewSRV if (threeDObjectEnabled) { passThroughShader.Render(deviceContext, userViewSRV, userViewForm.renderTargetView); } if (wobbleEffectEnabled) { passThroughShader.Render(deviceContext, filteredUserViewSRV, userViewForm.renderTargetView); } if (desktopDuplicationEnabled) { passThroughShader.Render(deviceContext, desktopTextureSRV, userViewForm.renderTargetView); } userViewForm.swapChain.Present(0, PresentFlags.None); // projection puts x and y in [-1,1]; adjust to obtain texture coordinates [0,1] // TODO: put this in SetContants? userProjection[0, 0] /= 2; userProjection[1, 1] /= -2; // y points down userProjection[2, 0] += 0.5f; userProjection[2, 1] += 0.5f; // projection mapping for each projector foreach (var form in projectorForms) { deviceContext.ClearRenderTargetView(form.renderTargetView, Color4.Black); deviceContext.ClearDepthStencilView(form.depthStencilView, DepthStencilClearFlags.Depth, 1, 0); foreach (var camera in ensemble.cameras) { var cameraDeviceResource = cameraDeviceResources[camera]; var world = new SharpDX.Matrix(); for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { world[i, j] = (float)camera.pose[i, j]; } } world.Transpose(); var projectorWorldViewProjection = world * form.view * form.projection; var userWorldViewProjection = world * userView * userProjection; projectiveTexturingShader.SetConstants(deviceContext, userWorldViewProjection, projectorWorldViewProjection); // TODO: clean this up by simply using a pointer to the userViewSRV if (wobbleEffectEnabled) { projectiveTexturingShader.Render(deviceContext, cameraDeviceResource.floatDepthImageRV, filteredUserViewSRV, cameraDeviceResource.vertexBuffer, form.renderTargetView, form.depthStencilView, form.viewport); } if (threeDObjectEnabled) { projectiveTexturingShader.Render(deviceContext, cameraDeviceResource.floatDepthImageRV, userViewSRV, cameraDeviceResource.vertexBuffer, form.renderTargetView, form.depthStencilView, form.viewport); } if (desktopDuplicationEnabled) { projectiveTexturingShader.Render(deviceContext, cameraDeviceResource.floatDepthImageRV, desktopTextureSRV, cameraDeviceResource.vertexBuffer, form.renderTargetView, form.depthStencilView, form.viewport); } } form.swapChain.Present(1, PresentFlags.None); } if (desktopDuplicationEnabled) { outputDuplication.ReleaseFrame(); } Console.WriteLine(stopwatch.ElapsedMilliseconds); stopwatch.Restart(); } } }
/* Код взят с: * 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 void compress(object sender, DoWorkEventArgs ea) { * int numBytes = GetNumBytes(); * byte[] duplicate = (byte[])frameBytes.Clone(); * using (var compressIntoMs = new MemoryStream()) * { * using (var gzs = new BufferedStream(new GZipStream(compressIntoMs, CompressionMode.Compress), numBytes)) * { * gzs.Write(duplicate, 0, numBytes); * } * byte[] compressed = compressIntoMs.ToArray(); * Debug.WriteLine(frameBytes.Length); * Debug.WriteLine(compressed.Length); * } * }*/ //private void HandleCapturedFrame(object sender, RunWorkerCompletedEventArgs e) private void CaptureFrame(object sender, DoWorkEventArgs ea) //private void CaptureFrame(object state) { //CaptureFrameAsync(); //Stopwatch timer = new Stopwatch(); //timer.Start(); //System.Drawing.Bitmap bitmap = null; SharpDX.DXGI.Resource screenResource = null; //bool captureDone = false; //for (int i = 0; !captureDone; i++) //{ try { OutputDuplicateFrameInformation duplicateFrameInformation; // Try to get duplicated frame within given time this.duplicatedOutput.AcquireNextFrame(1000, out duplicateFrameInformation, out screenResource); //if (i > 0) //{ // copy resource into memory that can be accessed by the CPU using (Texture2D screenTexture2D = screenResource.QueryInterface <Texture2D>()) device.ImmediateContext.CopyResource(screenTexture2D, screenTexture); DataBox mapSource = device.ImmediateContext.MapSubresource(screenTexture, 0, MapMode.Read, SharpDX.Direct3D11.MapFlags.None); /*int loopCap = dWidth * dHeight; * unsafe * { * uint* destPtr2 = (uint*)mapDest2.Scan0; * //uint* sourcePtr2 = (uint*)sourcePtr; * for (int x = 0; x < loopCap; ++x) * { * destPtr2[x] = (destPtr2[x] & 0x000000ff) << 16 | (destPtr2[x] & 0x0000FF00) | (destPtr2[x] & 0x00FF0000) >> 16 | (destPtr2[x] & 0xFF000000); * //sourcePtr2[x] = (sourcePtr2[x] & 0x000000ff) << 16 | (sourcePtr2[x] & 0x0000FF00) | (sourcePtr2[x] & 0x00FF0000) >> 16 | (sourcePtr2[x] & 0xFF000000); * } * }*/ byte[] byteData = new byte[GetNumBytesDisplay()]; Marshal.Copy(mapSource.DataPointer, byteData, 0, GetNumBytesDisplay()); frameBytes = byteData; //captureDone = true; //} duplicatedOutput.ReleaseFrame(); } catch (SharpDXException e) { if (e.ResultCode.Code != SharpDX.DXGI.ResultCode.WaitTimeout.Result.Code) { throw e; } } catch (Exception e) { throw e; } //} //timer.Stop(); //Debug.WriteLine(timer.ElapsedMilliseconds); //if (!continueCapturing) return; //CaptureFrameAsync(); //frameBytes = byteData; //screenResource.Dispose(); //return bitmap; //ea.Result = bytedata; //ThreadPool.QueueUserWorkItem(DoTheWork, new object[] { dWidth, dHeight, 60, frameBytes, outBytesPtr }); //Stopwatch timer = new Stopwatch(); //timer.Start(); //DoWork(dWidth, dHeight, 60, frameBytes, outBytesPtr); //timer.Stop(); //System.Console.WriteLine("Elapsed: " + timer.ElapsedMilliseconds); framesCapped++; //EncodeFrameAsync(); }
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(); } } } }
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(); } } } }