Allow more than one process, free resources on process dispose, implement SvcExitThread

This commit is contained in:
gdkchan 2018-03-12 01:04:52 -03:00
parent 3aaa4717b6
commit 7a27990faa
46 changed files with 926 additions and 598 deletions

View file

@ -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;