Skip to content

Commit 94471f0

Browse files
committed
Added capture-service for X11 (linux); Added some more color formats
1 parent 2667f84 commit 94471f0

File tree

13 files changed

+928
-14
lines changed

13 files changed

+928
-14
lines changed

ScreenCapture.NET.DX9/ScreenCapture.NET.DX9.csproj

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,4 @@
6868
<ProjectReference Include="..\ScreenCapture.NET\ScreenCapture.NET.csproj" />
6969
</ItemGroup>
7070

71-
<ItemGroup>
72-
<Folder Include="Downscale\" />
73-
</ItemGroup>
74-
7571
</Project>
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
// DarthAffe 07.09.2023: Copied from https://github.com/DarthAffe/RGB.NET/blob/2e0754f474b82ed4d0cae5c6c44378d234f1321b/RGB.NET.Presets/Textures/Sampler/AverageByteSampler.cs
2+
3+
using System;
4+
using System.Numerics;
5+
using System.Runtime.CompilerServices;
6+
7+
namespace ScreenCapture.NET.Downscale;
8+
9+
/// <summary>
10+
/// Represents a sampled that averages multiple byte-data entries.
11+
/// </summary>
12+
internal static class AverageByteSampler
13+
{
14+
#region Constants
15+
16+
private static readonly int INT_VECTOR_LENGTH = Vector<uint>.Count;
17+
18+
#endregion
19+
20+
#region Methods
21+
22+
public static unsafe void Sample(in SamplerInfo<byte> info, in Span<byte> pixelData)
23+
{
24+
int count = info.Width * info.Height;
25+
if (count == 0) return;
26+
27+
int dataLength = pixelData.Length;
28+
Span<uint> sums = stackalloc uint[dataLength];
29+
30+
int elementsPerVector = Vector<byte>.Count / dataLength;
31+
int valuesPerVector = elementsPerVector * dataLength;
32+
if (Vector.IsHardwareAccelerated && (info.Height > 1) && (info.Width >= valuesPerVector) && (dataLength <= Vector<byte>.Count))
33+
{
34+
int chunks = info.Width / elementsPerVector;
35+
36+
Vector<uint> sum1 = Vector<uint>.Zero;
37+
Vector<uint> sum2 = Vector<uint>.Zero;
38+
Vector<uint> sum3 = Vector<uint>.Zero;
39+
Vector<uint> sum4 = Vector<uint>.Zero;
40+
41+
for (int y = 0; y < info.Height; y++)
42+
{
43+
ReadOnlySpan<byte> data = info[y];
44+
45+
fixed (byte* colorPtr = data)
46+
{
47+
byte* current = colorPtr;
48+
for (int i = 0; i < chunks; i++)
49+
{
50+
Vector<byte> bytes = *(Vector<byte>*)current;
51+
Vector.Widen(bytes, out Vector<ushort> short1, out Vector<ushort> short2);
52+
Vector.Widen(short1, out Vector<uint> int1, out Vector<uint> int2);
53+
Vector.Widen(short2, out Vector<uint> int3, out Vector<uint> int4);
54+
55+
sum1 = Vector.Add(sum1, int1);
56+
sum2 = Vector.Add(sum2, int2);
57+
sum3 = Vector.Add(sum3, int3);
58+
sum4 = Vector.Add(sum4, int4);
59+
60+
current += valuesPerVector;
61+
}
62+
}
63+
64+
int missingElements = data.Length - (chunks * valuesPerVector);
65+
int offset = chunks * valuesPerVector;
66+
for (int i = 0; i < missingElements; i += dataLength)
67+
for (int j = 0; j < sums.Length; j++)
68+
sums[j] += data[offset + i + j];
69+
}
70+
71+
int value = 0;
72+
int sumIndex = 0;
73+
for (int j = 0; (j < INT_VECTOR_LENGTH) && (value < valuesPerVector); j++)
74+
{
75+
sums[sumIndex] += sum1[j];
76+
++sumIndex;
77+
++value;
78+
79+
if (sumIndex >= dataLength)
80+
sumIndex = 0;
81+
}
82+
83+
for (int j = 0; (j < INT_VECTOR_LENGTH) && (value < valuesPerVector); j++)
84+
{
85+
sums[sumIndex] += sum2[j];
86+
++sumIndex;
87+
++value;
88+
89+
if (sumIndex >= dataLength)
90+
sumIndex = 0;
91+
}
92+
93+
for (int j = 0; (j < INT_VECTOR_LENGTH) && (value < valuesPerVector); j++)
94+
{
95+
sums[sumIndex] += sum3[j];
96+
++sumIndex;
97+
++value;
98+
99+
if (sumIndex >= dataLength)
100+
sumIndex = 0;
101+
}
102+
103+
for (int j = 0; (j < INT_VECTOR_LENGTH) && (value < valuesPerVector); j++)
104+
{
105+
sums[sumIndex] += sum4[j];
106+
++sumIndex;
107+
++value;
108+
109+
if (sumIndex >= dataLength)
110+
sumIndex = 0;
111+
}
112+
}
113+
else
114+
{
115+
for (int y = 0; y < info.Height; y++)
116+
{
117+
ReadOnlySpan<byte> data = info[y];
118+
for (int i = 0; i < data.Length; i += dataLength)
119+
for (int j = 0; j < sums.Length; j++)
120+
sums[j] += data[i + j];
121+
}
122+
}
123+
124+
float divisor = count * byte.MaxValue;
125+
for (int i = 0; i < pixelData.Length; i++)
126+
pixelData[i] = (sums[i] / divisor).GetByteValueFromPercentage();
127+
}
128+
129+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
130+
private static byte GetByteValueFromPercentage(this float percentage)
131+
{
132+
if (float.IsNaN(percentage)) return 0;
133+
134+
percentage = percentage.Clamp(0, 1.0f);
135+
return (byte)(percentage >= 1.0f ? 255 : percentage * 256.0f);
136+
}
137+
138+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
139+
private static float Clamp(this float value, float min, float max)
140+
{
141+
// ReSharper disable ConvertIfStatementToReturnStatement - I'm not sure why, but inlining this statement reduces performance by ~10%
142+
if (value < min) return min;
143+
if (value > max) return max;
144+
return value;
145+
// ReSharper restore ConvertIfStatementToReturnStatement
146+
}
147+
148+
#endregion
149+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
// DarthAffe 07.09.2023: Copied from https://github.com/DarthAffe/RGB.NET/blob/2e0754f474b82ed4d0cae5c6c44378d234f1321b/RGB.NET.Core/Rendering/Textures/Sampler/SamplerInfo.cs
2+
3+
using System;
4+
5+
namespace ScreenCapture.NET.Downscale;
6+
7+
/// <summary>
8+
/// Represents the information used to sample data.
9+
/// </summary>
10+
/// <typeparam name="T">The type of the data to sample.</typeparam>
11+
internal readonly ref struct SamplerInfo<T>
12+
{
13+
#region Properties & Fields
14+
15+
private readonly ReadOnlySpan<T> _data;
16+
private readonly int _x;
17+
private readonly int _y;
18+
private readonly int _stride;
19+
private readonly int _dataPerPixel;
20+
private readonly int _dataWidth;
21+
22+
/// <summary>
23+
/// Gets the width of the region the data comes from.
24+
/// </summary>
25+
public readonly int Width;
26+
27+
/// <summary>
28+
/// Gets the height of region the data comes from.
29+
/// </summary>
30+
public readonly int Height;
31+
32+
/// <summary>
33+
/// Gets the data for the requested row.
34+
/// </summary>
35+
/// <param name="row">The row to get the data for.</param>
36+
/// <returns>A readonly span containing the data of the row.</returns>
37+
public ReadOnlySpan<T> this[int row] => _data.Slice((((_y + row) * _stride) + _x) * _dataPerPixel, _dataWidth);
38+
39+
#endregion
40+
41+
#region Constructors
42+
43+
/// <summary>
44+
/// Initializes a new instance of the <see cref="SamplerInfo{T}" /> class.
45+
/// </summary>
46+
/// <param name="width">The width of the region the data comes from.</param>
47+
/// <param name="height">The height of region the data comes from.</param>
48+
/// <param name="data">The data to sample.</param>
49+
public SamplerInfo(int x, int y, int width, int height, int stride, int dataPerPixel, in ReadOnlySpan<T> data)
50+
{
51+
this._x = x;
52+
this._y = y;
53+
this._data = data;
54+
this._stride = stride;
55+
this._dataPerPixel = dataPerPixel;
56+
this.Width = width;
57+
this.Height = height;
58+
59+
_dataWidth = width * dataPerPixel;
60+
}
61+
62+
#endregion
63+
}
705 Bytes
Loading
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
<PropertyGroup>
3+
<TargetFrameworks>net7.0;net6.0</TargetFrameworks>
4+
<RuntimeIdentifier>linux-x64</RuntimeIdentifier>
5+
<LangVersion>latest</LangVersion>
6+
<Nullable>enable</Nullable>
7+
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
8+
9+
<Authors>Darth Affe</Authors>
10+
<Company>Wyrez</Company>
11+
<Language>en-US</Language>
12+
<NeutralLanguage>en-US</NeutralLanguage>
13+
<Title>ScreenCapture.NET.X11</Title>
14+
<AssemblyName>ScreenCapture.NET.X11</AssemblyName>
15+
<AssemblyTitle>ScreenCapture.NET.X11</AssemblyTitle>
16+
<PackageId>ScreenCapture.NET.X11</PackageId>
17+
<RootNamespace>ScreenCapture.NET</RootNamespace>
18+
<Description>Vortice based Screen-Capturing</Description>
19+
<Summary>Vortice based Screen-Capturing using Desktop Duplication</Summary>
20+
<Copyright>Copyright © Darth Affe 2023</Copyright>
21+
<PackageCopyright>Copyright © Darth Affe 2023</PackageCopyright>
22+
<PackageIcon>icon.png</PackageIcon>
23+
<PackageProjectUrl>https://github.com/DarthAffe/ScreenCapture.NET</PackageProjectUrl>
24+
<PackageLicenseExpression>LGPL-2.1-only</PackageLicenseExpression>
25+
<RepositoryType>Github</RepositoryType>
26+
<RepositoryUrl>https://github.com/DarthAffe/ScreenCapture.NET</RepositoryUrl>
27+
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
28+
29+
<PackageReleaseNotes>
30+
</PackageReleaseNotes>
31+
32+
<Version>2.0.0</Version>
33+
<AssemblyVersion>2.0.0</AssemblyVersion>
34+
<FileVersion>2.0.0</FileVersion>
35+
36+
<OutputPath>..\bin\</OutputPath>
37+
<GenerateDocumentationFile>true</GenerateDocumentationFile>
38+
<IncludeSource>True</IncludeSource>
39+
<IncludeSymbols>True</IncludeSymbols>
40+
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
41+
</PropertyGroup>
42+
43+
<PropertyGroup Condition="'$(Configuration)'=='Debug'">
44+
<DefineConstants>$(DefineConstants);TRACE;DEBUG</DefineConstants>
45+
<DebugSymbols>true</DebugSymbols>
46+
<DebugType>full</DebugType>
47+
<Optimize>false</Optimize>
48+
</PropertyGroup>
49+
50+
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
51+
<DebugType>portable</DebugType>
52+
<Optimize>true</Optimize>
53+
<NoWarn>$(NoWarn);CS1591;CS1572;CS1573</NoWarn>
54+
<DefineConstants>$(DefineConstants);RELEASE</DefineConstants>
55+
</PropertyGroup>
56+
57+
<ItemGroup>
58+
<None Include="Resources\icon.png">
59+
<Pack>True</Pack>
60+
<PackagePath></PackagePath>
61+
</None>
62+
</ItemGroup>
63+
64+
<ItemGroup>
65+
<ProjectReference Include="..\ScreenCapture.NET\ScreenCapture.NET.csproj" />
66+
</ItemGroup>
67+
68+
</Project>

0 commit comments

Comments
 (0)