Ejemplo n.º 1
0
        public void Update(Texture2D DesktopTexture, OutputDuplicateFrameInformation FrameInfo, OutputDuplication DeskDupl)
        {
            // No update
            if (FrameInfo.LastMouseUpdateTime == 0)
            {
                _pointerShape?.Update(DesktopTexture, _pointerPosition);
                return;
            }

            _pointerPosition = FrameInfo.PointerPosition;

            if (FrameInfo.PointerShapeBufferSize != 0)
            {
                if (FrameInfo.PointerShapeBufferSize > _ptrShapeBufferSize)
                {
                    _ptrShapeBufferSize = FrameInfo.PointerShapeBufferSize;

                    _ptrShapeBuffer = _ptrShapeBuffer != IntPtr.Zero
                        ? Marshal.ReAllocCoTaskMem(_ptrShapeBuffer, _ptrShapeBufferSize)
                        : Marshal.AllocCoTaskMem(_ptrShapeBufferSize);
                }

                DeskDupl.GetFramePointerShape(_ptrShapeBufferSize,
                                              _ptrShapeBuffer,
                                              out _,
                                              out _ptrShapeInfo);

                _pointerShape?.Dispose();

                switch (_ptrShapeInfo.Type)
                {
                case PtrShapeMonochrome:
                    _pointerShape = new MonochromePointerShape(_ptrShapeBuffer,
                                                               _ptrShapeInfo,
                                                               _editorSession);
                    break;

                case PtrShapeMaskedColor:
                    _pointerShape = new MaskedColorPointerShape(_ptrShapeBuffer,
                                                                _ptrShapeInfo,
                                                                _editorSession);
                    break;

                case PtrShapeColor:
                    _pointerShape = new ColorPointerShape(_ptrShapeBuffer,
                                                          _ptrShapeInfo,
                                                          _editorSession.RenderTarget);
                    break;
                }
            }

            _pointerShape?.Update(DesktopTexture, _pointerPosition);
        }
Ejemplo n.º 2
0
        public void Update(Texture2D DesktopTexture, OutputDuplicatePointerPosition PointerPosition)
        {
            _bmp?.Dispose();

            var region = new ResourceRegion(
                PointerPosition.Position.X,
                PointerPosition.Position.Y,
                0,
                PointerPosition.Position.X + Width,
                PointerPosition.Position.Y + Height,
                1);

            _editorSession.Device.ImmediateContext.CopySubresourceRegion(
                DesktopTexture,
                0,
                region,
                _copyTex,
                0);

            var desktopMap = _editorSession.Device.ImmediateContext.MapSubresource(
                _copyTex,
                0,
                MapMode.Read,
                MapFlags.None);

            try
            {
                Marshal.Copy(desktopMap.DataPointer, DesktopBuffer, 0, DesktopBuffer.Length);
            }
            finally
            {
                _editorSession.Device.ImmediateContext.UnmapSubresource(_copyTex, 0);
            }

            OnUpdate();

            var gcPin = GCHandle.Alloc(ShapeBuffer, GCHandleType.Pinned);

            try
            {
                var pitch = Width * 4;

                _bmp = new Bitmap(_editorSession.RenderTarget,
                                  new Size2(Width, Height),
                                  new DataPointer(gcPin.AddrOfPinnedObject(), Height * pitch),
                                  pitch,
                                  new BitmapProperties(new PixelFormat(Format.B8G8R8A8_UNorm, AlphaMode.Premultiplied)));
            }
            finally
            {
                gcPin.Free();
            }
        }
Ejemplo n.º 3
0
        protected internal void GetCursor(Texture2D screenTexture, OutputDuplicateFrameInformation info, FrameInfo frame)
        {
            //Prepare buffer array to hold the cursor shape.
            if (CursorShapeBuffer == null || info.PointerShapeBufferSize > CursorShapeBuffer.Length)
            {
                CursorShapeBuffer = new byte[info.PointerShapeBufferSize];
            }

            //If there's a cursor shape available to be captured.
            if (info.PointerShapeBufferSize > 0)
            {
                //Pin the buffer in order to pass the address as parameter later.
                var pinnedBuffer        = GCHandle.Alloc(CursorShapeBuffer, GCHandleType.Pinned);
                var cursorBufferAddress = pinnedBuffer.AddrOfPinnedObject();

                //Load the cursor shape into the buffer.
                DuplicatedOutput.GetFramePointerShape(info.PointerShapeBufferSize, cursorBufferAddress, out _, out CursorShapeInfo);

                //If the cursor is monochrome, it will return the cursor shape twice, one is the mask.
                if (CursorShapeInfo.Type == 1)
                {
                    CursorShapeInfo.Height /= 2;
                }

                //The buffer must be unpinned, to free resources.
                pinnedBuffer.Free();
            }

            //Store the current cursor position, if it was moved.
            if (info.LastMouseUpdateTime != 0)
            {
                PreviousPosition = info.PointerPosition;
            }

            //TODO: In a future version, don't merge the cursor image in here, let the editor do that.
            //Saves the position of the cursor, so the editor can add the mouse clicks overlay later.
            frame.CursorX = PreviousPosition.Position.X - Left;
            frame.CursorY = PreviousPosition.Position.Y - Top;

            //If the method is supposed to simply the get the cursor shape no shape was loaded before, there's nothing else to do.
            //if (CursorShapeBuffer?.Length == 0 || (info.LastPresentTime == 0 && info.LastMouseUpdateTime == 0) || !info.PointerPosition.Visible)
            if (screenTexture == null || CursorShapeBuffer?.Length == 0)// || !info.PointerPosition.Visible)
            {
                return;
            }

            //Don't let it bleed beyond the top-left corner.
            var left    = Math.Max(frame.CursorX, 0);
            var top     = Math.Max(frame.CursorY, 0);
            var offsetX = Math.Abs(Math.Min(0, frame.CursorX));
            var offsetY = Math.Abs(Math.Min(0, frame.CursorY));

            //Adjust the offset, so it's possible to add the highlight correctly later.
            frame.CursorX += CursorShapeInfo.HotSpot.X;
            frame.CursorY += CursorShapeInfo.HotSpot.Y;

            if (CursorShapeInfo.Width - offsetX < 0 || CursorShapeInfo.Height - offsetY < 0)
            {
                return;
            }

            //The staging texture must be able to hold all pixels.
            if (CursorStagingTexture == null || CursorStagingTexture.Description.Width < CursorShapeInfo.Width - offsetX || CursorStagingTexture.Description.Height < CursorShapeInfo.Height - offsetY)
            {
                //In order to change the size of the texture, I need to instantiate it again with the new size.
                CursorStagingTexture?.Dispose();
                CursorStagingTexture = new Texture2D(Device, new Texture2DDescription
                {
                    ArraySize         = 1,
                    BindFlags         = BindFlags.None,
                    CpuAccessFlags    = CpuAccessFlags.Write,
                    Height            = CursorShapeInfo.Height - offsetY,
                    Format            = Format.B8G8R8A8_UNorm,
                    Width             = CursorShapeInfo.Width - offsetX,
                    MipLevels         = 1,
                    OptionFlags       = ResourceOptionFlags.None,
                    SampleDescription = new SampleDescription(1, 0),
                    Usage             = ResourceUsage.Staging
                });
            }

            //The region where the cursor is located is copied to the staging texture to act as the background when dealing with masks and transparency.
            var region = new ResourceRegion
            {
                Left   = left,
                Top    = top,
                Front  = 0,
                Right  = left + CursorStagingTexture.Description.Width,
                Bottom = top + CursorStagingTexture.Description.Height,
                Back   = 1
            };

            //Copy from the screen the region in which the cursor is located.
            Device.ImmediateContext.CopySubresourceRegion(screenTexture, 0, region, CursorStagingTexture, 0);

            //Get cursor details and draw it to the staging texture.
            DrawCursorShape(CursorStagingTexture, CursorShapeInfo, CursorShapeBuffer, offsetX, offsetY);

            //Copy back the cursor texture to the screen texture.
            Device.ImmediateContext.CopySubresourceRegion(CursorStagingTexture, 0, null, screenTexture, 0, left, top);
        }
Ejemplo n.º 4
0
    protected internal bool GetCursor(Texture2D screenTexture, OutputDuplicateFrameInformation info, FrameInfo frame)
    {
        //Prepare buffer array to hold the cursor shape.
        if (CursorShapeBuffer == null || info.PointerShapeBufferSize > CursorShapeBuffer.Length)
        {
            CursorShapeBuffer = new byte[info.PointerShapeBufferSize];
        }

        //If there's a cursor shape available to be captured.
        if (info.PointerShapeBufferSize > 0)
        {
            //Pin the buffer in order to pass the address as parameter later.
            var pinnedBuffer        = GCHandle.Alloc(CursorShapeBuffer, GCHandleType.Pinned);
            var cursorBufferAddress = pinnedBuffer.AddrOfPinnedObject();

            //Load the cursor shape into the buffer.
            DuplicatedOutput.GetFramePointerShape(info.PointerShapeBufferSize, cursorBufferAddress, out _, out CursorShapeInfo);

            //If the cursor is monochrome, it will return the cursor shape twice, one is the mask.
            if (CursorShapeInfo.Type == 1)
            {
                CursorShapeInfo.Height /= 2;
            }

            //The buffer must be unpinned, to free resources.
            pinnedBuffer.Free();
        }

        //Store the current cursor position, if it was moved.
        if (info.LastMouseUpdateTime != 0)
        {
            PreviousPosition = info.PointerPosition;
        }

        //TODO: In a future version, don't merge the cursor image in here, let the editor do that.
        //Saves the position of the cursor, so the editor can add the mouse clicks overlay later.
        frame.CursorX = PreviousPosition.Position.X - (Left - OffsetLeft);
        frame.CursorY = PreviousPosition.Position.Y - (Top - OffsetTop);

        //If the method is supposed to simply the get the cursor shape no shape was loaded before, there's nothing else to do.
        //if (CursorShapeBuffer?.Length == 0 || (info.LastPresentTime == 0 && info.LastMouseUpdateTime == 0) || !info.PointerPosition.Visible)
        if (screenTexture == null || CursorShapeBuffer?.Length == 0)// || !info.PointerPosition.Visible)
        {
            //FallbackCursorCapture(frame);

            //if (CursorShapeBuffer != null)
            return(false);
        }

        //Don't let it bleed beyond the top-left corner, calculate the dimensions of the portion of the cursor that will appear.
        var leftCut   = frame.CursorX;
        var topCut    = frame.CursorY;
        var rightCut  = screenTexture.Description.Width - (frame.CursorX + CursorShapeInfo.Width);
        var bottomCut = screenTexture.Description.Height - (frame.CursorY + CursorShapeInfo.Height);

        //Adjust to the hotspot offset, so it's possible to add the highlight correctly later.
        frame.CursorX += CursorShapeInfo.HotSpot.X;
        frame.CursorY += CursorShapeInfo.HotSpot.Y;

        //Don't try merging the textures if the cursor is out of bounds.
        if (leftCut + CursorShapeInfo.Width < 1 || topCut + CursorShapeInfo.Height < 1 || rightCut + CursorShapeInfo.Width < 1 || bottomCut + CursorShapeInfo.Height < 1)
        {
            return(false);
        }

        var cursorLeft   = Math.Max(leftCut, 0);
        var cursorTop    = Math.Max(topCut, 0);
        var cursorWidth  = leftCut < 0 ? CursorShapeInfo.Width + leftCut : rightCut < 0 ? CursorShapeInfo.Width + rightCut : CursorShapeInfo.Width;
        var cursorHeight = topCut < 0 ? CursorShapeInfo.Height + topCut : bottomCut < 0 ? CursorShapeInfo.Height + bottomCut : CursorShapeInfo.Height;

        //The staging texture must be able to hold all pixels.
        if (CursorStagingTexture == null || CursorStagingTexture.Description.Width != cursorWidth || CursorStagingTexture.Description.Height != cursorHeight)
        {
            //In order to change the size of the texture, I need to instantiate it again with the new size.
            CursorStagingTexture?.Dispose();
            CursorStagingTexture = new Texture2D(Device, new Texture2DDescription
            {
                ArraySize         = 1,
                BindFlags         = BindFlags.None,
                CpuAccessFlags    = CpuAccessFlags.Write,
                Height            = cursorHeight,
                Format            = Format.B8G8R8A8_UNorm,
                Width             = cursorWidth,
                MipLevels         = 1,
                OptionFlags       = ResourceOptionFlags.None,
                SampleDescription = new SampleDescription(1, 0),
                Usage             = ResourceUsage.Staging
            });
        }

        //The region where the cursor is located is copied to the staging texture to act as the background when dealing with masks and transparency.
        //The cutout must be the exact region needed and it can't overflow. It's not allowed to try to cut outside of the screenTexture region.
        var region = new ResourceRegion
        {
            Left   = cursorLeft,
            Top    = cursorTop,
            Front  = 0,
            Right  = cursorLeft + cursorWidth,
            Bottom = cursorTop + cursorHeight,
            Back   = 1
        };

        //Copy from the screen the region in which the cursor is located.
        Device.ImmediateContext.CopySubresourceRegion(screenTexture, 0, region, CursorStagingTexture, 0);

        //Get cursor details and draw it to the staging texture.
        DrawCursorShape(CursorStagingTexture, CursorShapeInfo, CursorShapeBuffer, leftCut < 0 ? leftCut * -1 : 0, topCut < 0 ? topCut * -1 : 0, cursorWidth, cursorHeight);

        //Copy back the cursor texture to the screen texture.
        Device.ImmediateContext.CopySubresourceRegion(CursorStagingTexture, 0, null, screenTexture, 0, cursorLeft, cursorTop);

        return(true);
    }
Ejemplo n.º 5
0
 public void Update(Texture2D DesktopTexture, OutputDuplicatePointerPosition PointerPosition)
 {
 }