|
|
|
@ -17,51 +17,38 @@ namespace SixLabors.ImageSharp.Advanced |
|
|
|
/// </content>
|
|
|
|
public static partial class ParallelRowIterator |
|
|
|
{ |
|
|
|
private readonly struct IterationParameters |
|
|
|
{ |
|
|
|
public readonly int MinY; |
|
|
|
public readonly int MaxY; |
|
|
|
public readonly int StepY; |
|
|
|
public readonly int Width; |
|
|
|
|
|
|
|
public IterationParameters(int minY, int maxY, int stepY) |
|
|
|
: this(minY, maxY, stepY, 0) |
|
|
|
{ |
|
|
|
} |
|
|
|
|
|
|
|
public IterationParameters(int minY, int maxY, int stepY, int width) |
|
|
|
{ |
|
|
|
this.MinY = minY; |
|
|
|
this.MaxY = maxY; |
|
|
|
this.StepY = stepY; |
|
|
|
this.Width = width; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
private readonly struct RowOperationWrapper<T> |
|
|
|
where T : struct, IRowOperation |
|
|
|
{ |
|
|
|
private readonly IterationParameters info; |
|
|
|
private readonly int minY; |
|
|
|
private readonly int maxY; |
|
|
|
private readonly int stepY; |
|
|
|
private readonly T action; |
|
|
|
|
|
|
|
[MethodImpl(InliningOptions.ShortMethod)] |
|
|
|
public RowOperationWrapper(in IterationParameters info, in T action) |
|
|
|
public RowOperationWrapper( |
|
|
|
int minY, |
|
|
|
int maxY, |
|
|
|
int stepY, |
|
|
|
in T action) |
|
|
|
{ |
|
|
|
this.info = info; |
|
|
|
this.minY = minY; |
|
|
|
this.maxY = maxY; |
|
|
|
this.stepY = stepY; |
|
|
|
this.action = action; |
|
|
|
} |
|
|
|
|
|
|
|
[MethodImpl(InliningOptions.ShortMethod)] |
|
|
|
public void Invoke(int i) |
|
|
|
{ |
|
|
|
int yMin = this.info.MinY + (i * this.info.StepY); |
|
|
|
int yMin = this.minY + (i * this.stepY); |
|
|
|
|
|
|
|
if (yMin >= this.info.MaxY) |
|
|
|
if (yMin >= this.maxY) |
|
|
|
{ |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
int yMax = Math.Min(yMin + this.info.StepY, this.info.MaxY); |
|
|
|
int yMax = Math.Min(yMin + this.stepY, this.maxY); |
|
|
|
|
|
|
|
for (int y = yMin; y < yMax; y++) |
|
|
|
{ |
|
|
|
@ -75,17 +62,26 @@ namespace SixLabors.ImageSharp.Advanced |
|
|
|
where T : struct, IRowOperation<TBuffer> |
|
|
|
where TBuffer : unmanaged |
|
|
|
{ |
|
|
|
private readonly IterationParameters info; |
|
|
|
private readonly int minY; |
|
|
|
private readonly int maxY; |
|
|
|
private readonly int stepY; |
|
|
|
private readonly int width; |
|
|
|
private readonly MemoryAllocator allocator; |
|
|
|
private readonly T action; |
|
|
|
|
|
|
|
[MethodImpl(InliningOptions.ShortMethod)] |
|
|
|
public RowOperationWrapper( |
|
|
|
in IterationParameters info, |
|
|
|
int minY, |
|
|
|
int maxY, |
|
|
|
int stepY, |
|
|
|
int width, |
|
|
|
MemoryAllocator allocator, |
|
|
|
in T action) |
|
|
|
{ |
|
|
|
this.info = info; |
|
|
|
this.minY = minY; |
|
|
|
this.maxY = maxY; |
|
|
|
this.stepY = stepY; |
|
|
|
this.width = width; |
|
|
|
this.allocator = allocator; |
|
|
|
this.action = action; |
|
|
|
} |
|
|
|
@ -93,16 +89,16 @@ namespace SixLabors.ImageSharp.Advanced |
|
|
|
[MethodImpl(InliningOptions.ShortMethod)] |
|
|
|
public void Invoke(int i) |
|
|
|
{ |
|
|
|
int yMin = this.info.MinY + (i * this.info.StepY); |
|
|
|
int yMin = this.minY + (i * this.stepY); |
|
|
|
|
|
|
|
if (yMin >= this.info.MaxY) |
|
|
|
if (yMin >= this.maxY) |
|
|
|
{ |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
int yMax = Math.Min(yMin + this.info.StepY, this.info.MaxY); |
|
|
|
int yMax = Math.Min(yMin + this.stepY, this.maxY); |
|
|
|
|
|
|
|
using IMemoryOwner<TBuffer> buffer = this.allocator.Allocate<TBuffer>(this.info.Width); |
|
|
|
using IMemoryOwner<TBuffer> buffer = this.allocator.Allocate<TBuffer>(this.width); |
|
|
|
|
|
|
|
Span<TBuffer> span = buffer.Memory.Span; |
|
|
|
|
|
|
|
@ -116,27 +112,35 @@ namespace SixLabors.ImageSharp.Advanced |
|
|
|
private readonly struct RowIntervalOperationWrapper<T> |
|
|
|
where T : struct, IRowIntervalOperation |
|
|
|
{ |
|
|
|
private readonly IterationParameters info; |
|
|
|
private readonly int minY; |
|
|
|
private readonly int maxY; |
|
|
|
private readonly int stepY; |
|
|
|
private readonly T operation; |
|
|
|
|
|
|
|
[MethodImpl(InliningOptions.ShortMethod)] |
|
|
|
public RowIntervalOperationWrapper(in IterationParameters info, in T operation) |
|
|
|
public RowIntervalOperationWrapper( |
|
|
|
int minY, |
|
|
|
int maxY, |
|
|
|
int stepY, |
|
|
|
in T operation) |
|
|
|
{ |
|
|
|
this.info = info; |
|
|
|
this.minY = minY; |
|
|
|
this.maxY = maxY; |
|
|
|
this.stepY = stepY; |
|
|
|
this.operation = operation; |
|
|
|
} |
|
|
|
|
|
|
|
[MethodImpl(InliningOptions.ShortMethod)] |
|
|
|
public void Invoke(int i) |
|
|
|
{ |
|
|
|
int yMin = this.info.MinY + (i * this.info.StepY); |
|
|
|
int yMin = this.minY + (i * this.stepY); |
|
|
|
|
|
|
|
if (yMin >= this.info.MaxY) |
|
|
|
if (yMin >= this.maxY) |
|
|
|
{ |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
int yMax = Math.Min(yMin + this.info.StepY, this.info.MaxY); |
|
|
|
int yMax = Math.Min(yMin + this.stepY, this.maxY); |
|
|
|
var rows = new RowInterval(yMin, yMax); |
|
|
|
|
|
|
|
// Skip the safety copy when invoking a potentially impure method on a readonly field
|
|
|
|
@ -148,17 +152,26 @@ namespace SixLabors.ImageSharp.Advanced |
|
|
|
where T : struct, IRowIntervalOperation<TBuffer> |
|
|
|
where TBuffer : unmanaged |
|
|
|
{ |
|
|
|
private readonly IterationParameters info; |
|
|
|
private readonly int minY; |
|
|
|
private readonly int maxY; |
|
|
|
private readonly int stepY; |
|
|
|
private readonly int width; |
|
|
|
private readonly MemoryAllocator allocator; |
|
|
|
private readonly T operation; |
|
|
|
|
|
|
|
[MethodImpl(InliningOptions.ShortMethod)] |
|
|
|
public RowIntervalOperationWrapper( |
|
|
|
in IterationParameters info, |
|
|
|
int minY, |
|
|
|
int maxY, |
|
|
|
int stepY, |
|
|
|
int width, |
|
|
|
MemoryAllocator allocator, |
|
|
|
in T operation) |
|
|
|
{ |
|
|
|
this.info = info; |
|
|
|
this.minY = minY; |
|
|
|
this.maxY = maxY; |
|
|
|
this.stepY = stepY; |
|
|
|
this.width = width; |
|
|
|
this.allocator = allocator; |
|
|
|
this.operation = operation; |
|
|
|
} |
|
|
|
@ -166,17 +179,17 @@ namespace SixLabors.ImageSharp.Advanced |
|
|
|
[MethodImpl(InliningOptions.ShortMethod)] |
|
|
|
public void Invoke(int i) |
|
|
|
{ |
|
|
|
int yMin = this.info.MinY + (i * this.info.StepY); |
|
|
|
int yMin = this.minY + (i * this.stepY); |
|
|
|
|
|
|
|
if (yMin >= this.info.MaxY) |
|
|
|
if (yMin >= this.maxY) |
|
|
|
{ |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
int yMax = Math.Min(yMin + this.info.StepY, this.info.MaxY); |
|
|
|
int yMax = Math.Min(yMin + this.stepY, this.maxY); |
|
|
|
var rows = new RowInterval(yMin, yMax); |
|
|
|
|
|
|
|
using IMemoryOwner<TBuffer> buffer = this.allocator.Allocate<TBuffer>(this.info.Width); |
|
|
|
using IMemoryOwner<TBuffer> buffer = this.allocator.Allocate<TBuffer>(this.width); |
|
|
|
|
|
|
|
Unsafe.AsRef(in this.operation).Invoke(in rows, buffer.Memory.Span); |
|
|
|
} |
|
|
|
|