Support different framebuffer offsets (fixes #59)

This commit is contained in:
gdkchan 2018-03-20 12:18:25 -03:00
parent 4314a8f3e5
commit 1bd99e5597
7 changed files with 82 additions and 14 deletions

View file

@ -12,11 +12,18 @@ namespace Ryujinx.Core.OsHle
DictByProcess = new ConcurrentDictionary<Process, IdDictionary>(); DictByProcess = new ConcurrentDictionary<Process, IdDictionary>();
} }
public int Add(Process Process, object Obj) public bool Add(Process Process, int Id, object Data)
{ {
IdDictionary Dict = DictByProcess.GetOrAdd(Process, (Key) => new IdDictionary()); 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) public object GetData(Process Process, int Id)

View file

@ -15,6 +15,11 @@ namespace Ryujinx.Core.OsHle
Objs = new ConcurrentDictionary<int, object>(); Objs = new ConcurrentDictionary<int, object>();
} }
public bool Add(int Id, object Data)
{
return Objs.TryAdd(Id, Data);
}
public int Add(object Data) public int Add(object Data)
{ {
if (Objs.TryAdd(FreeIdHint, Data)) if (Objs.TryAdd(FreeIdHint, Data))

View file

@ -356,9 +356,9 @@ namespace Ryujinx.Core.OsHle
ServiceNvDrv.Fds.DeleteProcess(this); ServiceNvDrv.Fds.DeleteProcess(this);
ServiceNvDrv.NvMaps.DeleteProcess(this); ServiceNvDrv.NvMaps .DeleteProcess(this);
ServiceNvDrv.NvMapsById.DeleteProcess(this); ServiceNvDrv.NvMapsById.DeleteProcess(this);
ServiceNvDrv.NvMapsFb .DeleteProcess(this);
Scheduler.Dispose(); Scheduler.Dispose();

View file

@ -7,6 +7,6 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices
public int Size; public int Size;
public int Align; public int Align;
public int Kind; public int Kind;
public long Address; public long CpuAddress;
} }
} }

View file

@ -0,0 +1,40 @@
using System;
using System.Collections.Generic;
namespace Ryujinx.Core.OsHle.IpcServices.NvServices
{
class NvMapFb
{
private List<long> BufferOffs;
public NvMapFb()
{
BufferOffs = new List<long>();
}
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];
}
}
}

View file

@ -22,6 +22,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices
public static GlobalStateTable NvMaps { get; private set; } public static GlobalStateTable NvMaps { get; private set; }
public static GlobalStateTable NvMapsById { get; private set; } public static GlobalStateTable NvMapsById { get; private set; }
public static GlobalStateTable NvMapsFb { get; private set; }
private KEvent Event; private KEvent Event;
@ -76,6 +77,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices
NvMaps = new GlobalStateTable(); NvMaps = new GlobalStateTable();
NvMapsById = new GlobalStateTable(); NvMapsById = new GlobalStateTable();
NvMapsFb = new GlobalStateTable();
} }
public long Open(ServiceCtx Context) public long Open(ServiceCtx Context)
@ -131,6 +133,8 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices
Context.ResponseData.Write(0); Context.ResponseData.Write(0);
NvMapsFb.Add(Context.Process, 0, new NvMapFb());
return 0; return 0;
} }
@ -209,8 +213,11 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices
if (Handle == 0) if (Handle == 0)
{ {
//Handle 0 is valid here, but it refers to something else. //This is used to store offsets for the Framebuffer(s);
//TODO: Figure out what, for now just return success. NvMapFb MapFb = (NvMapFb)NvMapsFb.GetData(Context.Process, 0);
MapFb.AddBufferOffset(BuffAddr);
return 0; return 0;
} }
@ -225,11 +232,11 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices
if ((Flags & 1) != 0) 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 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); Context.Memory.WriteInt64(Position + 0x20, Offset);
@ -614,7 +621,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices
return -1; //TODO: Corrent error code. return -1; //TODO: Corrent error code.
} }
Map.Address = Addr; Map.CpuAddress = Addr;
Map.Align = Align; Map.Align = Align;
Map.Kind = Kind; Map.Kind = Kind;

View file

@ -289,11 +289,20 @@ namespace Ryujinx.Core.OsHle.IpcServices.Android
long FbSize = (uint)FbWidth * FbHeight * 4; 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; BufferQueue[Slot].State = BufferState.Free;
@ -365,7 +374,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.Android
Interlocked.Increment(ref RenderQueueCount); 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() Context.Ns.Gpu.Renderer.QueueAction(delegate()
{ {