[Ryujinx.HLE] Address dotnet-format issues (#5380)

* dotnet format style --severity info

Some changes were manually reverted.

* dotnet format analyzers --serverity info

Some changes have been minimally adapted.

* Restore a few unused methods and variables

* Silence dotnet format IDE0060 warnings

* Silence dotnet format IDE0052 warnings

* Address or silence dotnet format IDE1006 warnings

* Address dotnet format CA1816 warnings

* Address or silence dotnet format CA2208 warnings

* Address or silence dotnet format CA1806 and a few CA1854 warnings

* Address dotnet format CA2211 warnings

* Address dotnet format CA1822 warnings

* Address or silence dotnet format CA1069 warnings

* Make dotnet format succeed in style mode

* Address or silence dotnet format CA2211 warnings

* Address review comments

* Address dotnet format CA2208 warnings properly

* Make ProcessResult readonly

* Address most dotnet format whitespace warnings

* Apply dotnet format whitespace formatting

A few of them have been manually reverted and the corresponding warning was silenced

* Add previously silenced warnings back

I have no clue how these disappeared

* Revert formatting changes for while and for-loops

* Format if-blocks correctly

* Run dotnet format style after rebase

* Run dotnet format whitespace after rebase

* Run dotnet format style after rebase

* Run dotnet format analyzers after rebase

* Run dotnet format after rebase and remove unused usings

- analyzers
- style
- whitespace

* Disable 'prefer switch expression' rule

* Add comments to disabled warnings

* Fix a few disabled warnings

* Fix naming rule violation, Convert shader properties to auto-property and convert values to const

* Simplify properties and array initialization, Use const when possible, Remove trailing commas

* Start working on disabled warnings

* Fix and silence a few dotnet-format warnings again

* Run dotnet format after rebase

* Use using declaration instead of block syntax

* Address IDE0251 warnings

* Address a few disabled IDE0060 warnings

* Silence IDE0060 in .editorconfig

* Revert "Simplify properties and array initialization, Use const when possible, Remove trailing commas"

This reverts commit 9462e4136c0a2100dc28b20cf9542e06790aa67e.

* dotnet format whitespace after rebase

* First dotnet format pass

* Fix naming rule violations

* Fix typo

* Add trailing commas, use targeted new and use array initializer

* Fix build issues

* Fix remaining build issues

* Remove SuppressMessage for CA1069 where possible

* Address dotnet format issues

* Address formatting issues

Co-authored-by: Ac_K <acoustik666@gmail.com>

* Add GetHashCode implementation for RenderingSurfaceInfo

* Explicitly silence CA1822 for every affected method in Syscall

* Address formatting issues in Demangler.cs

* Address review feedback

Co-authored-by: Ac_K <acoustik666@gmail.com>

* Revert marking service methods as static

* Next dotnet format pass

* Address review feedback

---------

Co-authored-by: Ac_K <acoustik666@gmail.com>
This commit is contained in:
TSRBerry 2023-07-16 19:31:14 +02:00 committed by GitHub
parent fec8291c17
commit 326749498b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
1015 changed files with 8173 additions and 7615 deletions

View file

@ -5,7 +5,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
{
class BufferItemConsumer : ConsumerBase
{
private GpuContext _gpuContext;
private readonly GpuContext _gpuContext;
public BufferItemConsumer(Switch device,
BufferQueueConsumer consumer,

View file

@ -4,7 +4,7 @@
{
public static BufferQueueCore CreateBufferQueue(Switch device, ulong pid, out BufferQueueProducer producer, out BufferQueueConsumer consumer)
{
BufferQueueCore core = new BufferQueueCore(device, pid);
BufferQueueCore core = new(device, pid);
producer = new BufferQueueProducer(core, device.System.TickSource);
consumer = new BufferQueueConsumer(core);

View file

@ -54,10 +54,10 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
if (Core.StillTracking(ref bufferItem))
{
Core.Slots[bufferItem.Slot].AcquireCalled = true;
Core.Slots[bufferItem.Slot].AcquireCalled = true;
Core.Slots[bufferItem.Slot].NeedsCleanupOnRelease = true;
Core.Slots[bufferItem.Slot].BufferState = BufferState.Acquired;
Core.Slots[bufferItem.Slot].Fence = AndroidFence.NoFence;
Core.Slots[bufferItem.Slot].BufferState = BufferState.Acquired;
Core.Slots[bufferItem.Slot].Fence = AndroidFence.NoFence;
ulong targetFrameNumber = Core.Slots[bufferItem.Slot].FrameNumber;
@ -159,12 +159,12 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
Core.Slots[slot].GraphicBuffer.Set(graphicBuffer);
Core.Slots[slot].BufferState = BufferState.Acquired;
Core.Slots[slot].AttachedByConsumer = true;
Core.Slots[slot].BufferState = BufferState.Acquired;
Core.Slots[slot].AttachedByConsumer = true;
Core.Slots[slot].NeedsCleanupOnRelease = false;
Core.Slots[slot].Fence = AndroidFence.NoFence;
Core.Slots[slot].FrameNumber = 0;
Core.Slots[slot].AcquireCalled = false;
Core.Slots[slot].Fence = AndroidFence.NoFence;
Core.Slots[slot].FrameNumber = 0;
Core.Slots[slot].AcquireCalled = false;
}
return Status.Success;
@ -197,7 +197,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
if (Core.Slots[slot].BufferState == BufferState.Acquired)
{
Core.Slots[slot].BufferState = BufferState.Free;
Core.Slots[slot].Fence = fence;
Core.Slots[slot].Fence = fence;
listener = Core.ProducerListener;
}
@ -237,7 +237,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
return Status.NoInit;
}
Core.ConsumerListener = consumerListener;
Core.ConsumerListener = consumerListener;
Core.ConsumerControlledByApp = controlledByApp;
}
@ -253,7 +253,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
return Status.BadValue;
}
Core.IsAbandoned = true;
Core.IsAbandoned = true;
Core.ConsumerListener = null;
Core.Queue.Clear();
@ -304,7 +304,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
lock (Core.Lock)
{
Core.DefaultWidth = (int)width;
Core.DefaultWidth = (int)width;
Core.DefaultHeight = (int)height;
}

View file

@ -9,35 +9,35 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
{
class BufferQueueCore
{
public BufferSlotArray Slots;
public int OverrideMaxBufferCount;
public bool UseAsyncBuffer;
public bool DequeueBufferCannotBlock;
public PixelFormat DefaultBufferFormat;
public int DefaultWidth;
public int DefaultHeight;
public int DefaultMaxBufferCount;
public int MaxAcquiredBufferCount;
public bool BufferHasBeenQueued;
public ulong FrameCounter;
public BufferSlotArray Slots;
public int OverrideMaxBufferCount;
public bool UseAsyncBuffer;
public bool DequeueBufferCannotBlock;
public PixelFormat DefaultBufferFormat;
public int DefaultWidth;
public int DefaultHeight;
public int DefaultMaxBufferCount;
public int MaxAcquiredBufferCount;
public bool BufferHasBeenQueued;
public ulong FrameCounter;
public NativeWindowTransform TransformHint;
public bool IsAbandoned;
public NativeWindowApi ConnectedApi;
public bool IsAllocating;
public IProducerListener ProducerListener;
public IConsumerListener ConsumerListener;
public bool ConsumerControlledByApp;
public uint ConsumerUsageBits;
public List<BufferItem> Queue;
public BufferInfo[] BufferHistory;
public uint BufferHistoryPosition;
public bool EnableExternalEvent;
public int MaxBufferCountCached;
public bool IsAbandoned;
public NativeWindowApi ConnectedApi;
public bool IsAllocating;
public IProducerListener ProducerListener;
public IConsumerListener ConsumerListener;
public bool ConsumerControlledByApp;
public uint ConsumerUsageBits;
public List<BufferItem> Queue;
public BufferInfo[] BufferHistory;
public uint BufferHistoryPosition;
public bool EnableExternalEvent;
public int MaxBufferCountCached;
public readonly object Lock = new();
private KEvent _waitBufferFreeEvent;
private KEvent _frameAvailableEvent;
private readonly KEvent _waitBufferFreeEvent;
private readonly KEvent _frameAvailableEvent;
public ulong Owner { get; }
@ -49,36 +49,36 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
public BufferQueueCore(Switch device, ulong pid)
{
Slots = new BufferSlotArray();
IsAbandoned = false;
OverrideMaxBufferCount = 0;
Slots = new BufferSlotArray();
IsAbandoned = false;
OverrideMaxBufferCount = 0;
DequeueBufferCannotBlock = false;
UseAsyncBuffer = false;
DefaultWidth = 1;
DefaultHeight = 1;
DefaultMaxBufferCount = 2;
MaxAcquiredBufferCount = 1;
FrameCounter = 0;
TransformHint = 0;
DefaultBufferFormat = PixelFormat.Rgba8888;
IsAllocating = false;
ProducerListener = null;
ConsumerListener = null;
ConsumerUsageBits = 0;
UseAsyncBuffer = false;
DefaultWidth = 1;
DefaultHeight = 1;
DefaultMaxBufferCount = 2;
MaxAcquiredBufferCount = 1;
FrameCounter = 0;
TransformHint = 0;
DefaultBufferFormat = PixelFormat.Rgba8888;
IsAllocating = false;
ProducerListener = null;
ConsumerListener = null;
ConsumerUsageBits = 0;
Queue = new List<BufferItem>();
// TODO: CreateGraphicBufferAlloc?
_waitBufferFreeEvent = new KEvent(device.System.KernelContext);
_waitBufferFreeEvent = new KEvent(device.System.KernelContext);
_frameAvailableEvent = new KEvent(device.System.KernelContext);
Owner = pid;
Active = true;
BufferHistory = new BufferInfo[BufferHistoryArraySize];
EnableExternalEvent = true;
BufferHistory = new BufferInfo[BufferHistoryArraySize];
EnableExternalEvent = true;
MaxBufferCountCached = 0;
}
@ -220,9 +220,9 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
Slots[slot].NeedsCleanupOnRelease = true;
}
Slots[slot].BufferState = BufferState.Free;
Slots[slot].FrameNumber = uint.MaxValue;
Slots[slot].AcquireCalled = false;
Slots[slot].BufferState = BufferState.Free;
Slots[slot].FrameNumber = uint.MaxValue;
Slots[slot].AcquireCalled = false;
Slots[slot].Fence.FenceCount = 0;
}
@ -259,7 +259,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
return;
}
bool needBufferReleaseSignal = false;
bool needBufferReleaseSignal = false;
bool needFrameAvailableSignal = false;
if (maxBufferCount > 1)

View file

@ -15,7 +15,9 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
private readonly ITickSource _tickSource;
#pragma warning disable IDE0052 // Remove unread private member
private uint _stickyTransform;
#pragma warning restore IDE0052
private uint _nextCallbackTicket;
private uint _currentCallbackTicket;
@ -28,9 +30,9 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
Core = core;
_tickSource = tickSource;
_stickyTransform = 0;
_callbackTicket = 0;
_nextCallbackTicket = 0;
_stickyTransform = 0;
_callbackTicket = 0;
_nextCallbackTicket = 0;
_currentCallbackTicket = 0;
}
@ -134,7 +136,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
{
if ((width == 0 && height != 0) || (height == 0 && width != 0))
{
slot = BufferSlotArray.InvalidBufferSlot;
slot = BufferSlotArray.InvalidBufferSlot;
fence = AndroidFence.NoFence;
return Status.BadValue;
@ -157,7 +159,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
if (status != Status.Success)
{
slot = BufferSlotArray.InvalidBufferSlot;
slot = BufferSlotArray.InvalidBufferSlot;
fence = AndroidFence.NoFence;
return status;
@ -176,7 +178,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
if (width == 0 || height == 0)
{
width = (uint)Core.DefaultWidth;
width = (uint)Core.DefaultWidth;
height = (uint)Core.DefaultHeight;
}
@ -190,7 +192,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
{
if (!Core.Slots[slot].IsPreallocated)
{
slot = BufferSlotArray.InvalidBufferSlot;
slot = BufferSlotArray.InvalidBufferSlot;
fence = AndroidFence.NoFence;
return Status.NoMemory;
@ -202,7 +204,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
$"available: Width = {graphicBuffer.Width} Height = {graphicBuffer.Height} Format = {graphicBuffer.Format} Usage = {graphicBuffer.Usage:x} " +
$"requested: Width = {width} Height = {height} Format = {format} Usage = {usage:x}");
slot = BufferSlotArray.InvalidBufferSlot;
slot = BufferSlotArray.InvalidBufferSlot;
fence = AndroidFence.NoFence;
return Status.NoInit;
@ -215,8 +217,8 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
fence = Core.Slots[slot].Fence;
Core.Slots[slot].Fence = AndroidFence.NoFence;
Core.Slots[slot].QueueTime = TimeSpanType.Zero;
Core.Slots[slot].Fence = AndroidFence.NoFence;
Core.Slots[slot].QueueTime = TimeSpanType.Zero;
Core.Slots[slot].PresentationTime = TimeSpanType.Zero;
Core.CheckSystemEventsLocked(Core.GetMaxBufferCountLocked(async));
@ -267,7 +269,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
if (Core.IsAbandoned)
{
graphicBuffer = default;
fence = AndroidFence.NoFence;
fence = AndroidFence.NoFence;
return Status.NoInit;
}
@ -288,13 +290,13 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
if (nextBufferSlot == BufferSlotArray.InvalidBufferSlot)
{
graphicBuffer = default;
fence = AndroidFence.NoFence;
fence = AndroidFence.NoFence;
return Status.NoMemory;
}
graphicBuffer = Core.Slots[nextBufferSlot].GraphicBuffer;
fence = Core.Slots[nextBufferSlot].Fence;
fence = Core.Slots[nextBufferSlot].Fence;
Core.FreeBufferLocked(nextBufferSlot);
@ -326,8 +328,8 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
Core.Slots[slot].GraphicBuffer.Set(graphicBuffer);
Core.Slots[slot].BufferState = BufferState.Dequeued;
Core.Slots[slot].Fence = AndroidFence.NoFence;
Core.Slots[slot].BufferState = BufferState.Dequeued;
Core.Slots[slot].Fence = AndroidFence.NoFence;
Core.Slots[slot].RequestBufferCalled = true;
return returnFlags;
@ -350,10 +352,10 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
return Status.BadValue;
}
BufferItem item = new BufferItem();
BufferItem item = new();
IConsumerListener frameAvailableListener = null;
IConsumerListener frameReplaceListener = null;
IConsumerListener frameReplaceListener = null;
lock (Core.Lock)
{
@ -388,25 +390,25 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
return Status.BadValue;
}
Core.Slots[slot].Fence = input.Fence;
Core.Slots[slot].Fence = input.Fence;
Core.Slots[slot].BufferState = BufferState.Queued;
Core.FrameCounter++;
Core.Slots[slot].FrameNumber = Core.FrameCounter;
Core.Slots[slot].QueueTime = TimeSpanType.FromTimeSpan(_tickSource.ElapsedTime);
Core.Slots[slot].FrameNumber = Core.FrameCounter;
Core.Slots[slot].QueueTime = TimeSpanType.FromTimeSpan(_tickSource.ElapsedTime);
Core.Slots[slot].PresentationTime = TimeSpanType.Zero;
item.AcquireCalled = Core.Slots[slot].AcquireCalled;
item.Crop = input.Crop;
item.Transform = input.Transform;
item.AcquireCalled = Core.Slots[slot].AcquireCalled;
item.Crop = input.Crop;
item.Transform = input.Transform;
item.TransformToDisplayInverse = (input.Transform & NativeWindowTransform.InverseDisplay) == NativeWindowTransform.InverseDisplay;
item.ScalingMode = input.ScalingMode;
item.Timestamp = input.Timestamp;
item.IsAutoTimestamp = input.IsAutoTimestamp != 0;
item.SwapInterval = input.SwapInterval;
item.FrameNumber = Core.FrameCounter;
item.Slot = slot;
item.Fence = input.Fence;
item.IsDroppable = Core.DequeueBufferCannotBlock || input.Async != 0;
item.ScalingMode = input.ScalingMode;
item.Timestamp = input.Timestamp;
item.IsAutoTimestamp = input.IsAutoTimestamp != 0;
item.SwapInterval = input.SwapInterval;
item.FrameNumber = Core.FrameCounter;
item.Slot = slot;
item.Fence = input.Fence;
item.IsDroppable = Core.DequeueBufferCannotBlock || input.Async != 0;
item.GraphicBuffer.Set(Core.Slots[slot].GraphicBuffer);
item.GraphicBuffer.Object.IncrementNvMapHandleRefCount(Core.Owner);
@ -416,8 +418,8 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
Core.BufferHistory[Core.BufferHistoryPosition] = new BufferInfo
{
FrameNumber = Core.FrameCounter,
QueueTime = Core.Slots[slot].QueueTime,
State = BufferState.Queued
QueueTime = Core.Slots[slot].QueueTime,
State = BufferState.Queued,
};
_stickyTransform = input.StickyTransform;
@ -460,10 +462,10 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
output = new QueueBufferOutput
{
Width = (uint)Core.DefaultWidth,
Height = (uint)Core.DefaultHeight,
TransformHint = Core.TransformHint,
NumPendingBuffers = (uint)Core.Queue.Count
Width = (uint)Core.DefaultWidth,
Height = (uint)Core.DefaultHeight,
TransformHint = Core.TransformHint,
NumPendingBuffers = (uint)Core.Queue.Count,
};
if ((input.StickyTransform & 8) != 0)
@ -506,7 +508,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
Core.Slots[slot].BufferState = BufferState.Free;
Core.Slots[slot].FrameNumber = 0;
Core.Slots[slot].Fence = fence;
Core.Slots[slot].Fence = fence;
Core.SignalDequeueEvent();
Core.SignalWaitBufferFreeEvent();
}
@ -568,7 +570,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
return Status.BadValue;
}
Core.BufferHasBeenQueued = false;
Core.BufferHasBeenQueued = false;
Core.DequeueBufferCannotBlock = Core.ConsumerControlledByApp && producerControlledByApp;
switch (api)
@ -578,11 +580,11 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
case NativeWindowApi.Media:
case NativeWindowApi.Camera:
Core.ProducerListener = listener;
Core.ConnectedApi = api;
Core.ConnectedApi = api;
output.Width = (uint)Core.DefaultWidth;
output.Height = (uint)Core.DefaultHeight;
output.TransformHint = Core.TransformHint;
output.Width = (uint)Core.DefaultWidth;
output.Height = (uint)Core.DefaultHeight;
output.TransformHint = Core.TransformHint;
output.NumPendingBuffers = (uint)Core.Queue.Count;
if (NxSettings.Settings.TryGetValue("nv!nvn_no_vsync_capability", out object noVSyncCapability) && (bool)noVSyncCapability)
@ -627,7 +629,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
producerListener = Core.ProducerListener;
Core.ProducerListener = null;
Core.ConnectedApi = NativeWindowApi.NoApi;
Core.ConnectedApi = NativeWindowApi.NoApi;
Core.SignalWaitBufferFreeEvent();
Core.SignalFrameAvailableEvent();
@ -667,13 +669,13 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
lock (Core.Lock)
{
Core.Slots[slot].BufferState = BufferState.Free;
Core.Slots[slot].Fence = AndroidFence.NoFence;
Core.Slots[slot].RequestBufferCalled = false;
Core.Slots[slot].AcquireCalled = false;
Core.Slots[slot].BufferState = BufferState.Free;
Core.Slots[slot].Fence = AndroidFence.NoFence;
Core.Slots[slot].RequestBufferCalled = false;
Core.Slots[slot].AcquireCalled = false;
Core.Slots[slot].NeedsCleanupOnRelease = false;
Core.Slots[slot].IsPreallocated = !graphicBuffer.IsNull;
Core.Slots[slot].FrameNumber = 0;
Core.Slots[slot].IsPreallocated = !graphicBuffer.IsNull;
Core.Slots[slot].FrameNumber = 0;
Core.Slots[slot].GraphicBuffer.Set(graphicBuffer);
@ -689,8 +691,8 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
{
// NOTE: Nintendo set the default width, height and format from the GraphicBuffer..
// This is entirely wrong and should only be controlled by the consumer...
Core.DefaultWidth = graphicBuffer.Object.Width;
Core.DefaultHeight = graphicBuffer.Object.Height;
Core.DefaultWidth = graphicBuffer.Object.Width;
Core.DefaultHeight = graphicBuffer.Object.Height;
Core.DefaultBufferFormat = graphicBuffer.Object.Format;
}
else
@ -729,7 +731,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
{
bool tryAgain = true;
freeSlot = BufferSlotArray.InvalidBufferSlot;
freeSlot = BufferSlotArray.InvalidBufferSlot;
returnStatus = Status.Success;
while (tryAgain)

View file

@ -6,24 +6,24 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
class BufferSlot
{
public AndroidStrongPointer<GraphicBuffer> GraphicBuffer;
public BufferState BufferState;
public bool RequestBufferCalled;
public ulong FrameNumber;
public AndroidFence Fence;
public bool AcquireCalled;
public bool NeedsCleanupOnRelease;
public bool AttachedByConsumer;
public TimeSpanType QueueTime;
public TimeSpanType PresentationTime;
public bool IsPreallocated;
public BufferState BufferState;
public bool RequestBufferCalled;
public ulong FrameNumber;
public AndroidFence Fence;
public bool AcquireCalled;
public bool NeedsCleanupOnRelease;
public bool AttachedByConsumer;
public TimeSpanType QueueTime;
public TimeSpanType PresentationTime;
public bool IsPreallocated;
public BufferSlot()
{
GraphicBuffer = new AndroidStrongPointer<GraphicBuffer>();
BufferState = BufferState.Free;
QueueTime = TimeSpanType.Zero;
GraphicBuffer = new AndroidStrongPointer<GraphicBuffer>();
BufferState = BufferState.Free;
QueueTime = TimeSpanType.Zero;
PresentationTime = TimeSpanType.Zero;
IsPreallocated = false;
IsPreallocated = false;
}
}
}

View file

@ -3,11 +3,11 @@
class BufferSlotArray
{
// TODO: move to BufferQueue
public const int NumBufferSlots = 0x40;
public const int NumBufferSlots = 0x40;
public const int MaxAcquiredBuffers = NumBufferSlots - 2;
public const int InvalidBufferSlot = -1;
public const int InvalidBufferSlot = -1;
private BufferSlot[] _raw = new BufferSlot[NumBufferSlots];
private readonly BufferSlot[] _raw = new BufferSlot[NumBufferSlots];
public BufferSlotArray()
{

View file

@ -8,8 +8,8 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
public class Slot
{
public AndroidStrongPointer<GraphicBuffer> GraphicBuffer;
public AndroidFence Fence;
public ulong FrameNumber;
public AndroidFence Fence;
public ulong FrameNumber;
public Slot()
{
@ -25,7 +25,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
protected readonly object Lock = new();
private IConsumerListener _listener;
private readonly IConsumerListener _listener;
public ConsumerBase(BufferQueueConsumer consumer, bool controlledByApp, IConsumerListener listener)
{
@ -35,8 +35,8 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
}
IsAbandoned = false;
Consumer = consumer;
_listener = listener;
Consumer = consumer;
_listener = listener;
Status connectStatus = consumer.Connect(this, controlledByApp);
@ -81,7 +81,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
{
Slots[slotIndex].GraphicBuffer.Reset();
Slots[slotIndex].Fence = AndroidFence.NoFence;
Slots[slotIndex].Fence = AndroidFence.NoFence;
Slots[slotIndex].FrameNumber = 0;
}
@ -123,7 +123,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
}
Slots[bufferItem.Slot].FrameNumber = bufferItem.FrameNumber;
Slots[bufferItem.Slot].Fence = bufferItem.Fence;
Slots[bufferItem.Slot].Fence = bufferItem.Fence;
return Status.Success;
}

View file

@ -7,11 +7,11 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
{
class HOSBinderDriverServer : IHOSBinderDriver
{
private static Dictionary<int, IBinder> _registeredBinderObjects = new Dictionary<int, IBinder>();
private static readonly Dictionary<int, IBinder> _registeredBinderObjects = new();
private static int _lastBinderId = 0;
private static object _lock = new object();
private static readonly object _lock = new();
public static int RegisterBinderObject(IBinder binder)
{

View file

@ -13,10 +13,10 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
ResultCode OnTransact(uint code, uint flags, ReadOnlySpan<byte> inputParcel, Span<byte> outputParcel)
{
Parcel inputParcelReader = new Parcel(inputParcel.ToArray());
Parcel inputParcelReader = new(inputParcel.ToArray());
// TODO: support objects?
Parcel outputParcelWriter = new Parcel((uint)(outputParcel.Length - Unsafe.SizeOf<ParcelHeader>()), 0);
Parcel outputParcelWriter = new((uint)(outputParcel.Length - Unsafe.SizeOf<ParcelHeader>()), 0);
string inputInterfaceToken = inputParcelReader.ReadInterfaceToken();

View file

@ -29,33 +29,33 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
SetPreallocatedBuffer,
Reserved15,
GetBufferInfo,
GetBufferHistory
GetBufferHistory,
}
[StructLayout(LayoutKind.Sequential, Pack = 1, Size = 0x54)]
public struct QueueBufferInput : IFlattenable
{
public long Timestamp;
public int IsAutoTimestamp;
public Rect Crop;
public long Timestamp;
public int IsAutoTimestamp;
public Rect Crop;
public NativeWindowScalingMode ScalingMode;
public NativeWindowTransform Transform;
public uint StickyTransform;
public int Async;
public int SwapInterval;
public AndroidFence Fence;
public NativeWindowTransform Transform;
public uint StickyTransform;
public int Async;
public int SwapInterval;
public AndroidFence Fence;
public void Flatten(Parcel parcel)
{
parcel.WriteUnmanagedType(ref this);
}
public uint GetFdCount()
public readonly uint GetFdCount()
{
return 0;
}
public uint GetFlattenedSize()
public readonly uint GetFlattenedSize()
{
return (uint)Unsafe.SizeOf<QueueBufferInput>();
}
@ -68,11 +68,11 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
public struct QueueBufferOutput
{
public uint Width;
public uint Height;
public uint Width;
public uint Height;
public NativeWindowTransform TransformHint;
public uint NumPendingBuffers;
public ulong FrameNumber;
public uint NumPendingBuffers;
public ulong FrameNumber;
public void WriteToParcel(Parcel parcel)
{
@ -108,15 +108,15 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
public void OnTransact(uint code, uint flags, Parcel inputParcel, Parcel outputParcel)
{
Status status = Status.Success;
int slot;
AndroidFence fence;
QueueBufferInput queueInput;
Status status = Status.Success;
int slot;
AndroidFence fence;
QueueBufferInput queueInput;
QueueBufferOutput queueOutput;
NativeWindowApi api;
NativeWindowApi api;
AndroidStrongPointer<GraphicBuffer> graphicBuffer;
AndroidStrongPointer<AndroidFence> strongFence;
AndroidStrongPointer<AndroidFence> strongFence;
switch ((TransactionCode)code)
{
@ -139,13 +139,13 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
break;
case TransactionCode.DequeueBuffer:
bool async = inputParcel.ReadBoolean();
uint width = inputParcel.ReadUInt32();
uint height = inputParcel.ReadUInt32();
bool async = inputParcel.ReadBoolean();
uint width = inputParcel.ReadUInt32();
uint height = inputParcel.ReadUInt32();
PixelFormat format = inputParcel.ReadUnmanagedType<PixelFormat>();
uint usage = inputParcel.ReadUInt32();
uint usage = inputParcel.ReadUInt32();
status = DequeueBuffer(out int dequeueSlot, out fence, async, width, height, format, usage);
status = DequeueBuffer(out int dequeueSlot, out fence, async, width, height, format, usage);
strongFence = new AndroidStrongPointer<AndroidFence>(fence);
outputParcel.WriteInt32(dequeueSlot);
@ -163,7 +163,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
break;
case TransactionCode.DetachNextBuffer:
status = DetachNextBuffer(out graphicBuffer, out fence);
status = DetachNextBuffer(out graphicBuffer, out fence);
strongFence = new AndroidStrongPointer<AndroidFence>(fence);
outputParcel.WriteStrongPointer(ref graphicBuffer);
@ -183,7 +183,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
break;
case TransactionCode.QueueBuffer:
slot = inputParcel.ReadInt32();
slot = inputParcel.ReadInt32();
queueInput = inputParcel.ReadFlattenable<QueueBufferInput>();
status = QueueBuffer(slot, ref queueInput, out queueOutput);
@ -194,7 +194,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
break;
case TransactionCode.CancelBuffer:
slot = inputParcel.ReadInt32();
slot = inputParcel.ReadInt32();
fence = inputParcel.ReadFlattenable<AndroidFence>();
CancelBuffer(slot, ref fence);

View file

@ -17,18 +17,18 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
{
int binderId = context.RequestData.ReadInt32();
uint code = context.RequestData.ReadUInt32();
uint code = context.RequestData.ReadUInt32();
uint flags = context.RequestData.ReadUInt32();
ulong dataPos = context.Request.SendBuff[0].Position;
ulong dataPos = context.Request.SendBuff[0].Position;
ulong dataSize = context.Request.SendBuff[0].Size;
ulong replyPos = context.Request.ReceiveBuff[0].Position;
ulong replyPos = context.Request.ReceiveBuff[0].Position;
ulong replySize = context.Request.ReceiveBuff[0].Size;
ReadOnlySpan<byte> inputParcel = context.Memory.GetSpan(dataPos, (int)dataSize);
Span<byte> outputParcel = new Span<byte>(new byte[replySize]);
Span<byte> outputParcel = new(new byte[replySize]);
ResultCode result = OnTransact(binderId, code, flags, inputParcel, outputParcel);
@ -45,8 +45,8 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
public ResultCode AdjustRefcount(ServiceCtx context)
{
int binderId = context.RequestData.ReadInt32();
int addVal = context.RequestData.ReadInt32();
int type = context.RequestData.ReadInt32();
int addVal = context.RequestData.ReadInt32();
int type = context.RequestData.ReadInt32();
return AdjustRefcount(binderId, addVal, type);
}
@ -77,27 +77,26 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
{
int binderId = context.RequestData.ReadInt32();
uint code = context.RequestData.ReadUInt32();
uint code = context.RequestData.ReadUInt32();
uint flags = context.RequestData.ReadUInt32();
(ulong dataPos, ulong dataSize) = context.Request.GetBufferType0x21();
(ulong dataPos, ulong dataSize) = context.Request.GetBufferType0x21();
(ulong replyPos, ulong replySize) = context.Request.GetBufferType0x22();
ReadOnlySpan<byte> inputParcel = context.Memory.GetSpan(dataPos, (int)dataSize);
using (IMemoryOwner<byte> outputParcelOwner = ByteMemoryPool.RentCleared(replySize))
using IMemoryOwner<byte> outputParcelOwner = ByteMemoryPool.RentCleared(replySize);
Span<byte> outputParcel = outputParcelOwner.Memory.Span;
ResultCode result = OnTransact(binderId, code, flags, inputParcel, outputParcel);
if (result == ResultCode.Success)
{
Span<byte> outputParcel = outputParcelOwner.Memory.Span;
ResultCode result = OnTransact(binderId, code, flags, inputParcel, outputParcel);
if (result == ResultCode.Success)
{
context.Memory.Write(replyPos, outputParcel);
}
return result;
context.Memory.Write(replyPos, outputParcel);
}
return result;
}
protected abstract ResultCode AdjustRefcount(int binderId, int addVal, int type);

View file

@ -5,6 +5,6 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
NotInitialized,
ManagedClosed,
ManagedOpened,
Stray
Stray,
}
}
}

View file

@ -2,10 +2,10 @@
{
enum NativeWindowApi
{
NoApi = 0,
NVN = 1,
CPU = 2,
Media = 3,
Camera = 4
NoApi = 0,
NVN = 1,
CPU = 2,
Media = 3,
Camera = 4,
}
}

View file

@ -2,12 +2,12 @@
{
enum NativeWindowAttribute : uint
{
Width = 0,
Height = 1,
Format = 2,
MinUnqueuedBuffers = 3,
Width = 0,
Height = 1,
Format = 2,
MinUnqueuedBuffers = 3,
ConsumerRunningBehind = 9,
ConsumerUsageBits = 10,
MaxBufferCountAsync = 12
ConsumerUsageBits = 10,
MaxBufferCountAsync = 12,
}
}

View file

@ -2,10 +2,10 @@
{
enum NativeWindowScalingMode : uint
{
Freeze = 0,
Freeze = 0,
ScaleToWindow = 1,
ScaleCrop = 2,
Unknown = 3,
NoScaleCrop = 4,
ScaleCrop = 2,
Unknown = 3,
NoScaleCrop = 4,
}
}

View file

@ -5,14 +5,14 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
[Flags]
enum NativeWindowTransform : uint
{
None = 0,
FlipX = 1,
FlipY = 2,
Rotate90 = 4,
Rotate180 = FlipX | FlipY,
Rotate270 = Rotate90 | Rotate180,
InverseDisplay = 8,
None = 0,
FlipX = 1,
FlipY = 2,
Rotate90 = 4,
Rotate180 = FlipX | FlipY,
Rotate270 = Rotate90 | Rotate180,
InverseDisplay = 8,
NoVSyncCapability = 0x10,
ReturnFrameNumber = 0x20
ReturnFrameNumber = 0x20,
}
}

View file

@ -13,7 +13,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
{
private readonly byte[] _rawData;
private Span<byte> Raw => new Span<byte>(_rawData);
private Span<byte> Raw => new(_rawData);
private ref ParcelHeader Header => ref MemoryMarshal.Cast<byte, ParcelHeader>(_rawData)[0];
@ -26,10 +26,10 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
public Parcel(byte[] rawData)
{
_rawData = rawData;
_rawData = rawData;
_payloadPosition = 0;
_objectPosition = 0;
_objectPosition = 0;
}
public Parcel(uint payloadSize, uint objectsSize)
@ -38,16 +38,18 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
_rawData = new byte[BitUtils.AlignUp<uint>(headerSize + payloadSize + objectsSize, 4)];
Header.PayloadSize = payloadSize;
Header.ObjectsSize = objectsSize;
Header.PayloadSize = payloadSize;
Header.ObjectsSize = objectsSize;
Header.PayloadOffset = headerSize;
Header.ObjectOffset = Header.PayloadOffset + Header.ObjectsSize;
Header.ObjectOffset = Header.PayloadOffset + Header.ObjectsSize;
}
public string ReadInterfaceToken()
{
// Ignore the policy flags
#pragma warning disable IDE0059 // Remove unnecessary value assignment
int strictPolicy = ReadInt32();
#pragma warning restore IDE0059
return ReadString16();
}
@ -64,7 +66,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
ReadOnlySpan<byte> data = ReadInPlace((size + 1) * 2);
// Return the unicode string without the last character (null terminator)
return Encoding.Unicode.GetString(data.Slice(0, size * 2));
return Encoding.Unicode.GetString(data[..(size * 2)]);
}
public int ReadInt32() => ReadUnmanagedType<int>();
@ -77,7 +79,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
{
long flattenableSize = ReadInt64();
T result = new T();
T result = new();
Debug.Assert(flattenableSize == result.GetFlattenedSize());
@ -86,7 +88,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
return result;
}
public T ReadUnmanagedType<T>() where T: unmanaged
public T ReadUnmanagedType<T>() where T : unmanaged
{
ReadOnlySpan<byte> data = ReadInPlace(Unsafe.SizeOf<T>());
@ -105,8 +107,8 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
[StructLayout(LayoutKind.Sequential, Size = 0x28)]
private struct FlatBinderObject
{
public int Type;
public int Flags;
public int Type;
public int Flags;
public long BinderId;
public long Cookie;
@ -115,12 +117,12 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
public Span<byte> ServiceName => MemoryMarshal.CreateSpan(ref _serviceNameStart, 0x8);
}
public void WriteObject<T>(T obj, string serviceName) where T: IBinder
public void WriteObject<T>(T obj, string serviceName) where T : IBinder
{
FlatBinderObject flatBinderObject = new FlatBinderObject
FlatBinderObject flatBinderObject = new()
{
Type = 2,
Flags = 0,
Type = 2,
Flags = 0,
BinderId = HOSBinderDriverServer.GetBinderId(obj),
};
@ -149,7 +151,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
}
}
public void WriteStrongPointer<T>(ref AndroidStrongPointer<T> value) where T: unmanaged, IFlattenable
public void WriteStrongPointer<T>(ref AndroidStrongPointer<T> value) where T : unmanaged, IFlattenable
{
WriteBoolean(!value.IsNull);
@ -205,17 +207,17 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
{
uint headerSize = (uint)Unsafe.SizeOf<ParcelHeader>();
Header.PayloadSize = (uint)_payloadPosition;
Header.ObjectsSize = (uint)_objectPosition;
Header.PayloadSize = (uint)_payloadPosition;
Header.ObjectsSize = (uint)_objectPosition;
Header.PayloadOffset = headerSize;
Header.ObjectOffset = Header.PayloadOffset + Header.PayloadSize;
Header.ObjectOffset = Header.PayloadOffset + Header.PayloadSize;
}
public ReadOnlySpan<byte> Finish()
{
UpdateHeader();
return Raw.Slice(0, (int)(Header.PayloadSize + Header.ObjectsSize + Unsafe.SizeOf<ParcelHeader>()));
return Raw[..(int)(Header.PayloadSize + Header.ObjectsSize + Unsafe.SizeOf<ParcelHeader>())];
}
}
}

View file

@ -1,22 +1,25 @@
namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
using System.Diagnostics.CodeAnalysis;
namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
{
[SuppressMessage("Design", "CA1069: Enums values should not be duplicated")]
enum Status
{
Success = 0,
WouldBlock = -11,
NoMemory = -12,
Busy = -16,
NoInit = -19,
BadValue = -22,
Success = 0,
WouldBlock = -11,
NoMemory = -12,
Busy = -16,
NoInit = -19,
BadValue = -22,
InvalidOperation = -37,
// Producer flags
BufferNeedsReallocation = 1,
ReleaseAllBuffers = 2,
ReleaseAllBuffers = 2,
// Consumer errors
StaleBufferSlot = 1,
StaleBufferSlot = 1,
NoBufferAvailaible = 2,
PresentLater = 3,
PresentLater = 3,
}
}

View file

@ -11,49 +11,47 @@ using System.Threading;
namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
{
using ResultCode = Ryujinx.HLE.HOS.Services.Vi.ResultCode;
class SurfaceFlinger : IConsumerListener, IDisposable
{
private const int TargetFps = 60;
private Switch _device;
private readonly Switch _device;
private Dictionary<long, Layer> _layers;
private readonly Dictionary<long, Layer> _layers;
private bool _isRunning;
private Thread _composerThread;
private readonly Thread _composerThread;
private Stopwatch _chrono;
private readonly Stopwatch _chrono;
private ManualResetEvent _event = new ManualResetEvent(false);
private AutoResetEvent _nextFrameEvent = new AutoResetEvent(true);
private readonly ManualResetEvent _event = new(false);
private readonly AutoResetEvent _nextFrameEvent = new(true);
private long _ticks;
private long _ticksPerFrame;
private long _spinTicks;
private long _1msTicks;
private readonly long _spinTicks;
private readonly long _1msTicks;
private int _swapInterval;
private int _swapIntervalDelay;
private readonly object Lock = new();
private readonly object _lock = new();
public long RenderLayerId { get; private set; }
private class Layer
{
public int ProducerBinderId;
public int ProducerBinderId;
public IGraphicBufferProducer Producer;
public BufferItemConsumer Consumer;
public BufferQueueCore Core;
public ulong Owner;
public LayerState State;
public BufferItemConsumer Consumer;
public BufferQueueCore Core;
public ulong Owner;
public LayerState State;
}
private class TextureCallbackInformation
{
public Layer Layer;
public Layer Layer;
public BufferItem Item;
}
@ -65,7 +63,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
_composerThread = new Thread(HandleComposition)
{
Name = "SurfaceFlinger.Composer"
Name = "SurfaceFlinger.Composer",
};
_chrono = new Stopwatch();
@ -100,7 +98,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
{
layerId = 1;
lock (Lock)
lock (_lock)
{
foreach (KeyValuePair<long, Layer> pair in _layers)
{
@ -118,7 +116,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
private void CreateLayerFromId(ulong pid, long layerId, LayerState initialState)
{
lock (Lock)
lock (_lock)
{
Logger.Info?.Print(LogClass.SurfaceFlinger, $"Creating layer {layerId}");
@ -132,16 +130,16 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
_layers.Add(layerId, new Layer
{
ProducerBinderId = HOSBinderDriverServer.RegisterBinderObject(producer),
Producer = producer,
Consumer = new BufferItemConsumer(_device, consumer, 0, -1, false, this),
Core = core,
Owner = pid,
State = initialState
Producer = producer,
Consumer = new BufferItemConsumer(_device, consumer, 0, -1, false, this),
Core = core,
Owner = pid,
State = initialState,
});
}
}
public ResultCode OpenLayer(ulong pid, long layerId, out IBinder producer)
public Vi.ResultCode OpenLayer(ulong pid, long layerId, out IBinder producer)
{
Layer layer = GetLayerByIdLocked(layerId);
@ -149,18 +147,18 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
{
producer = null;
return ResultCode.InvalidArguments;
return Vi.ResultCode.InvalidArguments;
}
layer.State = LayerState.ManagedOpened;
producer = layer.Producer;
return ResultCode.Success;
return Vi.ResultCode.Success;
}
public ResultCode CloseLayer(long layerId)
public Vi.ResultCode CloseLayer(long layerId)
{
lock (Lock)
lock (_lock)
{
Layer layer = GetLayerByIdLocked(layerId);
@ -168,18 +166,18 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
{
Logger.Error?.Print(LogClass.SurfaceFlinger, $"Failed to close layer {layerId}");
return ResultCode.InvalidValue;
return Vi.ResultCode.InvalidValue;
}
CloseLayer(layerId, layer);
return ResultCode.Success;
return Vi.ResultCode.Success;
}
}
public ResultCode DestroyManagedLayer(long layerId)
public Vi.ResultCode DestroyManagedLayer(long layerId)
{
lock (Lock)
lock (_lock)
{
Layer layer = GetLayerByIdLocked(layerId);
@ -187,14 +185,14 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
{
Logger.Error?.Print(LogClass.SurfaceFlinger, $"Failed to destroy managed layer {layerId} (not found)");
return ResultCode.InvalidValue;
return Vi.ResultCode.InvalidValue;
}
if (layer.State != LayerState.ManagedClosed && layer.State != LayerState.ManagedOpened)
{
Logger.Error?.Print(LogClass.SurfaceFlinger, $"Failed to destroy managed layer {layerId} (permission denied)");
return ResultCode.PermissionDenied;
return Vi.ResultCode.PermissionDenied;
}
HOSBinderDriverServer.UnregisterBinderObject(layer.ProducerBinderId);
@ -204,13 +202,13 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
CloseLayer(layerId, layer);
}
return ResultCode.Success;
return Vi.ResultCode.Success;
}
}
public ResultCode DestroyStrayLayer(long layerId)
public Vi.ResultCode DestroyStrayLayer(long layerId)
{
lock (Lock)
lock (_lock)
{
Layer layer = GetLayerByIdLocked(layerId);
@ -218,14 +216,14 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
{
Logger.Error?.Print(LogClass.SurfaceFlinger, $"Failed to destroy stray layer {layerId} (not found)");
return ResultCode.InvalidValue;
return Vi.ResultCode.InvalidValue;
}
if (layer.State != LayerState.Stray)
{
Logger.Error?.Print(LogClass.SurfaceFlinger, $"Failed to destroy stray layer {layerId} (permission denied)");
return ResultCode.PermissionDenied;
return Vi.ResultCode.PermissionDenied;
}
HOSBinderDriverServer.UnregisterBinderObject(layer.ProducerBinderId);
@ -235,7 +233,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
CloseLayer(layerId, layer);
}
return ResultCode.Success;
return Vi.ResultCode.Success;
}
}
@ -263,7 +261,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
public void SetRenderLayer(long layerId)
{
lock (Lock)
lock (_lock)
{
RenderLayerId = layerId;
}
@ -284,7 +282,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
public IGraphicBufferProducer GetProducerByLayerId(long layerId)
{
lock (Lock)
lock (_lock)
{
Layer layer = GetLayerByIdLocked(layerId);
@ -365,7 +363,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
public void Compose()
{
lock (Lock)
lock (_lock)
{
// TODO: support multilayers (& multidisplay ?)
if (RenderLayerId == 0)
@ -403,7 +401,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
private void PostFrameBuffer(Layer layer, BufferItem item)
{
int frameBufferWidth = item.GraphicBuffer.Object.Width;
int frameBufferWidth = item.GraphicBuffer.Object.Width;
int frameBufferHeight = item.GraphicBuffer.Object.Height;
int nvMapHandle = item.GraphicBuffer.Object.Buffer.Surfaces[0].NvMapHandle;
@ -434,9 +432,9 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
bool flipY = item.Transform.HasFlag(NativeWindowTransform.FlipY);
AspectRatio aspectRatio = _device.Configuration.AspectRatio;
bool isStretched = aspectRatio == AspectRatio.Stretched;
bool isStretched = aspectRatio == AspectRatio.Stretched;
ImageCrop crop = new ImageCrop(
ImageCrop crop = new(
cropRect.Left,
cropRect.Right,
cropRect.Top,
@ -447,10 +445,10 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
aspectRatio.ToFloatX(),
aspectRatio.ToFloatY());
TextureCallbackInformation textureCallbackInformation = new TextureCallbackInformation
TextureCallbackInformation textureCallbackInformation = new()
{
Layer = layer,
Item = item
Item = item,
};
if (_device.Gpu.Window.EnqueueFrameThreadSafe(
@ -543,6 +541,6 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
_device.Statistics.RecordGameFrameTime();
}
public void OnBuffersReleased() {}
public void OnBuffersReleased() { }
}
}

View file

@ -16,17 +16,17 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
private byte _fenceStorageStart;
private Span<byte> _storage => MemoryMarshal.CreateSpan(ref _fenceStorageStart, Unsafe.SizeOf<NvFence>() * 4);
private Span<byte> Storage => MemoryMarshal.CreateSpan(ref _fenceStorageStart, Unsafe.SizeOf<NvFence>() * 4);
public Span<NvFence> NvFences => MemoryMarshal.Cast<byte, NvFence>(_storage);
public Span<NvFence> NvFences => MemoryMarshal.Cast<byte, NvFence>(Storage);
public static AndroidFence NoFence
{
get
{
AndroidFence fence = new AndroidFence
AndroidFence fence = new()
{
FenceCount = 0
FenceCount = 0,
};
fence.NvFences[0].Id = NvFence.InvalidSyncPointId;
@ -81,12 +81,12 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
}
}
public uint GetFlattenedSize()
public readonly uint GetFlattenedSize()
{
return (uint)Unsafe.SizeOf<AndroidFence>();
}
public uint GetFdCount()
public readonly uint GetFdCount()
{
return 0;
}
@ -101,4 +101,4 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
this = parcel.ReadUnmanagedType<AndroidFence>();
}
}
}
}

View file

@ -1,6 +1,6 @@
namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger.Types
{
class AndroidStrongPointer<T> where T: unmanaged, IFlattenable
class AndroidStrongPointer<T> where T : unmanaged, IFlattenable
{
public T Object;
@ -20,13 +20,13 @@
public void Set(AndroidStrongPointer<T> other)
{
Object = other.Object;
Object = other.Object;
_hasObject = other._hasObject;
}
public void Set(T obj)
{
Object = obj;
Object = obj;
_hasObject = true;
}

View file

@ -6,9 +6,9 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger.Types
[StructLayout(LayoutKind.Sequential, Size = 0x1C, Pack = 1)]
struct BufferInfo
{
public ulong FrameNumber;
public ulong FrameNumber;
public TimeSpanType QueueTime;
public TimeSpanType PresentationTime;
public BufferState State;
public BufferState State;
}
}

View file

@ -6,33 +6,33 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
class BufferItem : ICloneable
{
public AndroidStrongPointer<GraphicBuffer> GraphicBuffer;
public AndroidFence Fence;
public Rect Crop;
public NativeWindowTransform Transform;
public NativeWindowScalingMode ScalingMode;
public long Timestamp;
public bool IsAutoTimestamp;
public int SwapInterval;
public ulong FrameNumber;
public int Slot;
public bool IsDroppable;
public bool AcquireCalled;
public bool TransformToDisplayInverse;
public AndroidFence Fence;
public Rect Crop;
public NativeWindowTransform Transform;
public NativeWindowScalingMode ScalingMode;
public long Timestamp;
public bool IsAutoTimestamp;
public int SwapInterval;
public ulong FrameNumber;
public int Slot;
public bool IsDroppable;
public bool AcquireCalled;
public bool TransformToDisplayInverse;
public BufferItem()
{
GraphicBuffer = new AndroidStrongPointer<GraphicBuffer>();
Transform = NativeWindowTransform.None;
ScalingMode = NativeWindowScalingMode.Freeze;
Timestamp = 0;
IsAutoTimestamp = false;
FrameNumber = 0;
Slot = BufferSlotArray.InvalidBufferSlot;
IsDroppable = false;
AcquireCalled = false;
GraphicBuffer = new AndroidStrongPointer<GraphicBuffer>();
Transform = NativeWindowTransform.None;
ScalingMode = NativeWindowScalingMode.Freeze;
Timestamp = 0;
IsAutoTimestamp = false;
FrameNumber = 0;
Slot = BufferSlotArray.InvalidBufferSlot;
IsDroppable = false;
AcquireCalled = false;
TransformToDisplayInverse = false;
SwapInterval = 1;
Fence = AndroidFence.NoFence;
SwapInterval = 1;
Fence = AndroidFence.NoFence;
Crop = new Rect();
Crop.MakeInvalid();
@ -40,19 +40,20 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
public object Clone()
{
BufferItem item = new BufferItem();
item.Transform = Transform;
item.ScalingMode = ScalingMode;
item.IsAutoTimestamp = IsAutoTimestamp;
item.FrameNumber = FrameNumber;
item.Slot = Slot;
item.IsDroppable = IsDroppable;
item.AcquireCalled = AcquireCalled;
item.TransformToDisplayInverse = TransformToDisplayInverse;
item.SwapInterval = SwapInterval;
item.Fence = Fence;
item.Crop = Crop;
BufferItem item = new()
{
Transform = Transform,
ScalingMode = ScalingMode,
IsAutoTimestamp = IsAutoTimestamp,
FrameNumber = FrameNumber,
Slot = Slot,
IsDroppable = IsDroppable,
AcquireCalled = AcquireCalled,
TransformToDisplayInverse = TransformToDisplayInverse,
SwapInterval = SwapInterval,
Fence = Fence,
Crop = Crop,
};
item.GraphicBuffer.Set(GraphicBuffer);

View file

@ -2,9 +2,9 @@
{
internal enum BufferState
{
Free = 0,
Free = 0,
Dequeued = 1,
Queued = 2,
Acquired = 3
Queued = 2,
Acquired = 3,
}
}
}

View file

@ -2,16 +2,16 @@
{
enum ColorBytePerPixel
{
Bpp1 = 1,
Bpp2 = 2,
Bpp4 = 4,
Bpp8 = 8,
Bpp16 = 16,
Bpp24 = 24,
Bpp32 = 32,
Bpp48 = 48,
Bpp64 = 64,
Bpp96 = 96,
Bpp128 = 128
Bpp1 = 1,
Bpp2 = 2,
Bpp4 = 4,
Bpp8 = 8,
Bpp16 = 16,
Bpp24 = 24,
Bpp32 = 32,
Bpp48 = 48,
Bpp64 = 64,
Bpp96 = 96,
Bpp128 = 128,
}
}
}

View file

@ -2,6 +2,7 @@
{
enum ColorComponent : uint
{
#pragma warning disable IDE0055 // Disable formatting
X1 = (0x01 << ColorShift.Component) | ColorBytePerPixel.Bpp1,
X2 = (0x02 << ColorShift.Component) | ColorBytePerPixel.Bpp2,
X4 = (0x03 << ColorShift.Component) | ColorBytePerPixel.Bpp4,
@ -38,5 +39,6 @@
Y12X12 = (0x24 << ColorShift.Component) | ColorBytePerPixel.Bpp32,
X20Y20Z20 = (0x26 << ColorShift.Component) | ColorBytePerPixel.Bpp64,
X16Y16Z16W16 = (0x27 << ColorShift.Component) | ColorBytePerPixel.Bpp64,
#pragma warning restore IDE0055
}
}
}

View file

@ -3,7 +3,7 @@
enum ColorDataType
{
Integer = 0x0 << ColorShift.DataType,
Float = 0x1 << ColorShift.DataType,
Stencil = 0x2 << ColorShift.DataType
Float = 0x1 << ColorShift.DataType,
Stencil = 0x2 << ColorShift.DataType,
}
}
}

View file

@ -1,7 +1,11 @@
namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
using System.Diagnostics.CodeAnalysis;
namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
{
[SuppressMessage("Design", "CA1069: Enums values should not be duplicated")]
enum ColorFormat : ulong
{
#pragma warning disable IDE0055 // Disable formatting
NonColor8 = ColorSpace.NonColor | ColorSwizzle.X000 | ColorComponent.X8 | ColorDataType.Integer,
NonColor16 = ColorSpace.NonColor | ColorSwizzle.X000 | ColorComponent.X16 | ColorDataType.Integer,
NonColor24 = ColorSpace.NonColor | ColorSwizzle.X000 | ColorComponent.X24 | ColorDataType.Integer,
@ -231,5 +235,6 @@
X4Bayer12GBRG = ColorSpace.BayerGBRG | ColorSwizzle.Y000 | ColorComponent.Y4X12 | ColorDataType.Integer,
X6Bayer10GBRG = ColorSpace.BayerGBRG | ColorSwizzle.Y000 | ColorComponent.Y6X10 | ColorDataType.Integer,
XYZ = ColorSpace.XYZ | ColorSwizzle.XYZ1 | ColorComponent.X20Y20Z20 | ColorDataType.Float,
#pragma warning restore IDE0055
}
}
}

View file

@ -2,9 +2,9 @@
{
class ColorShift
{
public const int Swizzle = 16;
public const int DataType = 14;
public const int Space = 32;
public const int Swizzle = 16;
public const int DataType = 14;
public const int Space = 32;
public const int Component = 8;
}
}
}

View file

@ -2,32 +2,32 @@
{
enum ColorSpace : ulong
{
NonColor = 0x0L << ColorShift.Space,
LinearRGBA = 0x1L << ColorShift.Space,
SRGB = 0x2L << ColorShift.Space,
NonColor = 0x0L << ColorShift.Space,
LinearRGBA = 0x1L << ColorShift.Space,
SRGB = 0x2L << ColorShift.Space,
RGB709 = 0x3L << ColorShift.Space,
LinearRGB709 = 0x4L << ColorShift.Space,
RGB709 = 0x3L << ColorShift.Space,
LinearRGB709 = 0x4L << ColorShift.Space,
LinearScRGB = 0x5L << ColorShift.Space,
LinearScRGB = 0x5L << ColorShift.Space,
RGB2020 = 0x6L << ColorShift.Space,
RGB2020 = 0x6L << ColorShift.Space,
LinearRGB2020 = 0x7L << ColorShift.Space,
RGB2020_PQ = 0x8L << ColorShift.Space,
RGB2020_PQ = 0x8L << ColorShift.Space,
ColorIndex = 0x9L << ColorShift.Space,
ColorIndex = 0x9L << ColorShift.Space,
YCbCr601 = 0xAL << ColorShift.Space,
YCbCr601_RR = 0xBL << ColorShift.Space,
YCbCr601_ER = 0xCL << ColorShift.Space,
YCbCr709 = 0xDL << ColorShift.Space,
YCbCr709_ER = 0xEL << ColorShift.Space,
YCbCr601 = 0xAL << ColorShift.Space,
YCbCr601_RR = 0xBL << ColorShift.Space,
YCbCr601_ER = 0xCL << ColorShift.Space,
YCbCr709 = 0xDL << ColorShift.Space,
YCbCr709_ER = 0xEL << ColorShift.Space,
BayerRGGB = 0x10L << ColorShift.Space,
BayerBGGR = 0x11L << ColorShift.Space,
BayerGRBG = 0x12L << ColorShift.Space,
BayerGBRG = 0x13L << ColorShift.Space,
BayerRGGB = 0x10L << ColorShift.Space,
BayerBGGR = 0x11L << ColorShift.Space,
BayerGRBG = 0x12L << ColorShift.Space,
BayerGBRG = 0x13L << ColorShift.Space,
XYZ = 0x14L << ColorShift.Space,
XYZ = 0x14L << ColorShift.Space,
}
}
}

View file

@ -2,6 +2,7 @@
{
enum ColorSwizzle
{
#pragma warning disable IDE0055 // Disable formatting
XYZW = 0x688 << ColorShift.Swizzle,
ZYXW = 0x60a << ColorShift.Swizzle,
WZYX = 0x053 << ColorShift.Swizzle,
@ -26,6 +27,7 @@
_000X = 0x124 << ColorShift.Swizzle,
_0XY0 = 0x844 << ColorShift.Swizzle,
XXXY = 0x200 << ColorShift.Swizzle,
YYYX = 0x049 << ColorShift.Swizzle
YYYX = 0x049 << ColorShift.Swizzle,
#pragma warning restore IDE0055
}
}
}

View file

@ -9,14 +9,14 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
struct GraphicBuffer : IFlattenable
{
public GraphicBufferHeader Header;
public NvGraphicBuffer Buffer;
public NvGraphicBuffer Buffer;
public int Width => Header.Width;
public int Height => Header.Height;
public PixelFormat Format => Header.Format;
public int Usage => Header.Usage;
public readonly int Width => Header.Width;
public readonly int Height => Header.Height;
public readonly PixelFormat Format => Header.Format;
public readonly int Usage => Header.Usage;
public Rect ToRect()
public readonly Rect ToRect()
{
return new Rect(Width, Height);
}
@ -41,34 +41,34 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
Buffer = parcel.ReadUnmanagedType<NvGraphicBuffer>();
}
public void IncrementNvMapHandleRefCount(ulong pid)
public readonly void IncrementNvMapHandleRefCount(ulong pid)
{
NvMapDeviceFile.IncrementMapRefCount(pid, Buffer.NvMapId);
for (int i = 0; i < Buffer.Surfaces.Length; i++)
for (int i = 0; i < NvGraphicBufferSurfaceArray.Length; i++)
{
NvMapDeviceFile.IncrementMapRefCount(pid, Buffer.Surfaces[i].NvMapHandle);
}
}
public void DecrementNvMapHandleRefCount(ulong pid)
public readonly void DecrementNvMapHandleRefCount(ulong pid)
{
NvMapDeviceFile.DecrementMapRefCount(pid, Buffer.NvMapId);
for (int i = 0; i < Buffer.Surfaces.Length; i++)
for (int i = 0; i < NvGraphicBufferSurfaceArray.Length; i++)
{
NvMapDeviceFile.DecrementMapRefCount(pid, Buffer.Surfaces[i].NvMapHandle);
}
}
public uint GetFlattenedSize()
public readonly uint GetFlattenedSize()
{
return (uint)Unsafe.SizeOf<GraphicBuffer>();
}
public uint GetFdCount()
public readonly uint GetFdCount()
{
return 0;
}
}
}
}

View file

@ -5,12 +5,12 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
[StructLayout(LayoutKind.Sequential, Size = 0x28, Pack = 1)]
struct GraphicBufferHeader
{
public int Magic;
public int Width;
public int Height;
public int Stride;
public int Magic;
public int Width;
public int Height;
public int Stride;
public PixelFormat Format;
public int Usage;
public int Usage;
public int Pid;
public int RefCount;
@ -18,4 +18,4 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
public int FdsCount;
public int IntsCount;
}
}
}

View file

@ -38,4 +38,4 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
[FieldOffset(0x34)]
public NvGraphicBufferSurfaceArray Surfaces;
}
}
}

View file

@ -41,4 +41,4 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
[FieldOffset(0x38)]
public long Size;
}
}
}

View file

@ -15,27 +15,20 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
[FieldOffset(0xb0)]
private NvGraphicBufferSurface Surface2;
public NvGraphicBufferSurface this[int index]
public readonly NvGraphicBufferSurface this[int index]
{
get
{
if (index == 0)
return index switch
{
return Surface0;
}
else if (index == 1)
{
return Surface1;
}
else if (index == 2)
{
return Surface2;
}
throw new IndexOutOfRangeException();
0 => Surface0,
1 => Surface1,
2 => Surface2,
_ => throw new IndexOutOfRangeException(),
};
}
}
public int Length => 3;
public static int Length => 3;
}
}
}

View file

@ -11,18 +11,18 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
public int Right;
public int Bottom;
public int Width => Right - Left;
public int Height => Bottom - Top;
public readonly int Width => Right - Left;
public readonly int Height => Bottom - Top;
public Rect(int width, int height)
{
Left = 0;
Top = 0;
Right = width;
Left = 0;
Top = 0;
Right = width;
Bottom = height;
}
public bool IsEmpty()
public readonly bool IsEmpty()
{
return Width <= 0 || Height <= 0;
}
@ -31,10 +31,10 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
{
result = new Rect
{
Left = Math.Max(Left, other.Left),
Top = Math.Max(Top, other.Top),
Right = Math.Min(Right, other.Right),
Bottom = Math.Min(Bottom, other.Bottom)
Left = Math.Max(Left, other.Left),
Top = Math.Max(Top, other.Top),
Right = Math.Min(Right, other.Right),
Bottom = Math.Min(Bottom, other.Bottom),
};
return !result.IsEmpty();
@ -42,7 +42,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
public void MakeInvalid()
{
Right = -1;
Right = -1;
Bottom = -1;
}
@ -56,16 +56,16 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
return !x.Equals(y);
}
public override bool Equals(object obj)
public readonly override bool Equals(object obj)
{
return obj is Rect rect && Equals(rect);
}
public bool Equals(Rect cmpObj)
public readonly bool Equals(Rect cmpObj)
{
return Left == cmpObj.Left && Top == cmpObj.Top && Right == cmpObj.Right && Bottom == cmpObj.Bottom;
}
public override int GetHashCode() => HashCode.Combine(Left, Top, Right, Bottom);
public readonly override int GetHashCode() => HashCode.Combine(Left, Top, Right, Bottom);
}
}
}