forked from Mirror/Ryujinx
Support different framebuffer offsets (fixes #59)
This commit is contained in:
parent
4314a8f3e5
commit
1bd99e5597
7 changed files with 82 additions and 14 deletions
|
@ -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)
|
||||||
|
|
|
@ -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))
|
||||||
|
|
|
@ -357,8 +357,8 @@ 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();
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
40
Ryujinx.Core/OsHle/Services/Nv/NvMapFb.cs
Normal file
40
Ryujinx.Core/OsHle/Services/Nv/NvMapFb.cs
Normal 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];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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()
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue