Allow more than one process, free resources on process dispose, implement SvcExitThread
This commit is contained in:
12
Ryujinx.Core/OsHle/Services/Vi/Display.cs
Normal file
12
Ryujinx.Core/OsHle/Services/Vi/Display.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
namespace Ryujinx.Core.OsHle.IpcServices.Vi
|
||||
{
|
||||
class Display
|
||||
{
|
||||
public string Name { get; private set; }
|
||||
|
||||
public Display(string Name)
|
||||
{
|
||||
this.Name = Name;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,8 @@ namespace Ryujinx.Core.OsHle.IpcServices.Vi
|
||||
|
||||
public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
||||
|
||||
private IdDictionary Displays;
|
||||
|
||||
public IApplicationDisplayService()
|
||||
{
|
||||
m_Commands = new Dictionary<int, ServiceProcessRequest>()
|
||||
@@ -28,14 +30,17 @@ namespace Ryujinx.Core.OsHle.IpcServices.Vi
|
||||
{ 2020, OpenLayer },
|
||||
{ 2021, CloseLayer },
|
||||
{ 2030, CreateStrayLayer },
|
||||
{ 2031, DestroyStrayLayer },
|
||||
{ 2101, SetLayerScalingMode },
|
||||
{ 5202, GetDisplayVSyncEvent }
|
||||
};
|
||||
|
||||
Displays = new IdDictionary();
|
||||
}
|
||||
|
||||
public long GetRelayService(ServiceCtx Context)
|
||||
{
|
||||
MakeObject(Context, new IHOSBinderDriver());
|
||||
MakeObject(Context, new IHOSBinderDriver(Context.Ns.Gpu.Renderer));
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -56,7 +61,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.Vi
|
||||
|
||||
public long GetIndirectDisplayTransactionService(ServiceCtx Context)
|
||||
{
|
||||
MakeObject(Context, new IHOSBinderDriver());
|
||||
MakeObject(Context, new IHOSBinderDriver(Context.Ns.Gpu.Renderer));
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -65,7 +70,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.Vi
|
||||
{
|
||||
string Name = GetDisplayName(Context);
|
||||
|
||||
long DisplayId = Context.Ns.Os.Displays.GenerateId(new Display(Name));
|
||||
long DisplayId = Displays.Add(new Display(Name));
|
||||
|
||||
Context.ResponseData.Write(DisplayId);
|
||||
|
||||
@@ -76,7 +81,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.Vi
|
||||
{
|
||||
int DisplayId = Context.RequestData.ReadInt32();
|
||||
|
||||
Context.Ns.Os.Displays.Delete(DisplayId);
|
||||
Displays.Delete(DisplayId);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -99,6 +104,8 @@ namespace Ryujinx.Core.OsHle.IpcServices.Vi
|
||||
|
||||
public long CloseLayer(ServiceCtx Context)
|
||||
{
|
||||
long LayerId = Context.RequestData.ReadInt64();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -109,7 +116,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.Vi
|
||||
|
||||
long ParcelPtr = Context.Request.ReceiveBuff[0].Position;
|
||||
|
||||
Display Disp = Context.Ns.Os.Displays.GetData<Display>((int)DisplayId);
|
||||
Display Disp = Displays.GetData<Display>((int)DisplayId);
|
||||
|
||||
byte[] Parcel = MakeIGraphicsBufferProducer(ParcelPtr);
|
||||
|
||||
@@ -121,6 +128,11 @@ namespace Ryujinx.Core.OsHle.IpcServices.Vi
|
||||
return 0;
|
||||
}
|
||||
|
||||
public long DestroyStrayLayer(ServiceCtx Context)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public long SetLayerScalingMode(ServiceCtx Context)
|
||||
{
|
||||
int ScalingMode = Context.RequestData.ReadInt32();
|
||||
@@ -133,7 +145,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.Vi
|
||||
{
|
||||
string Name = GetDisplayName(Context);
|
||||
|
||||
int Handle = Context.Ns.Os.Handles.GenerateId(new HEvent());
|
||||
int Handle = Context.Process.HandleTable.OpenHandle(new HEvent());
|
||||
|
||||
Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using ChocolArm64.Memory;
|
||||
using Ryujinx.Core.OsHle.Ipc;
|
||||
using Ryujinx.Core.OsHle.IpcServices.Android;
|
||||
using Ryujinx.Graphics.Gal;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
@@ -14,7 +15,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.Vi
|
||||
|
||||
private NvFlinger Flinger;
|
||||
|
||||
public IHOSBinderDriver()
|
||||
public IHOSBinderDriver(IGalRenderer Renderer)
|
||||
{
|
||||
m_Commands = new Dictionary<int, ServiceProcessRequest>()
|
||||
{
|
||||
@@ -23,7 +24,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.Vi
|
||||
{ 2, GetNativeHandle }
|
||||
};
|
||||
|
||||
Flinger = new NvFlinger();
|
||||
Flinger = new NvFlinger(Renderer);
|
||||
}
|
||||
|
||||
public long TransactParcel(ServiceCtx Context)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using ChocolArm64.Memory;
|
||||
using Ryujinx.Core.OsHle.Handles;
|
||||
using Ryujinx.Core.OsHle.IpcServices.NvServices;
|
||||
using Ryujinx.Graphics.Gal;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
@@ -54,18 +55,27 @@ namespace Ryujinx.Core.OsHle.IpcServices.Android
|
||||
public GbpBuffer Data;
|
||||
}
|
||||
|
||||
private IGalRenderer Renderer;
|
||||
|
||||
private BufferEntry[] BufferQueue;
|
||||
|
||||
private ManualResetEvent WaitBufferFree;
|
||||
|
||||
private object RenderQueueLock;
|
||||
|
||||
private int RenderQueueCount;
|
||||
|
||||
private bool NvFlingerDisposed;
|
||||
|
||||
private bool KeepRunning;
|
||||
|
||||
public NvFlinger()
|
||||
public NvFlinger(IGalRenderer Renderer)
|
||||
{
|
||||
Commands = new Dictionary<(string, int), ServiceProcessParcel>()
|
||||
{
|
||||
{ ("android.gui.IGraphicBufferProducer", 0x1), GbpRequestBuffer },
|
||||
{ ("android.gui.IGraphicBufferProducer", 0x3), GbpDequeueBuffer },
|
||||
{ ("android.gui.IGraphicBufferProducer", 0x4), GbpDetachBuffer },
|
||||
{ ("android.gui.IGraphicBufferProducer", 0x7), GbpQueueBuffer },
|
||||
{ ("android.gui.IGraphicBufferProducer", 0x8), GbpCancelBuffer },
|
||||
{ ("android.gui.IGraphicBufferProducer", 0x9), GbpQuery },
|
||||
@@ -74,10 +84,14 @@ namespace Ryujinx.Core.OsHle.IpcServices.Android
|
||||
{ ("android.gui.IGraphicBufferProducer", 0xe), GbpPreallocBuffer }
|
||||
};
|
||||
|
||||
this.Renderer = Renderer;
|
||||
|
||||
BufferQueue = new BufferEntry[0x40];
|
||||
|
||||
WaitBufferFree = new ManualResetEvent(false);
|
||||
|
||||
RenderQueueLock = new object();
|
||||
|
||||
KeepRunning = true;
|
||||
}
|
||||
|
||||
@@ -193,6 +207,11 @@ namespace Ryujinx.Core.OsHle.IpcServices.Android
|
||||
return MakeReplyParcel(Context, 1280, 720, 0, 0, 0);
|
||||
}
|
||||
|
||||
private long GbpDetachBuffer(ServiceCtx Context, BinaryReader ParcelReader)
|
||||
{
|
||||
return MakeReplyParcel(Context, 0);
|
||||
}
|
||||
|
||||
private long GbpCancelBuffer(ServiceCtx Context, BinaryReader ParcelReader)
|
||||
{
|
||||
//TODO: Errors.
|
||||
@@ -266,7 +285,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.Android
|
||||
|
||||
long FbSize = (uint)FbWidth * FbHeight * 4;
|
||||
|
||||
HNvMap NvMap = GetNvMap(Context, Slot);
|
||||
NvMap NvMap = GetNvMap(Context, Slot);
|
||||
|
||||
if ((ulong)(NvMap.Address + FbSize) > AMemoryMgr.AddrSize)
|
||||
{
|
||||
@@ -330,7 +349,17 @@ namespace Ryujinx.Core.OsHle.IpcServices.Android
|
||||
Rotate = -MathF.PI * 0.5f;
|
||||
}
|
||||
|
||||
byte* Fb = (byte*)Context.Ns.Memory.Ram + NvMap.Address;
|
||||
lock (RenderQueueLock)
|
||||
{
|
||||
if (NvFlingerDisposed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Interlocked.Increment(ref RenderQueueCount);
|
||||
}
|
||||
|
||||
byte* Fb = (byte*)Context.Memory.Ram + NvMap.Address;
|
||||
|
||||
Context.Ns.Gpu.Renderer.QueueAction(delegate()
|
||||
{
|
||||
@@ -346,6 +375,8 @@ namespace Ryujinx.Core.OsHle.IpcServices.Android
|
||||
|
||||
BufferQueue[Slot].State = BufferState.Free;
|
||||
|
||||
Interlocked.Decrement(ref RenderQueueCount);
|
||||
|
||||
lock (WaitBufferFree)
|
||||
{
|
||||
WaitBufferFree.Set();
|
||||
@@ -353,7 +384,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.Android
|
||||
});
|
||||
}
|
||||
|
||||
private HNvMap GetNvMap(ServiceCtx Context, int Slot)
|
||||
private NvMap GetNvMap(ServiceCtx Context, int Slot)
|
||||
{
|
||||
int NvMapHandle = BitConverter.ToInt32(BufferQueue[Slot].Data.RawData, 0x4c);
|
||||
|
||||
@@ -366,7 +397,9 @@ namespace Ryujinx.Core.OsHle.IpcServices.Android
|
||||
NvMapHandle = BitConverter.ToInt32(RawValue, 0);
|
||||
}
|
||||
|
||||
return Context.Ns.Os.Handles.GetData<HNvMap>(NvMapHandle);
|
||||
ServiceNvDrv NvDrv = (ServiceNvDrv)Context.Process.Services.GetService("nvdrv");
|
||||
|
||||
return NvDrv.GetNvMap(NvMapHandle);
|
||||
}
|
||||
|
||||
private int GetFreeSlotBlocking(int Width, int Height)
|
||||
@@ -432,10 +465,24 @@ namespace Ryujinx.Core.OsHle.IpcServices.Android
|
||||
Dispose(true);
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
protected virtual void Dispose(bool Disposing)
|
||||
{
|
||||
if (disposing)
|
||||
if (Disposing && !NvFlingerDisposed)
|
||||
{
|
||||
lock (RenderQueueLock)
|
||||
{
|
||||
NvFlingerDisposed = true;
|
||||
}
|
||||
|
||||
//Ensure that all pending actions was sent before
|
||||
//we can safely assume that the class was disposed.
|
||||
while (RenderQueueCount > 0)
|
||||
{
|
||||
Thread.Yield();
|
||||
}
|
||||
|
||||
Renderer.ResetFrameBuffer();
|
||||
|
||||
lock (WaitBufferFree)
|
||||
{
|
||||
KeepRunning = false;
|
||||
|
||||
Reference in New Issue
Block a user