From 1bd99e559785ecf6a40e1bcb4a717642014c078f Mon Sep 17 00:00:00 2001 From: gdkchan Date: Tue, 20 Mar 2018 12:18:25 -0300 Subject: [PATCH] Support different framebuffer offsets (fixes #59) --- Ryujinx.Core/OsHle/GlobalStateTable.cs | 11 ++++- Ryujinx.Core/OsHle/IdDictionary.cs | 5 +++ Ryujinx.Core/OsHle/Process.cs | 4 +- Ryujinx.Core/OsHle/Services/Nv/NvMap.cs | 2 +- Ryujinx.Core/OsHle/Services/Nv/NvMapFb.cs | 40 +++++++++++++++++++ .../OsHle/Services/Nv/ServiceNvDrv.cs | 17 +++++--- Ryujinx.Core/OsHle/Services/Vi/NvFlinger.cs | 17 ++++++-- 7 files changed, 82 insertions(+), 14 deletions(-) create mode 100644 Ryujinx.Core/OsHle/Services/Nv/NvMapFb.cs diff --git a/Ryujinx.Core/OsHle/GlobalStateTable.cs b/Ryujinx.Core/OsHle/GlobalStateTable.cs index ffc9f262..2a5714ad 100644 --- a/Ryujinx.Core/OsHle/GlobalStateTable.cs +++ b/Ryujinx.Core/OsHle/GlobalStateTable.cs @@ -12,11 +12,18 @@ namespace Ryujinx.Core.OsHle DictByProcess = new ConcurrentDictionary(); } - public int Add(Process Process, object Obj) + public bool Add(Process Process, int Id, object Data) { IdDictionary Dict = DictByProcess.GetOrAdd(Process, (Key) => new IdDictionary()); - return Dict.Add(Obj); + return Dict.Add(Id, Data); + } + + public int Add(Process Process, object Data) + { + IdDictionary Dict = DictByProcess.GetOrAdd(Process, (Key) => new IdDictionary()); + + return Dict.Add(Data); } public object GetData(Process Process, int Id) diff --git a/Ryujinx.Core/OsHle/IdDictionary.cs b/Ryujinx.Core/OsHle/IdDictionary.cs index 0746ae81..2a498e7f 100644 --- a/Ryujinx.Core/OsHle/IdDictionary.cs +++ b/Ryujinx.Core/OsHle/IdDictionary.cs @@ -15,6 +15,11 @@ namespace Ryujinx.Core.OsHle Objs = new ConcurrentDictionary(); } + public bool Add(int Id, object Data) + { + return Objs.TryAdd(Id, Data); + } + public int Add(object Data) { if (Objs.TryAdd(FreeIdHint, Data)) diff --git a/Ryujinx.Core/OsHle/Process.cs b/Ryujinx.Core/OsHle/Process.cs index 1846e576..25c10a43 100644 --- a/Ryujinx.Core/OsHle/Process.cs +++ b/Ryujinx.Core/OsHle/Process.cs @@ -356,9 +356,9 @@ namespace Ryujinx.Core.OsHle ServiceNvDrv.Fds.DeleteProcess(this); - ServiceNvDrv.NvMaps.DeleteProcess(this); - + ServiceNvDrv.NvMaps .DeleteProcess(this); ServiceNvDrv.NvMapsById.DeleteProcess(this); + ServiceNvDrv.NvMapsFb .DeleteProcess(this); Scheduler.Dispose(); diff --git a/Ryujinx.Core/OsHle/Services/Nv/NvMap.cs b/Ryujinx.Core/OsHle/Services/Nv/NvMap.cs index ca844f9f..d5a5a800 100644 --- a/Ryujinx.Core/OsHle/Services/Nv/NvMap.cs +++ b/Ryujinx.Core/OsHle/Services/Nv/NvMap.cs @@ -7,6 +7,6 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices public int Size; public int Align; public int Kind; - public long Address; + public long CpuAddress; } } \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Services/Nv/NvMapFb.cs b/Ryujinx.Core/OsHle/Services/Nv/NvMapFb.cs new file mode 100644 index 00000000..1066cc95 --- /dev/null +++ b/Ryujinx.Core/OsHle/Services/Nv/NvMapFb.cs @@ -0,0 +1,40 @@ +using System; +using System.Collections.Generic; + +namespace Ryujinx.Core.OsHle.IpcServices.NvServices +{ + class NvMapFb + { + private List BufferOffs; + + public NvMapFb() + { + BufferOffs = new List(); + } + + public void AddBufferOffset(long Offset) + { + BufferOffs.Add(Offset); + } + + public bool HasBufferOffset(int Index) + { + if ((uint)Index >= BufferOffs.Count) + { + return false; + } + + return true; + } + + public long GetBufferOffset(int Index) + { + if ((uint)Index >= BufferOffs.Count) + { + throw new ArgumentOutOfRangeException(nameof(Index)); + } + + return BufferOffs[Index]; + } + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Services/Nv/ServiceNvDrv.cs b/Ryujinx.Core/OsHle/Services/Nv/ServiceNvDrv.cs index ef223772..a1e0e532 100644 --- a/Ryujinx.Core/OsHle/Services/Nv/ServiceNvDrv.cs +++ b/Ryujinx.Core/OsHle/Services/Nv/ServiceNvDrv.cs @@ -22,6 +22,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices public static GlobalStateTable NvMaps { get; private set; } public static GlobalStateTable NvMapsById { get; private set; } + public static GlobalStateTable NvMapsFb { get; private set; } private KEvent Event; @@ -76,6 +77,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices NvMaps = new GlobalStateTable(); NvMapsById = new GlobalStateTable(); + NvMapsFb = new GlobalStateTable(); } public long Open(ServiceCtx Context) @@ -131,6 +133,8 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices Context.ResponseData.Write(0); + NvMapsFb.Add(Context.Process, 0, new NvMapFb()); + return 0; } @@ -209,8 +213,11 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices if (Handle == 0) { - //Handle 0 is valid here, but it refers to something else. - //TODO: Figure out what, for now just return success. + //This is used to store offsets for the Framebuffer(s); + NvMapFb MapFb = (NvMapFb)NvMapsFb.GetData(Context.Process, 0); + + MapFb.AddBufferOffset(BuffAddr); + return 0; } @@ -225,11 +232,11 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices if ((Flags & 1) != 0) { - Offset = Context.Ns.Gpu.MapMemory(Map.Address, Offset, Map.Size); + Offset = Context.Ns.Gpu.MapMemory(Map.CpuAddress, Offset, Map.Size); } else { - Offset = Context.Ns.Gpu.MapMemory(Map.Address, Map.Size); + Offset = Context.Ns.Gpu.MapMemory(Map.CpuAddress, Map.Size); } Context.Memory.WriteInt64(Position + 0x20, Offset); @@ -614,7 +621,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices return -1; //TODO: Corrent error code. } - Map.Address = Addr; + Map.CpuAddress = Addr; Map.Align = Align; Map.Kind = Kind; diff --git a/Ryujinx.Core/OsHle/Services/Vi/NvFlinger.cs b/Ryujinx.Core/OsHle/Services/Vi/NvFlinger.cs index 3a7a2ee6..550260bb 100644 --- a/Ryujinx.Core/OsHle/Services/Vi/NvFlinger.cs +++ b/Ryujinx.Core/OsHle/Services/Vi/NvFlinger.cs @@ -289,11 +289,20 @@ namespace Ryujinx.Core.OsHle.IpcServices.Android long FbSize = (uint)FbWidth * FbHeight * 4; - NvMap NvMap = GetNvMap(Context, Slot); + NvMap Map = GetNvMap(Context, Slot); - if ((ulong)(NvMap.Address + FbSize) > AMemoryMgr.AddrSize) + NvMapFb MapFb = (NvMapFb)ServiceNvDrv.NvMapsFb.GetData(Context.Process, 0); + + long Address = Map.CpuAddress; + + if (MapFb.HasBufferOffset(Slot)) { - Logging.Error($"Frame buffer address {NvMap.Address:x16} is invalid!"); + Address += MapFb.GetBufferOffset(Slot); + } + + if ((ulong)(Address + FbSize) > AMemoryMgr.AddrSize) + { + Logging.Error($"Frame buffer address {Address:x16} is invalid!"); BufferQueue[Slot].State = BufferState.Free; @@ -365,7 +374,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.Android Interlocked.Increment(ref RenderQueueCount); } - byte* Fb = (byte*)Context.Memory.Ram + NvMap.Address; + byte* Fb = (byte*)Context.Memory.Ram + Address; Context.Ns.Gpu.Renderer.QueueAction(delegate() {