Implement Surface Flinger shared layers.

Co-authored-by: Alula <6276139+alula@users.noreply.github.com>
This commit is contained in:
Jacobwasbeast 2025-02-07 04:27:01 -06:00
parent e2a5e69f4c
commit 965fb9dd5f
5 changed files with 53 additions and 63 deletions

View File

@ -114,6 +114,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys
} }
[CommandCmif(26)] [CommandCmif(26)]
// AcquireCallerAppletCaptureSharedBuffer() -> (b8, u32) // AcquireCallerAppletCaptureSharedBuffer() -> (b8, u32)
public ResultCode AcquireCallerAppletCaptureSharedBuffer(ServiceCtx context) public ResultCode AcquireCallerAppletCaptureSharedBuffer(ServiceCtx context)
{ {
@ -123,5 +124,12 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys
return ResultCode.Success; return ResultCode.Success;
} }
[CommandCmif(27)]
public ResultCode ReleaseCallerAppletCaptureSharedBuffer(ServiceCtx context)
{
context.ResponseData.Write(2);
return ResultCode.Success;
}
} }
} }

View File

@ -225,7 +225,6 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys
public ResultCode CreateManagedDisplayLayer(ServiceCtx context) public ResultCode CreateManagedDisplayLayer(ServiceCtx context)
{ {
context.Device.System.SurfaceFlinger.CreateLayer(out long layerId, _pid); context.Device.System.SurfaceFlinger.CreateLayer(out long layerId, _pid);
context.Device.System.SurfaceFlinger.SetRenderLayer(layerId);
context.ResponseData.Write(layerId); context.ResponseData.Write(layerId);
@ -236,9 +235,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys
// IsSystemBufferSharingEnabled() // IsSystemBufferSharingEnabled()
public ResultCode IsSystemBufferSharingEnabled(ServiceCtx context) public ResultCode IsSystemBufferSharingEnabled(ServiceCtx context)
{ {
// NOTE: Service checks a private field and return an error if the SystemBufferSharing is disabled. // TODO: Implement this once we have a way to check if we're not an AppletId.Application
// todo check if we're not an AppletId.Application
return ResultCode.Success; return ResultCode.Success;
} }

View File

@ -4,6 +4,7 @@ using Ryujinx.Common.Logging;
using Ryujinx.Common.PreciseSleep; using Ryujinx.Common.PreciseSleep;
using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.GAL;
using Ryujinx.Graphics.Gpu; using Ryujinx.Graphics.Gpu;
using Ryujinx.HLE.HOS.Kernel.Process;
using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvMap; using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvMap;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@ -38,8 +39,6 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
private readonly Lock _lock = new(); private readonly Lock _lock = new();
public long RenderLayerId { get; private set; }
private class Layer private class Layer
{ {
public int ProducerBinderId; public int ProducerBinderId;
@ -60,7 +59,6 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
{ {
_device = device; _device = device;
_layers = new Dictionary<long, Layer>(); _layers = new Dictionary<long, Layer>();
RenderLayerId = 0;
_composerThread = new Thread(HandleComposition) _composerThread = new Thread(HandleComposition)
{ {
@ -239,34 +237,12 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
private void CloseLayer(long layerId, Layer layer) 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) if (layer.State == LayerState.ManagedOpened)
{ {
layer.State = LayerState.ManagedClosed; layer.State = LayerState.ManagedClosed;
} }
} }
public void SetRenderLayer(long layerId)
{
lock (_lock)
{
RenderLayerId = layerId;
}
}
private Layer GetLayerByIdLocked(long layerId) private Layer GetLayerByIdLocked(long layerId)
{ {
foreach (KeyValuePair<long, Layer> pair in _layers) foreach (KeyValuePair<long, Layer> pair in _layers)
@ -360,13 +336,25 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
{ {
lock (_lock) lock (_lock)
{ {
// TODO: support multilayers (& multidisplay ?) foreach (var (layerId, layer) in _layers)
if (RenderLayerId == 0)
{ {
return; if (layer.State == LayerState.NotInitialized || layer.State == LayerState.ManagedClosed)
continue;
if (_device.System.KernelContext.Processes.TryGetValue(layer.Owner, out var process))
{
if (process.State == ProcessState.Exiting || process.State == ProcessState.Exited)
{
HOSBinderDriverServer.UnregisterBinderObject(layer.ProducerBinderId);
if (_layers.Remove(layerId))
{
CloseLayer(layerId, layer);
} }
Layer layer = GetLayerByIdLocked(RenderLayerId); continue;
}
}
Status acquireStatus = layer.Consumer.AcquireBuffer(out BufferItem item, 0); Status acquireStatus = layer.Consumer.AcquireBuffer(out BufferItem item, 0);
@ -394,7 +382,9 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
} }
else if (acquireStatus != Status.NoBufferAvailaible && acquireStatus != Status.InvalidOperation) else if (acquireStatus != Status.NoBufferAvailaible && acquireStatus != Status.InvalidOperation)
{ {
throw new InvalidOperationException(); Logger.Warning?.Print(LogClass.SurfaceFlinger, $"Failed to acquire buffer for layer {layerId} (status: {acquireStatus})");
continue;
}
} }
} }
} }

View File

@ -40,7 +40,6 @@ namespace Ryujinx.HLE.HOS.Services.Vi.RootService.ApplicationDisplayService
ulong pid = context.Device.System.AppletState.AppletResourceUserIds.GetData<ulong>((int)appletResourceUserId); ulong pid = context.Device.System.AppletState.AppletResourceUserIds.GetData<ulong>((int)appletResourceUserId);
context.Device.System.SurfaceFlinger.CreateLayer(out long layerId, pid); context.Device.System.SurfaceFlinger.CreateLayer(out long layerId, pid);
context.Device.System.SurfaceFlinger.SetRenderLayer(layerId);
context.ResponseData.Write(layerId); context.ResponseData.Write(layerId);

View File

@ -248,8 +248,6 @@ namespace Ryujinx.HLE.HOS.Services.Vi.RootService
return result; return result;
} }
context.Device.System.SurfaceFlinger.SetRenderLayer(layerId);
using Parcel parcel = new(0x28, 0x4); using Parcel parcel = new(0x28, 0x4);
parcel.WriteObject(producer, "dispdrv\0"); parcel.WriteObject(producer, "dispdrv\0");
@ -286,8 +284,6 @@ namespace Ryujinx.HLE.HOS.Services.Vi.RootService
// TODO: support multi display. // TODO: support multi display.
IBinder producer = context.Device.System.SurfaceFlinger.CreateLayer(out long layerId, 0, LayerState.Stray); 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); using Parcel parcel = new(0x28, 0x4);
parcel.WriteObject(producer, "dispdrv\0"); parcel.WriteObject(producer, "dispdrv\0");