Implement Surface Flinger shared layers.
Co-authored-by: Alula <6276139+alula@users.noreply.github.com>
This commit is contained in:
parent
e2a5e69f4c
commit
965fb9dd5f
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user