diff --git a/ScreenCapture.NET/DirectX/DX11ScreenCapture.cs b/ScreenCapture.NET/DirectX/DX11ScreenCapture.cs index 1cf6a6b..dd54a7e 100644 --- a/ScreenCapture.NET/DirectX/DX11ScreenCapture.cs +++ b/ScreenCapture.NET/DirectX/DX11ScreenCapture.cs @@ -10,7 +10,6 @@ using Vortice.DXGI; using Vortice.Mathematics; using MapFlags = Vortice.Direct3D11.MapFlags; using ResultCode = Vortice.DXGI.ResultCode; -using Usage = Vortice.Direct3D11.Usage; namespace ScreenCapture.NET { @@ -31,6 +30,8 @@ namespace ScreenCapture.NET FeatureLevel.Level_10_0 }; + private const int BPP = 4; + #endregion #region Properties & Fields @@ -179,7 +180,13 @@ namespace ScreenCapture.NET MappedSubresource mapSource = _context.Map(stagingTexture, 0, MapMode.Read, MapFlags.None); IntPtr sourcePtr = mapSource.DataPointer; lock (captureZone.Buffer) - Marshal.Copy(sourcePtr, captureZone.Buffer, 0, captureZone.Buffer.Length); + { + for (int y = 0; y < captureZone.Height; y++) + { + Marshal.Copy(sourcePtr, captureZone.Buffer, y * captureZone.Stride, captureZone.Stride); + sourcePtr += mapSource.RowPitch; + } + } _context.Unmap(stagingTexture, 0); captureZone.SetUpdated(); @@ -199,9 +206,6 @@ namespace ScreenCapture.NET if ((x + width) > Display.Width) throw new ArgumentException("x + width > Display width"); if ((y + height) > Display.Height) throw new ArgumentException("y + height > Display height"); - int textureWidth = (int)Math.Ceiling(width / 32.0) * 32; - int textureHeight = (int)Math.Ceiling(height / 32.0) * 32; - int unscaledWidth = width; int unscaledHeight = height; if (downscaleLevel > 0) @@ -214,12 +218,9 @@ namespace ScreenCapture.NET if (width < 1) width = 1; if (height < 1) height = 1; - int bufferWidth = (int)Math.Ceiling(width / 32.0) * 32; - int bufferHeight = (int)Math.Ceiling(height / 32.0) * 32; + byte[] buffer = new byte[width * height * 4]; - byte[] buffer = new byte[bufferWidth * bufferHeight * 4]; - - CaptureZone captureZone = new(_indexCounter++, x, y, width, height, downscaleLevel, unscaledWidth, unscaledHeight, textureWidth, textureHeight, bufferWidth, bufferHeight, buffer); + CaptureZone captureZone = new(_indexCounter++, x, y, width, height, BPP, downscaleLevel, unscaledWidth, unscaledHeight, buffer); lock (_captureZones) InitializeCaptureZone(captureZone); @@ -252,13 +253,13 @@ namespace ScreenCapture.NET CpuAccessFlags = CpuAccessFlags.Read, BindFlags = BindFlags.None, Format = Format.B8G8R8A8_UNorm, - Width = captureZone.BufferWidth, - Height = captureZone.BufferHeight, + Width = captureZone.Width, + Height = captureZone.Height, OptionFlags = ResourceOptionFlags.None, MipLevels = 1, ArraySize = 1, SampleDescription = { Count = 1, Quality = 0 }, - Usage = Usage.Staging + Usage = ResourceUsage.Staging }; ID3D11Texture2D stagingTexture = _device!.CreateTexture2D(stagingTextureDesc); @@ -271,13 +272,13 @@ namespace ScreenCapture.NET CpuAccessFlags = CpuAccessFlags.None, BindFlags = BindFlags.RenderTarget | BindFlags.ShaderResource, Format = Format.B8G8R8A8_UNorm, - Width = captureZone.CaptureWidth, - Height = captureZone.CaptureHeight, + Width = captureZone.UnscaledWidth, + Height = captureZone.UnscaledHeight, OptionFlags = ResourceOptionFlags.GenerateMips, MipLevels = captureZone.DownscaleLevel + 1, ArraySize = 1, SampleDescription = { Count = 1, Quality = 0 }, - Usage = Usage.Default + Usage = ResourceUsage.Default }; scalingTexture = _device!.CreateTexture2D(scalingTextureDesc); scalingTextureView = _device.CreateShaderResourceView(scalingTexture); @@ -302,7 +303,7 @@ namespace ScreenCapture.NET _context = _device.ImmediateContext; _output = adapter.GetOutput(Display.Index); - using IDXGIOutput5 output1 = _output.QueryInterface(); + using IDXGIOutput5 output = _output.QueryInterface(); Texture2DDescription captureTextureDesc = new() { @@ -315,7 +316,7 @@ namespace ScreenCapture.NET MipLevels = 1, ArraySize = 1, SampleDescription = { Count = 1, Quality = 0 }, - Usage = Usage.Default + Usage = ResourceUsage.Default }; _captureTexture = _device.CreateTexture2D(captureTextureDesc); @@ -324,8 +325,8 @@ namespace ScreenCapture.NET foreach (CaptureZone captureZone in captureZones) InitializeCaptureZone(captureZone); } - - _duplicatedOutput = output1.DuplicateOutput1(_device, Format.B8G8R8A8_UNorm); // DarthAffe 27.02.2021: This prepares for the use of 10bit color depth + + _duplicatedOutput = output.DuplicateOutput1(_device, Format.B8G8R8A8_UNorm); // DarthAffe 27.02.2021: This prepares for the use of 10bit color depth } catch { Dispose(false); } } diff --git a/ScreenCapture.NET/Model/BlackBarDetection.cs b/ScreenCapture.NET/Model/BlackBarDetection.cs index 6af698f..b85a1f1 100644 --- a/ScreenCapture.NET/Model/BlackBarDetection.cs +++ b/ScreenCapture.NET/Model/BlackBarDetection.cs @@ -78,11 +78,10 @@ namespace ScreenCapture.NET private int CalculateTop() { int threshold = Threshold; - int stride = _captureZone.BufferWidth * 4; - int bytesPerRow = _captureZone.Width * 4; + int stride = _captureZone.Stride; for (int row = 0; row < _captureZone.Height; row++) { - Span data = new(_captureZone.Buffer, row * stride, bytesPerRow); + Span data = new(_captureZone.Buffer, row * stride, stride); for (int i = 0; i < data.Length; i += 4) if ((data[i] > threshold) || (data[i + 1] > threshold) || (data[i + 2] > threshold)) return row; @@ -94,11 +93,10 @@ namespace ScreenCapture.NET private int CalculateBottom() { int threshold = Threshold; - int stride = _captureZone.BufferWidth * 4; - int bytesPerRow = _captureZone.Width * 4; + int stride = _captureZone.Stride; for (int row = _captureZone.Height; row >= 0; row--) { - Span data = new(_captureZone.Buffer, row * stride, bytesPerRow); + Span data = new(_captureZone.Buffer, row * stride, stride); for (int i = 0; i < data.Length; i += 4) if ((data[i] > threshold) || (data[i + 1] > threshold) || (data[i + 2] > threshold)) return _captureZone.Height - row; @@ -110,7 +108,7 @@ namespace ScreenCapture.NET private int CalculateLeft() { int threshold = Threshold; - int stride = _captureZone.BufferWidth * 4; + int stride = _captureZone.Stride; byte[] buffer = _captureZone.Buffer; for (int column = 0; column < _captureZone.Width; column++) for (int row = 0; row < _captureZone.Height; row++) @@ -125,7 +123,7 @@ namespace ScreenCapture.NET private int CalculateRight() { int threshold = Threshold; - int stride = _captureZone.BufferWidth * 4; + int stride = _captureZone.Stride; byte[] buffer = _captureZone.Buffer; for (int column = _captureZone.Width; column >= 0; column--) for (int row = 0; row < _captureZone.Height; row++) diff --git a/ScreenCapture.NET/Model/CaptureZone.cs b/ScreenCapture.NET/Model/CaptureZone.cs index 6846e81..dbbc48d 100644 --- a/ScreenCapture.NET/Model/CaptureZone.cs +++ b/ScreenCapture.NET/Model/CaptureZone.cs @@ -52,26 +52,14 @@ namespace ScreenCapture.NET public int UnscaledHeight { get; } /// - /// Gets the actually captured width of the region (this can be greated than due to size-constraints on the GPU). + /// Gets the amount of bytes per pixel in the image (most likely 3 [RGB] or 4 [ARGB]). /// - public int CaptureWidth { get; } + public int BytesPerPixel { get; } /// - /// Gets the actually captured height of the region (this can be greated than due to size-constraints on the GPU). + /// Gets the size in bytes of a row in the region ( * ). /// - public int CaptureHeight { get; } - - /// - /// Gets the width of the buffer the capture is saved to. - /// Equals most of the time but can be bigger. - /// - public int BufferWidth { get; } - - /// - /// Gets the height of the buffer the capture is saved to. - /// Equals most of the time but can be bigger. - /// - public int BufferHeight { get; } + public int Stride => Width * BytesPerPixel; /// /// Gets the buffer containing the image data. Format depends on the specific capture but is most likely BGRA32. @@ -117,25 +105,18 @@ namespace ScreenCapture.NET /// The level of downscaling applied to the image of this region before copying to local memory. /// The original width of the region. /// The original height of the region - /// The actually captured width of the region. - /// The actually captured height of the region. - /// The width of the buffer the capture is saved to. - /// The height of the buffer the capture is saved to. /// The buffer containing the image data. - public CaptureZone(int id, int x, int y, int width, int height, int downscaleLevel, int unscaledWidth, int unscaledHeight, int captureWidth, int captureHeight, int bufferWidth, int bufferHeight, byte[] buffer) + internal CaptureZone(int id, int x, int y, int width, int height, int bytesPerPixel, int downscaleLevel, int unscaledWidth, int unscaledHeight, byte[] buffer) { this.Id = id; this.X = x; this.Y = y; this.Width = width; this.Height = height; + this.BytesPerPixel = bytesPerPixel; this.UnscaledWidth = unscaledWidth; this.UnscaledHeight = unscaledHeight; this.DownscaleLevel = downscaleLevel; - this.CaptureWidth = captureWidth; - this.CaptureHeight = captureHeight; - this.BufferWidth = bufferWidth; - this.BufferHeight = bufferHeight; this.Buffer = buffer; BlackBars = new BlackBarDetection(this); diff --git a/ScreenCapture.NET/ScreenCapture.NET.csproj b/ScreenCapture.NET/ScreenCapture.NET.csproj index fde0ab6..d705f93 100644 --- a/ScreenCapture.NET/ScreenCapture.NET.csproj +++ b/ScreenCapture.NET/ScreenCapture.NET.csproj @@ -60,7 +60,7 @@ - +