From 965fb9dd5fe1af768dab247e942e10cf60e31092 Mon Sep 17 00:00:00 2001 From: Jacobwasbeast Date: Fri, 7 Feb 2025 04:27:01 -0600 Subject: [PATCH] Implement Surface Flinger shared layers. Co-authored-by: Alula <6276139+alula@users.noreply.github.com> --- .../SystemAppletProxy/IDisplayController.cs | 8 ++ .../SystemAppletProxy/ISelfController.cs | 5 +- .../Services/SurfaceFlinger/SurfaceFlinger.cs | 96 +++++++++---------- .../IManagerDisplayService.cs | 1 - .../RootService/IApplicationDisplayService.cs | 6 +- 5 files changed, 53 insertions(+), 63 deletions(-) diff --git a/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/IDisplayController.cs b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/IDisplayController.cs index 140b6435c..0c8da8339 100644 --- a/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/IDisplayController.cs +++ b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/IDisplayController.cs @@ -114,6 +114,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys } [CommandCmif(26)] + // AcquireCallerAppletCaptureSharedBuffer() -> (b8, u32) public ResultCode AcquireCallerAppletCaptureSharedBuffer(ServiceCtx context) { @@ -123,5 +124,12 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys return ResultCode.Success; } + + [CommandCmif(27)] + public ResultCode ReleaseCallerAppletCaptureSharedBuffer(ServiceCtx context) + { + context.ResponseData.Write(2); + return ResultCode.Success; + } } } diff --git a/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ISelfController.cs b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ISelfController.cs index ed9d5350f..71b4b482a 100644 --- a/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ISelfController.cs +++ b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ISelfController.cs @@ -225,7 +225,6 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys public ResultCode CreateManagedDisplayLayer(ServiceCtx context) { context.Device.System.SurfaceFlinger.CreateLayer(out long layerId, _pid); - context.Device.System.SurfaceFlinger.SetRenderLayer(layerId); context.ResponseData.Write(layerId); @@ -236,9 +235,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys // IsSystemBufferSharingEnabled() public ResultCode IsSystemBufferSharingEnabled(ServiceCtx context) { - // NOTE: Service checks a private field and return an error if the SystemBufferSharing is disabled. - - // todo check if we're not an AppletId.Application + // TODO: Implement this once we have a way to check if we're not an AppletId.Application return ResultCode.Success; } diff --git a/src/Ryujinx.HLE/HOS/Services/SurfaceFlinger/SurfaceFlinger.cs b/src/Ryujinx.HLE/HOS/Services/SurfaceFlinger/SurfaceFlinger.cs index ba6850c2b..78b286d7a 100644 --- a/src/Ryujinx.HLE/HOS/Services/SurfaceFlinger/SurfaceFlinger.cs +++ b/src/Ryujinx.HLE/HOS/Services/SurfaceFlinger/SurfaceFlinger.cs @@ -4,6 +4,7 @@ using Ryujinx.Common.Logging; using Ryujinx.Common.PreciseSleep; using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.Gpu; +using Ryujinx.HLE.HOS.Kernel.Process; using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvMap; using System; using System.Collections.Generic; @@ -38,8 +39,6 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger private readonly Lock _lock = new(); - public long RenderLayerId { get; private set; } - private class Layer { public int ProducerBinderId; @@ -60,7 +59,6 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger { _device = device; _layers = new Dictionary(); - RenderLayerId = 0; _composerThread = new Thread(HandleComposition) { @@ -239,34 +237,12 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger private void CloseLayer(long layerId, Layer layer) { - // If the layer was removed and the current in use, we need to change the current layer in use. - if (RenderLayerId == layerId) - { - // If no layer is availaible, reset to default value. - if (_layers.Count == 0) - { - SetRenderLayer(0); - } - else - { - SetRenderLayer(_layers.Last().Key); - } - } - if (layer.State == LayerState.ManagedOpened) { layer.State = LayerState.ManagedClosed; } } - public void SetRenderLayer(long layerId) - { - lock (_lock) - { - RenderLayerId = layerId; - } - } - private Layer GetLayerByIdLocked(long layerId) { foreach (KeyValuePair pair in _layers) @@ -360,41 +336,55 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger { lock (_lock) { - // TODO: support multilayers (& multidisplay ?) - if (RenderLayerId == 0) + foreach (var (layerId, layer) in _layers) { - return; - } - - Layer layer = GetLayerByIdLocked(RenderLayerId); - - Status acquireStatus = layer.Consumer.AcquireBuffer(out BufferItem item, 0); - - if (acquireStatus == Status.Success) - { - if (_device.VSyncMode == VSyncMode.Unbounded) + if (layer.State == LayerState.NotInitialized || layer.State == LayerState.ManagedClosed) + continue; + + if (_device.System.KernelContext.Processes.TryGetValue(layer.Owner, out var process)) { - if (_swapInterval != 0) + if (process.State == ProcessState.Exiting || process.State == ProcessState.Exited) { - UpdateSwapInterval(0); - _vSyncMode = _device.VSyncMode; + HOSBinderDriverServer.UnregisterBinderObject(layer.ProducerBinderId); + + if (_layers.Remove(layerId)) + { + CloseLayer(layerId, layer); + } + + continue; } } - else if (_device.VSyncMode != _vSyncMode) + + Status acquireStatus = layer.Consumer.AcquireBuffer(out BufferItem item, 0); + + if (acquireStatus == Status.Success) { - UpdateSwapInterval(_device.VSyncMode == VSyncMode.Unbounded ? 0 : item.SwapInterval); - _vSyncMode = _device.VSyncMode; - } - else if (item.SwapInterval != _swapInterval || _device.TargetVSyncInterval != _targetVSyncInterval) - { - UpdateSwapInterval(item.SwapInterval); - } + if (_device.VSyncMode == VSyncMode.Unbounded) + { + if (_swapInterval != 0) + { + UpdateSwapInterval(0); + _vSyncMode = _device.VSyncMode; + } + } + else if (_device.VSyncMode != _vSyncMode) + { + UpdateSwapInterval(_device.VSyncMode == VSyncMode.Unbounded ? 0 : item.SwapInterval); + _vSyncMode = _device.VSyncMode; + } + else if (item.SwapInterval != _swapInterval || _device.TargetVSyncInterval != _targetVSyncInterval) + { + UpdateSwapInterval(item.SwapInterval); + } - PostFrameBuffer(layer, item); - } - else if (acquireStatus != Status.NoBufferAvailaible && acquireStatus != Status.InvalidOperation) - { - throw new InvalidOperationException(); + PostFrameBuffer(layer, item); + } + else if (acquireStatus != Status.NoBufferAvailaible && acquireStatus != Status.InvalidOperation) + { + Logger.Warning?.Print(LogClass.SurfaceFlinger, $"Failed to acquire buffer for layer {layerId} (status: {acquireStatus})"); + continue; + } } } } diff --git a/src/Ryujinx.HLE/HOS/Services/Vi/RootService/ApplicationDisplayService/IManagerDisplayService.cs b/src/Ryujinx.HLE/HOS/Services/Vi/RootService/ApplicationDisplayService/IManagerDisplayService.cs index 3a08cdd78..837d6230e 100644 --- a/src/Ryujinx.HLE/HOS/Services/Vi/RootService/ApplicationDisplayService/IManagerDisplayService.cs +++ b/src/Ryujinx.HLE/HOS/Services/Vi/RootService/ApplicationDisplayService/IManagerDisplayService.cs @@ -40,7 +40,6 @@ namespace Ryujinx.HLE.HOS.Services.Vi.RootService.ApplicationDisplayService ulong pid = context.Device.System.AppletState.AppletResourceUserIds.GetData((int)appletResourceUserId); context.Device.System.SurfaceFlinger.CreateLayer(out long layerId, pid); - context.Device.System.SurfaceFlinger.SetRenderLayer(layerId); context.ResponseData.Write(layerId); diff --git a/src/Ryujinx.HLE/HOS/Services/Vi/RootService/IApplicationDisplayService.cs b/src/Ryujinx.HLE/HOS/Services/Vi/RootService/IApplicationDisplayService.cs index 9fe247e8a..56bcae1ee 100644 --- a/src/Ryujinx.HLE/HOS/Services/Vi/RootService/IApplicationDisplayService.cs +++ b/src/Ryujinx.HLE/HOS/Services/Vi/RootService/IApplicationDisplayService.cs @@ -248,8 +248,6 @@ namespace Ryujinx.HLE.HOS.Services.Vi.RootService return result; } - context.Device.System.SurfaceFlinger.SetRenderLayer(layerId); - using Parcel parcel = new(0x28, 0x4); parcel.WriteObject(producer, "dispdrv\0"); @@ -285,9 +283,7 @@ namespace Ryujinx.HLE.HOS.Services.Vi.RootService // TODO: support multi display. IBinder producer = context.Device.System.SurfaceFlinger.CreateLayer(out long layerId, 0, LayerState.Stray); - - context.Device.System.SurfaceFlinger.SetRenderLayer(layerId); - + using Parcel parcel = new(0x28, 0x4); parcel.WriteObject(producer, "dispdrv\0");