aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Core
diff options
context:
space:
mode:
Diffstat (limited to 'Ryujinx.Core')
-rw-r--r--Ryujinx.Core/OsHle/Services/Nv/INvDrvServices.cs2
-rw-r--r--Ryujinx.Core/OsHle/Services/Nv/NvMap.cs1
-rw-r--r--Ryujinx.Core/OsHle/Services/Vi/NvFlinger.cs119
3 files changed, 45 insertions, 77 deletions
diff --git a/Ryujinx.Core/OsHle/Services/Nv/INvDrvServices.cs b/Ryujinx.Core/OsHle/Services/Nv/INvDrvServices.cs
index e41f03a4..abda5b86 100644
--- a/Ryujinx.Core/OsHle/Services/Nv/INvDrvServices.cs
+++ b/Ryujinx.Core/OsHle/Services/Nv/INvDrvServices.cs
@@ -244,6 +244,8 @@ namespace Ryujinx.Core.OsHle.Services.Nv
Context.Memory.WriteInt64(Position + 0x20, Offset);
+ Map.GpuAddress = Offset;
+
return 0;
}
diff --git a/Ryujinx.Core/OsHle/Services/Nv/NvMap.cs b/Ryujinx.Core/OsHle/Services/Nv/NvMap.cs
index 9ef70319..f3dd1f47 100644
--- a/Ryujinx.Core/OsHle/Services/Nv/NvMap.cs
+++ b/Ryujinx.Core/OsHle/Services/Nv/NvMap.cs
@@ -8,5 +8,6 @@ namespace Ryujinx.Core.OsHle.Services.Nv
public int Align;
public int Kind;
public long CpuAddress;
+ public long GpuAddress;
}
} \ No newline at end of file
diff --git a/Ryujinx.Core/OsHle/Services/Vi/NvFlinger.cs b/Ryujinx.Core/OsHle/Services/Vi/NvFlinger.cs
index 45b99ead..4ab64e2a 100644
--- a/Ryujinx.Core/OsHle/Services/Vi/NvFlinger.cs
+++ b/Ryujinx.Core/OsHle/Services/Vi/NvFlinger.cs
@@ -2,6 +2,7 @@ using ChocolArm64.Memory;
using Ryujinx.Core.OsHle.Handles;
using Ryujinx.Core.OsHle.Services.Nv;
using Ryujinx.Graphics.Gal;
+using Ryujinx.Graphics.Gpu;
using System;
using System.Collections.Generic;
using System.IO;
@@ -63,13 +64,7 @@ namespace Ryujinx.Core.OsHle.Services.Android
private ManualResetEvent WaitBufferFree;
- private object RenderQueueLock;
-
- private int RenderQueueCount;
-
- private bool NvFlingerDisposed;
-
- private bool KeepRunning;
+ private bool Disposed;
public NvFlinger(IGalRenderer Renderer, KEvent ReleaseEvent)
{
@@ -92,10 +87,6 @@ namespace Ryujinx.Core.OsHle.Services.Android
BufferQueue = new BufferEntry[0x40];
WaitBufferFree = new ManualResetEvent(false);
-
- RenderQueueLock = new object();
-
- KeepRunning = true;
}
public long ProcessParcelRequest(ServiceCtx Context, byte[] ParcelData, int Code)
@@ -285,35 +276,24 @@ namespace Ryujinx.Core.OsHle.Services.Android
return 0;
}
- private unsafe void SendFrameBuffer(ServiceCtx Context, int Slot)
+ private void SendFrameBuffer(ServiceCtx Context, int Slot)
{
- int FbWidth = BufferQueue[Slot].Data.Width;
- int FbHeight = BufferQueue[Slot].Data.Height;
-
- long FbSize = (uint)FbWidth * FbHeight * 4;
+ int FbWidth = 1280;
+ int FbHeight = 720;
NvMap Map = GetNvMap(Context, Slot);
NvMapFb MapFb = (NvMapFb)INvDrvServices.NvMapsFb.GetData(Context.Process, 0);
- long Address = Map.CpuAddress;
+ long CpuAddr = Map.CpuAddress;
+ long GpuAddr = Map.GpuAddress;
if (MapFb.HasBufferOffset(Slot))
{
- Address += MapFb.GetBufferOffset(Slot);
- }
-
- if ((ulong)(Address + FbSize) > AMemoryMgr.AddrSize)
- {
- Logging.Error($"Frame buffer address {Address:x16} is invalid!");
-
- BufferQueue[Slot].State = BufferState.Free;
+ CpuAddr += MapFb.GetBufferOffset(Slot);
- ReleaseEvent.Handle.Set();
-
- WaitBufferFree.Set();
-
- return;
+ //TODO: Enable once the frame buffers problems are fixed.
+ //GpuAddr += MapFb.GetBufferOffset(Slot);
}
BufferQueue[Slot].State = BufferState.Acquired;
@@ -367,41 +347,28 @@ namespace Ryujinx.Core.OsHle.Services.Android
Rotate = -MathF.PI * 0.5f;
}
- lock (RenderQueueLock)
- {
- if (NvFlingerDisposed)
- {
- return;
- }
+ Renderer.SetFrameBufferTransform(ScaleX, ScaleY, Rotate, OffsX, OffsY);
- Interlocked.Increment(ref RenderQueueCount);
+ //TODO: Support double buffering here aswell, it is broken for GPU
+ //frame buffers because it seems to be completely out of sync.
+ if (Context.Ns.Gpu.Engine3d.IsFrameBufferPosition(GpuAddr))
+ {
+ //Frame buffer is rendered to by the GPU, we can just
+ //bind the frame buffer texture, it's not necessary to read anything.
+ Renderer.SetFrameBuffer(GpuAddr);
}
-
- byte* Fb = (byte*)Context.Memory.Ram + Address;
-
- Context.Ns.Gpu.Renderer.QueueAction(delegate()
+ else
{
- Context.Ns.Gpu.Renderer.SetFrameBuffer(
- Fb,
- FbWidth,
- FbHeight,
- ScaleX,
- ScaleY,
- OffsX,
- OffsY,
- Rotate);
-
- BufferQueue[Slot].State = BufferState.Free;
+ //Frame buffer is not set on the GPU registers, in this case
+ //assume that the app is manually writing to it.
+ Texture Texture = new Texture(CpuAddr, FbWidth, FbHeight);
- Interlocked.Decrement(ref RenderQueueCount);
+ byte[] Data = TextureReader.Read(Context.Memory, Texture);
- ReleaseEvent.Handle.Set();
+ Renderer.SetFrameBuffer(Data, FbWidth, FbHeight);
+ }
- lock (WaitBufferFree)
- {
- WaitBufferFree.Set();
- }
- });
+ Context.Ns.Gpu.Renderer.QueueAction(() => ReleaseBuffer(Slot));
}
private NvMap GetNvMap(ServiceCtx Context, int Slot)
@@ -420,6 +387,18 @@ namespace Ryujinx.Core.OsHle.Services.Android
return INvDrvServices.NvMaps.GetData<NvMap>(Context.Process, NvMapHandle);
}
+ private void ReleaseBuffer(int Slot)
+ {
+ BufferQueue[Slot].State = BufferState.Free;
+
+ ReleaseEvent.Handle.Set();
+
+ lock (WaitBufferFree)
+ {
+ WaitBufferFree.Set();
+ }
+ }
+
private int GetFreeSlotBlocking(int Width, int Height)
{
int Slot;
@@ -435,7 +414,7 @@ namespace Ryujinx.Core.OsHle.Services.Android
Logging.Debug("Waiting for a free BufferQueue slot...");
- if (!KeepRunning)
+ if (Disposed)
{
break;
}
@@ -445,7 +424,7 @@ namespace Ryujinx.Core.OsHle.Services.Android
WaitBufferFree.WaitOne();
}
- while (KeepRunning);
+ while (!Disposed);
Logging.Debug($"Found free BufferQueue slot {Slot}!");
@@ -485,26 +464,12 @@ namespace Ryujinx.Core.OsHle.Services.Android
protected virtual void Dispose(bool Disposing)
{
- if (Disposing && !NvFlingerDisposed)
+ if (Disposing && !Disposed)
{
- 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();
+ Disposed = true;
lock (WaitBufferFree)
{
- KeepRunning = false;
-
WaitBufferFree.Set();
}