SurfaceFlinger v2 (#981)
* Rewrite SurfaceFlinger Reimplement accurately SurfaceFlinger (based on my 8.1.0 reversing of it) TODO: support swap interval properly and reintroduce disabled "game vsync" support. * Some fixes for SetBufferCount * uncomment a test from last commit * SurfaceFlinger: don't free the graphic buffer in SetBufferCount * SurfaceFlinger: Implement swap interval correctly * SurfaceFlinger: Reintegrate Game VSync toggle * SurfaceFlinger: do not push a fence on buffer release on the consumer side * Revert "SurfaceFlinger: do not push a fence on buffer release on the consumer side" This reverts commit 586b52b0bfab2d11f361f4b59ab7b7141020bbad. * Make the game vsync toggle work dynamically again * Unregister producer's Binder object when closing layer * Address ripinperi's comments * Add a timeout on syncpoint wait operation Syncpoint aren't supposed to be waited on for more than a second. This effectively workaround issues caused by not having a channel scheduling in place yet. PS: Also introduce Android WaitForever warning about fence being not signaled for 3s * Fix a print of previous commit * Address Ac_K's comments * Address gdkchan's comments * Address final comments
This commit is contained in:
parent
03711dd7b5
commit
36749c358d
50 changed files with 3416 additions and 831 deletions
175
Ryujinx.HLE/HOS/Services/SurfaceFlinger/ConsumerBase.cs
Normal file
175
Ryujinx.HLE/HOS/Services/SurfaceFlinger/ConsumerBase.cs
Normal file
|
@ -0,0 +1,175 @@
|
|||
using Ryujinx.HLE.HOS.Services.SurfaceFlinger.Types;
|
||||
using System;
|
||||
|
||||
namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
|
||||
{
|
||||
class ConsumerBase : IConsumerListener
|
||||
{
|
||||
public class Slot
|
||||
{
|
||||
public AndroidStrongPointer<GraphicBuffer> GraphicBuffer;
|
||||
public AndroidFence Fence;
|
||||
public ulong FrameNumber;
|
||||
|
||||
public Slot()
|
||||
{
|
||||
GraphicBuffer = new AndroidStrongPointer<GraphicBuffer>();
|
||||
}
|
||||
}
|
||||
|
||||
protected Slot[] Slots = new Slot[BufferSlotArray.NumBufferSlots];
|
||||
|
||||
protected bool IsAbandoned;
|
||||
|
||||
protected BufferQueueConsumer Consumer;
|
||||
|
||||
protected readonly object Lock = new object();
|
||||
|
||||
private IConsumerListener _listener;
|
||||
|
||||
public ConsumerBase(BufferQueueConsumer consumer, bool controlledByApp, IConsumerListener listener)
|
||||
{
|
||||
for (int i = 0; i < Slots.Length; i++)
|
||||
{
|
||||
Slots[i] = new Slot();
|
||||
}
|
||||
|
||||
IsAbandoned = false;
|
||||
Consumer = consumer;
|
||||
_listener = listener;
|
||||
|
||||
Status connectStatus = consumer.Connect(this, controlledByApp);
|
||||
|
||||
if (connectStatus != Status.Success)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void OnBuffersReleased()
|
||||
{
|
||||
lock (Lock)
|
||||
{
|
||||
if (IsAbandoned)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Consumer.GetReleasedBuffers(out ulong slotMask);
|
||||
|
||||
for (int i = 0; i < Slots.Length; i++)
|
||||
{
|
||||
if ((slotMask & (1UL << i)) != 0)
|
||||
{
|
||||
FreeBufferLocked(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void OnFrameAvailable(ref BufferItem item)
|
||||
{
|
||||
_listener?.OnFrameAvailable(ref item);
|
||||
}
|
||||
|
||||
public virtual void OnFrameReplaced(ref BufferItem item)
|
||||
{
|
||||
_listener?.OnFrameReplaced(ref item);
|
||||
}
|
||||
|
||||
protected virtual void FreeBufferLocked(int slotIndex)
|
||||
{
|
||||
Slots[slotIndex].GraphicBuffer.Reset();
|
||||
|
||||
Slots[slotIndex].Fence = AndroidFence.NoFence;
|
||||
Slots[slotIndex].FrameNumber = 0;
|
||||
}
|
||||
|
||||
public void Abandon()
|
||||
{
|
||||
lock (Lock)
|
||||
{
|
||||
if (!IsAbandoned)
|
||||
{
|
||||
AbandonLocked();
|
||||
|
||||
IsAbandoned = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void AbandonLocked()
|
||||
{
|
||||
for (int i = 0; i < Slots.Length; i++)
|
||||
{
|
||||
FreeBufferLocked(i);
|
||||
}
|
||||
|
||||
Consumer.Disconnect();
|
||||
}
|
||||
|
||||
protected virtual Status AcquireBufferLocked(out BufferItem bufferItem, ulong expectedPresent)
|
||||
{
|
||||
Status acquireStatus = Consumer.AcquireBuffer(out bufferItem, expectedPresent);
|
||||
|
||||
if (acquireStatus != Status.Success)
|
||||
{
|
||||
return acquireStatus;
|
||||
}
|
||||
|
||||
if (!bufferItem.GraphicBuffer.IsNull)
|
||||
{
|
||||
Slots[bufferItem.Slot].GraphicBuffer.Set(bufferItem.GraphicBuffer.Object);
|
||||
}
|
||||
|
||||
Slots[bufferItem.Slot].FrameNumber = bufferItem.FrameNumber;
|
||||
Slots[bufferItem.Slot].Fence = bufferItem.Fence;
|
||||
|
||||
return Status.Success;
|
||||
}
|
||||
|
||||
protected virtual Status AddReleaseFenceLocked(int slot, ref AndroidStrongPointer<GraphicBuffer> graphicBuffer, ref AndroidFence fence)
|
||||
{
|
||||
if (!StillTracking(slot, ref graphicBuffer))
|
||||
{
|
||||
return Status.Success;
|
||||
}
|
||||
|
||||
Slots[slot].Fence = fence;
|
||||
|
||||
return Status.Success;
|
||||
}
|
||||
|
||||
protected virtual Status ReleaseBufferLocked(int slot, ref AndroidStrongPointer<GraphicBuffer> graphicBuffer)
|
||||
{
|
||||
if (!StillTracking(slot, ref graphicBuffer))
|
||||
{
|
||||
return Status.Success;
|
||||
}
|
||||
|
||||
Status result = Consumer.ReleaseBuffer(slot, Slots[slot].FrameNumber, ref Slots[slot].Fence);
|
||||
|
||||
if (result == Status.StaleBufferSlot)
|
||||
{
|
||||
FreeBufferLocked(slot);
|
||||
}
|
||||
|
||||
Slots[slot].Fence = AndroidFence.NoFence;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
protected virtual bool StillTracking(int slotIndex, ref AndroidStrongPointer<GraphicBuffer> graphicBuffer)
|
||||
{
|
||||
if (slotIndex < 0 || slotIndex >= Slots.Length)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Slot slot = Slots[slotIndex];
|
||||
|
||||
// TODO: Check this. On Android, this checks the "handle". I assume NvMapHandle is the handle, but it might not be.
|
||||
return !slot.GraphicBuffer.IsNull && slot.GraphicBuffer.Object.Buffer.Surfaces[0].NvMapHandle == graphicBuffer.Object.Buffer.Surfaces[0].NvMapHandle;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue