/// <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 */
                        }
                    }
                }
            }
        }
示例#2
0
        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);
            }
        }
示例#3
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);
     }
 }
示例#5
0
        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);
        }
示例#7
0
        /// <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();
                    }
                }
            }
示例#9
0
        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);
        }
示例#11
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);
        }
示例#12
0
        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;
        }
示例#13
0
        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++;
        }
示例#16
0
 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);
         }
     }
 }
示例#17
0
        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();
                }
            }
        }
示例#18
0
        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 { }
            }
        }
示例#21
0
        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();
                }
            }
        }
示例#22
0
    /* Код взят с:
     * 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);
    }
示例#23
0
        /*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();
        }
示例#24
0
        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();
                    }
                }
            }
        }