diff options
| author | Thomas Guillemard <me@thog.eu> | 2019-11-03 18:26:29 +0100 |
|---|---|---|
| committer | Ac_K <Acoustik666@gmail.com> | 2019-11-03 18:26:29 +0100 |
| commit | b29950dbd6657f6f6511bc2df2efc4b0ff40e8b9 (patch) | |
| tree | 204cba19b5fd54744d247119c0b725c89d524cc0 /Ryujinx.HLE/HOS/Services/Android/NvFlinger.cs | |
| parent | 9426ef3f06916f4206213b28b1ca162c851d4e07 (diff) | |
hle: Fix some inconsistencies in namespace naming in Services (#808)
Also fix IShopServiceAccessSystemInterface being in the wrong namespace.
Diffstat (limited to 'Ryujinx.HLE/HOS/Services/Android/NvFlinger.cs')
| -rw-r--r-- | Ryujinx.HLE/HOS/Services/Android/NvFlinger.cs | 413 |
1 files changed, 0 insertions, 413 deletions
diff --git a/Ryujinx.HLE/HOS/Services/Android/NvFlinger.cs b/Ryujinx.HLE/HOS/Services/Android/NvFlinger.cs deleted file mode 100644 index 63df78e5..00000000 --- a/Ryujinx.HLE/HOS/Services/Android/NvFlinger.cs +++ /dev/null @@ -1,413 +0,0 @@ -using Ryujinx.Common.Logging; -using Ryujinx.Graphics.Gal; -using Ryujinx.Graphics.Memory; -using Ryujinx.HLE.HOS.Kernel.Threading; -using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostAsGpu; -using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvMap; -using System; -using System.Collections.Generic; -using System.IO; -using System.Runtime.InteropServices; -using System.Text; -using System.Threading; - -using static Ryujinx.HLE.HOS.Services.Android.Parcel; - -namespace Ryujinx.HLE.HOS.Services.Android -{ - class NvFlinger : IDisposable - { - private delegate ResultCode ServiceProcessParcel(ServiceCtx context, BinaryReader parcelReader); - - private Dictionary<(string, int), ServiceProcessParcel> _commands; - - private KEvent _binderEvent; - - private IGalRenderer _renderer; - - private const int BufferQueueCount = 0x40; - private const int BufferQueueMask = BufferQueueCount - 1; - - private BufferEntry[] _bufferQueue; - - private AutoResetEvent _waitBufferFree; - - private bool _disposed; - - public NvFlinger(IGalRenderer renderer, KEvent binderEvent) - { - _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 }, - { ("android.gui.IGraphicBufferProducer", 0xa), GbpConnect }, - { ("android.gui.IGraphicBufferProducer", 0xb), GbpDisconnect }, - { ("android.gui.IGraphicBufferProducer", 0xe), GbpPreallocBuffer } - }; - - _renderer = renderer; - _binderEvent = binderEvent; - - _bufferQueue = new BufferEntry[0x40]; - - _waitBufferFree = new AutoResetEvent(false); - } - - public ResultCode ProcessParcelRequest(ServiceCtx context, byte[] parcelData, int code) - { - using (MemoryStream ms = new MemoryStream(parcelData)) - { - BinaryReader reader = new BinaryReader(ms); - - ms.Seek(4, SeekOrigin.Current); - - int strSize = reader.ReadInt32(); - - string interfaceName = Encoding.Unicode.GetString(reader.ReadBytes(strSize * 2)); - - long remainder = ms.Position & 0xf; - - if (remainder != 0) - { - ms.Seek(0x10 - remainder, SeekOrigin.Current); - } - - ms.Seek(0x50, SeekOrigin.Begin); - - if (_commands.TryGetValue((interfaceName, code), out ServiceProcessParcel procReq)) - { - Logger.PrintDebug(LogClass.ServiceVi, $"{interfaceName} {procReq.Method.Name}"); - - return procReq(context, reader); - } - else - { - throw new NotImplementedException($"{interfaceName} {code}"); - } - } - } - - private ResultCode GbpRequestBuffer(ServiceCtx context, BinaryReader parcelReader) - { - int slot = parcelReader.ReadInt32(); - - using (MemoryStream ms = new MemoryStream()) - { - BinaryWriter writer = new BinaryWriter(ms); - - BufferEntry entry = _bufferQueue[slot]; - - int bufferCount = 1; //? - long bufferSize = entry.Data.Size; - - writer.Write(bufferCount); - writer.Write(bufferSize); - - entry.Data.Write(writer); - - writer.Write(0); - - return MakeReplyParcel(context, ms.ToArray()); - } - } - - private ResultCode GbpDequeueBuffer(ServiceCtx context, BinaryReader parcelReader) - { - // TODO: Errors. - int format = parcelReader.ReadInt32(); - int width = parcelReader.ReadInt32(); - int height = parcelReader.ReadInt32(); - int getTimestamps = parcelReader.ReadInt32(); - int usage = parcelReader.ReadInt32(); - - int slot = GetFreeSlotBlocking(width, height); - - return MakeReplyParcel(context, slot, 1, 0x24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); - } - - private ResultCode GbpQueueBuffer(ServiceCtx context, BinaryReader parcelReader) - { - context.Device.Statistics.RecordGameFrameTime(); - - // TODO: Errors. - int slot = parcelReader.ReadInt32(); - - long Position = parcelReader.BaseStream.Position; - - QueueBufferObject queueBufferObject = ReadFlattenedObject<QueueBufferObject>(parcelReader); - - parcelReader.BaseStream.Position = Position; - - _bufferQueue[slot].Transform = queueBufferObject.Transform; - _bufferQueue[slot].Crop = queueBufferObject.Crop; - - _bufferQueue[slot].State = BufferState.Queued; - - SendFrameBuffer(context, slot); - - if (context.Device.EnableDeviceVsync) - { - context.Device.VsyncEvent.WaitOne(); - } - - return MakeReplyParcel(context, 1280, 720, 0, 0, 0); - } - - private ResultCode GbpDetachBuffer(ServiceCtx context, BinaryReader parcelReader) - { - return MakeReplyParcel(context, 0); - } - - private ResultCode GbpCancelBuffer(ServiceCtx context, BinaryReader parcelReader) - { - // TODO: Errors. - int slot = parcelReader.ReadInt32(); - - MultiFence fence = ReadFlattenedObject<MultiFence>(parcelReader); - - _bufferQueue[slot].State = BufferState.Free; - - _waitBufferFree.Set(); - - return MakeReplyParcel(context, 0); - } - - private ResultCode GbpQuery(ServiceCtx context, BinaryReader parcelReader) - { - return MakeReplyParcel(context, 0, 0); - } - - private ResultCode GbpConnect(ServiceCtx context, BinaryReader parcelReader) - { - return MakeReplyParcel(context, 1280, 720, 0, 0, 0); - } - - private ResultCode GbpDisconnect(ServiceCtx context, BinaryReader parcelReader) - { - return MakeReplyParcel(context, 0); - } - - private ResultCode GbpPreallocBuffer(ServiceCtx context, BinaryReader parcelReader) - { - int slot = parcelReader.ReadInt32(); - - bool hasInput = parcelReader.ReadInt32() == 1; - - if (hasInput) - { - byte[] graphicBuffer = ReadFlattenedObject(parcelReader); - - _bufferQueue[slot].State = BufferState.Free; - - using (BinaryReader graphicBufferReader = new BinaryReader(new MemoryStream(graphicBuffer))) - { - _bufferQueue[slot].Data = new GbpBuffer(graphicBufferReader); - } - - } - - return MakeReplyParcel(context, 0); - } - - private byte[] ReadFlattenedObject(BinaryReader reader) - { - long flattenedObjectSize = reader.ReadInt64(); - - return reader.ReadBytes((int)flattenedObjectSize); - } - - private unsafe T ReadFlattenedObject<T>(BinaryReader reader) where T: struct - { - byte[] data = ReadFlattenedObject(reader); - - fixed (byte* ptr = data) - { - return Marshal.PtrToStructure<T>((IntPtr)ptr); - } - } - - private ResultCode MakeReplyParcel(ServiceCtx context, params int[] ints) - { - using (MemoryStream ms = new MemoryStream()) - { - BinaryWriter writer = new BinaryWriter(ms); - - foreach (int Int in ints) - { - writer.Write(Int); - } - - return MakeReplyParcel(context, ms.ToArray()); - } - } - - private ResultCode MakeReplyParcel(ServiceCtx context, byte[] data) - { - (long replyPos, long replySize) = context.Request.GetBufferType0x22(); - - byte[] reply = MakeParcel(data, new byte[0]); - - context.Memory.WriteBytes(replyPos, reply); - - return ResultCode.Success; - } - - private GalImageFormat ConvertColorFormat(ColorFormat colorFormat) - { - switch (colorFormat) - { - case ColorFormat.A8B8G8R8: - return GalImageFormat.Rgba8 | GalImageFormat.Unorm; - case ColorFormat.X8B8G8R8: - return GalImageFormat.Rgbx8 | GalImageFormat.Unorm; - case ColorFormat.R5G6B5: - return GalImageFormat.Bgr565 | GalImageFormat.Unorm; - case ColorFormat.A8R8G8B8: - return GalImageFormat.Bgra8 | GalImageFormat.Unorm; - case ColorFormat.A4B4G4R4: - return GalImageFormat.Rgba4 | GalImageFormat.Unorm; - default: - throw new NotImplementedException($"Color Format \"{colorFormat}\" not implemented!"); - } - } - - // TODO: support multi surface - private void SendFrameBuffer(ServiceCtx context, int slot) - { - int fbWidth = _bufferQueue[slot].Data.Header.Width; - int fbHeight = _bufferQueue[slot].Data.Header.Height; - - int nvMapHandle = _bufferQueue[slot].Data.Buffer.Surfaces[0].NvMapHandle; - - if (nvMapHandle == 0) - { - nvMapHandle = _bufferQueue[slot].Data.Buffer.NvMapId; - } - - int bufferOffset = _bufferQueue[slot].Data.Buffer.Surfaces[0].Offset; - - NvMapHandle map = NvMapDeviceFile.GetMapFromHandle(context.Process, nvMapHandle); - - long fbAddr = map.Address + bufferOffset; - - _bufferQueue[slot].State = BufferState.Acquired; - - Rect crop = _bufferQueue[slot].Crop; - - bool flipX = _bufferQueue[slot].Transform.HasFlag(HalTransform.FlipX); - bool flipY = _bufferQueue[slot].Transform.HasFlag(HalTransform.FlipY); - - GalImageFormat imageFormat = ConvertColorFormat(_bufferQueue[slot].Data.Buffer.Surfaces[0].ColorFormat); - - int BlockHeight = 1 << _bufferQueue[slot].Data.Buffer.Surfaces[0].BlockHeightLog2; - - // Note: Rotation is being ignored. - - int top = crop.Top; - int left = crop.Left; - int right = crop.Right; - int bottom = crop.Bottom; - - NvGpuVmm vmm = NvHostAsGpuDeviceFile.GetAddressSpaceContext(context.Process).Vmm; - - _renderer.QueueAction(() => - { - if (!_renderer.Texture.TryGetImage(fbAddr, out GalImage image)) - { - image = new GalImage( - fbWidth, - fbHeight, 1, 1, 1, BlockHeight, 1, - GalMemoryLayout.BlockLinear, - imageFormat, - GalTextureTarget.TwoD); - } - - context.Device.Gpu.ResourceManager.ClearPbCache(); - context.Device.Gpu.ResourceManager.SendTexture(vmm, fbAddr, image); - - _renderer.RenderTarget.SetTransform(flipX, flipY, top, left, right, bottom); - _renderer.RenderTarget.Present(fbAddr); - - ReleaseBuffer(slot); - }); - } - - private void ReleaseBuffer(int slot) - { - _bufferQueue[slot].State = BufferState.Free; - - _binderEvent.ReadableEvent.Signal(); - - _waitBufferFree.Set(); - } - - private int GetFreeSlotBlocking(int width, int height) - { - int slot; - - do - { - if ((slot = GetFreeSlot(width, height)) != -1) - { - break; - } - - if (_disposed) - { - break; - } - - _waitBufferFree.WaitOne(); - } - while (!_disposed); - - return slot; - } - - private int GetFreeSlot(int width, int height) - { - lock (_bufferQueue) - { - for (int slot = 0; slot < _bufferQueue.Length; slot++) - { - if (_bufferQueue[slot].State != BufferState.Free) - { - continue; - } - - GbpBuffer data = _bufferQueue[slot].Data; - - if (data.Header.Width == width && - data.Header.Height == height) - { - _bufferQueue[slot].State = BufferState.Dequeued; - - return slot; - } - } - } - - return -1; - } - - public void Dispose() - { - Dispose(true); - } - - protected virtual void Dispose(bool disposing) - { - if (disposing && !_disposed) - { - _disposed = true; - - _waitBufferFree.Set(); - _waitBufferFree.Dispose(); - } - } - } -}
\ No newline at end of file |
