aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.HLE/HOS/Services/SurfaceFlinger/SurfaceFlinger.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Ryujinx.HLE/HOS/Services/SurfaceFlinger/SurfaceFlinger.cs')
-rw-r--r--Ryujinx.HLE/HOS/Services/SurfaceFlinger/SurfaceFlinger.cs150
1 files changed, 113 insertions, 37 deletions
diff --git a/Ryujinx.HLE/HOS/Services/SurfaceFlinger/SurfaceFlinger.cs b/Ryujinx.HLE/HOS/Services/SurfaceFlinger/SurfaceFlinger.cs
index be2e15bd..8fa27905 100644
--- a/Ryujinx.HLE/HOS/Services/SurfaceFlinger/SurfaceFlinger.cs
+++ b/Ryujinx.HLE/HOS/Services/SurfaceFlinger/SurfaceFlinger.cs
@@ -11,6 +11,8 @@ using System.Threading;
namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
{
+ using ResultCode = Ryujinx.HLE.HOS.Services.Vi.ResultCode;
+
class SurfaceFlinger : IConsumerListener, IDisposable
{
private const int TargetFps = 60;
@@ -45,6 +47,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
public BufferItemConsumer Consumer;
public BufferQueueCore Core;
public ulong Owner;
+ public LayerState State;
}
private class TextureCallbackInformation
@@ -92,24 +95,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
}
}
- public IGraphicBufferProducer OpenLayer(ulong pid, long layerId)
- {
- bool needCreate;
-
- lock (Lock)
- {
- needCreate = GetLayerByIdLocked(layerId) == null;
- }
-
- if (needCreate)
- {
- CreateLayerFromId(pid, layerId);
- }
-
- return GetProducerByLayerId(layerId);
- }
-
- public IGraphicBufferProducer CreateLayer(ulong pid, out long layerId)
+ public IGraphicBufferProducer CreateLayer(out long layerId, ulong pid, LayerState initialState = LayerState.ManagedClosed)
{
layerId = 1;
@@ -124,12 +110,12 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
}
}
- CreateLayerFromId(pid, layerId);
+ CreateLayerFromId(pid, layerId, initialState);
return GetProducerByLayerId(layerId);
}
- private void CreateLayerFromId(ulong pid, long layerId)
+ private void CreateLayerFromId(ulong pid, long layerId, LayerState initialState)
{
lock (Lock)
{
@@ -148,39 +134,129 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
Producer = producer,
Consumer = new BufferItemConsumer(_device, consumer, 0, -1, false, this),
Core = core,
- Owner = pid
+ Owner = pid,
+ State = initialState
});
}
}
- public bool CloseLayer(long layerId)
+ public ResultCode OpenLayer(ulong pid, long layerId, out IBinder producer)
+ {
+ Layer layer = GetLayerByIdLocked(layerId);
+
+ if (layer == null || layer.State != LayerState.ManagedClosed)
+ {
+ producer = null;
+
+ return ResultCode.InvalidArguments;
+ }
+
+ layer.State = LayerState.ManagedOpened;
+ producer = layer.Producer;
+
+ return ResultCode.Success;
+ }
+
+ public ResultCode CloseLayer(long layerId)
{
lock (Lock)
{
Layer layer = GetLayerByIdLocked(layerId);
- if (layer != null)
+ if (layer == null)
{
- HOSBinderDriverServer.UnregisterBinderObject(layer.ProducerBinderId);
+ Logger.Error?.Print(LogClass.SurfaceFlinger, $"Failed to close layer {layerId}");
+
+ return ResultCode.InvalidValue;
}
- bool removed = _layers.Remove(layerId);
+ CloseLayer(layerId, layer);
+
+ return ResultCode.Success;
+ }
+ }
- // If the layer was removed and the current in use, we need to change the current layer in use.
- if (removed && RenderLayerId == layerId)
+ public ResultCode DestroyManagedLayer(long layerId)
+ {
+ lock (Lock)
+ {
+ Layer layer = GetLayerByIdLocked(layerId);
+
+ if (layer == null)
{
- // If no layer is availaible, reset to default value.
- if (_layers.Count == 0)
- {
- SetRenderLayer(0);
- }
- else
- {
- SetRenderLayer(_layers.Last().Key);
- }
+ Logger.Error?.Print(LogClass.SurfaceFlinger, $"Failed to destroy managed layer {layerId} (not found)");
+
+ return ResultCode.InvalidValue;
+ }
+
+ if (layer.State != LayerState.ManagedClosed && layer.State != LayerState.ManagedOpened)
+ {
+ Logger.Error?.Print(LogClass.SurfaceFlinger, $"Failed to destroy managed layer {layerId} (permission denied)");
+
+ return ResultCode.PermissionDenied;
+ }
+
+ HOSBinderDriverServer.UnregisterBinderObject(layer.ProducerBinderId);
+
+ if (_layers.Remove(layerId) && layer.State == LayerState.ManagedOpened)
+ {
+ CloseLayer(layerId, layer);
+ }
+
+ return ResultCode.Success;
+ }
+ }
+
+ public ResultCode DestroyStrayLayer(long layerId)
+ {
+ lock (Lock)
+ {
+ Layer layer = GetLayerByIdLocked(layerId);
+
+ if (layer == null)
+ {
+ Logger.Error?.Print(LogClass.SurfaceFlinger, $"Failed to destroy stray layer {layerId} (not found)");
+
+ return ResultCode.InvalidValue;
}
- return removed;
+ if (layer.State != LayerState.Stray)
+ {
+ Logger.Error?.Print(LogClass.SurfaceFlinger, $"Failed to destroy stray layer {layerId} (permission denied)");
+
+ return ResultCode.PermissionDenied;
+ }
+
+ HOSBinderDriverServer.UnregisterBinderObject(layer.ProducerBinderId);
+
+ if (_layers.Remove(layerId))
+ {
+ CloseLayer(layerId, layer);
+ }
+
+ return ResultCode.Success;
+ }
+ }
+
+ 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;
}
}