aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Embedded_SW/Embedded/Communication/PMR/Debugging/StartDebugLogRequest.pb-c.c
blob: 4c9f854c8c9a16155715cf3028936694df422f09 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SharpDX;
using SharpDX.Direct3D11;
using SharpDX.DXGI;
using Tango.RemoteDesktop.Utils;
using Device = SharpDX.Direct3D11.Device;
using MapFlags = SharpDX.Direct3D11.MapFlags;

namespace Tango.RemoteDesktop.CaptureMethods
{
    /// <summary>
    /// Represents a high performance DirectX screen capture method.
    /// </summary>
    /// <seealso cref="Tango.RemoteDesktop.ICaptureMethod" />
    public class DirectXScreenCapture : ICaptureMethod
    {
        private static bool _hasInstance;
        private Device device;
        private Output1 output1;
        private Texture2DDescription textureDesc;
        private OutputDuplication duplicatedOutput;
        private int monitorWidth;
        private int monitorHeight;

        /// <summary>
        /// Gets or sets the index of the graphics adapter.
        /// </summary>
        public int AdapterIndex { get; set; }

        /// <summary>
        /// Gets or sets the index of the monitor within the graphics adapter.
        /// </summary>
        public int MonitorIndex { get; set; }

        /// <summary>
        /// Initializes a new instance of the <see cref="DirectXScreenCapture"/> class.
        /// </summary>
        /// <exception cref="InvalidOperationException">An instance of the DirectX screen capture method already exists. Please dispose it before attempting to create a new one.</exception>
        public DirectXScreenCapture()
        {
            if (_hasInstance)
            {
                throw new InvalidOperationException("An instance of the DirectX screen capture method already exists. Please dispose it before attempting to create a new one.");
            }

            // Create DXGI Factory1
            var factory = new Factory1();
            var adapter = factory.GetAdapter1(AdapterIndex);

            // Create device from Adapter
            device = new Device(adapter);

            // Get DXGI.Output
            var 
an class="w"> output1 = output.QueryInterface<Output1>(); // Width/Height of desktop to capture monitorWidth = ((SharpDX.Rectangle)output.Description.DesktopBounds).Width; monitorHeight = ((SharpDX.Rectangle)output.Description.DesktopBounds).Height; // Create Staging texture CPU-accessible textureDesc = new Texture2DDescription { CpuAccessFlags = CpuAccessFlags.Read, BindFlags = BindFlags.None, Format = Format.B8G8R8A8_UNorm, Width = monitorWidth, Height = monitorHeight, OptionFlags = ResourceOptionFlags.None, MipLevels = 1, ArraySize = 1, SampleDescription = { Count = 1, Quality = 0 }, Usage = ResourceUsage.Staging }; // Duplicate the output duplicatedOutput = output1.DuplicateOutput(device); _hasInstance = true; } /// <summary> /// Gets the desktop bitmap. /// </summary> /// <param name="region">The capture region.</param> /// <returns></returns> public virtual Bitmap GetDesktopBitmap(CaptureRegion region) { var screenTexture = new Texture2D(device, textureDesc); SharpDX.DXGI.Resource screenResource; OutputDuplicateFrameInformation duplicateFrameInformation; // Try to get duplicated frame within given time duplicatedOutput.AcquireNextFrame(10000, 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); // Create Drawing.Bitmap var bitmap = new Bitmap(monitorWidth, monitorHeight, System.Drawing.Imaging.PixelFormat.Format32bppRgb); var boundsRect = new System.Drawing.Rectangle(0, 0, monitorWidth, monitorHeight); // Copy pixels from screen capture Texture to GDI bitmap var mapDest = bitmap.LockBits(boundsRect, System.Drawing.Imaging.ImageLockMode.WriteOnly, bitmap.PixelFormat); var sourcePtr = mapSource.DataPointer; var destPtr = mapDest.Scan0; for (int y = 0; y < region.Height; y++) { // Copy a single line Utilities.CopyMemory(destPtr, sourcePtr, monitorWidth * 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); if (region.Left > 0 || region.Top > 0 || region.Width < monitorWidth || region.Height < monitorHeight) { var cropped = CropImage(bitmap, new System.Drawing.Rectangle(region.Left, region.Top, region.Width, region.Height)); bitmap.Dispose(); bitmap = cropped; } screenTexture.Dispose(); screenResource.Dispose(); duplicatedOutput.ReleaseFrame(); return bitmap; } private Bitmap CropImage(Bitmap img, System.Drawing.Rectangle cropArea) { Bitmap bmpImage = new Bitmap(img); return bmpImage.Clone(cropArea, bmpImage.PixelFormat); } /// <summary> /// Releases unmanaged and - optionally - managed resources. /// </summary> public void Dispose() { _hasInstance = false; duplicatedOutput.Dispose(); device.Dispose(); } } }