Surface Flinger: Fix an oversight when closing a layer (#2192)
* Surface Flinger: Fix an oversight when closing a layer As the title say. I also took the liberty of changing the logic on how we select the current layer being rendered to make it more explicit when opening and creating layers. NOTE: Found by Ac_k. * check for RenderLayerId and not the dictionary size This fix a possible race condition between the time you create a layer and set the one currently used for rendering
This commit is contained in:
parent
5cb83293bc
commit
73881fad19
4 changed files with 38 additions and 9 deletions
|
@ -218,6 +218,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys
|
||||||
public ResultCode CreateManagedDisplayLayer(ServiceCtx context)
|
public ResultCode CreateManagedDisplayLayer(ServiceCtx context)
|
||||||
{
|
{
|
||||||
context.Device.System.SurfaceFlinger.CreateLayer(_pid, out long layerId);
|
context.Device.System.SurfaceFlinger.CreateLayer(_pid, out long layerId);
|
||||||
|
context.Device.System.SurfaceFlinger.SetRenderLayer(layerId);
|
||||||
|
|
||||||
context.ResponseData.Write(layerId);
|
context.ResponseData.Write(layerId);
|
||||||
|
|
||||||
|
@ -228,9 +229,9 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys
|
||||||
// CreateManagedDisplaySeparableLayer() -> (u64, u64)
|
// CreateManagedDisplaySeparableLayer() -> (u64, u64)
|
||||||
public ResultCode CreateManagedDisplaySeparableLayer(ServiceCtx context)
|
public ResultCode CreateManagedDisplaySeparableLayer(ServiceCtx context)
|
||||||
{
|
{
|
||||||
// NOTE: first create the recoding layer and then the display one because right now Surface Flinger only use the last id.
|
|
||||||
context.Device.System.SurfaceFlinger.CreateLayer(_pid, out long recordingLayerId);
|
|
||||||
context.Device.System.SurfaceFlinger.CreateLayer(_pid, out long displayLayerId);
|
context.Device.System.SurfaceFlinger.CreateLayer(_pid, out long displayLayerId);
|
||||||
|
context.Device.System.SurfaceFlinger.CreateLayer(_pid, out long recordingLayerId);
|
||||||
|
context.Device.System.SurfaceFlinger.SetRenderLayer(displayLayerId);
|
||||||
|
|
||||||
context.ResponseData.Write(displayLayerId);
|
context.ResponseData.Write(displayLayerId);
|
||||||
context.ResponseData.Write(recordingLayerId);
|
context.ResponseData.Write(recordingLayerId);
|
||||||
|
|
|
@ -7,6 +7,7 @@ using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvMap;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
|
namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
|
||||||
|
@ -36,7 +37,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
|
||||||
|
|
||||||
private readonly object Lock = new object();
|
private readonly object Lock = new object();
|
||||||
|
|
||||||
public long LastId { get; private set; }
|
public long RenderLayerId { get; private set; }
|
||||||
|
|
||||||
private class Layer
|
private class Layer
|
||||||
{
|
{
|
||||||
|
@ -57,7 +58,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
|
||||||
{
|
{
|
||||||
_device = device;
|
_device = device;
|
||||||
_layers = new Dictionary<long, Layer>();
|
_layers = new Dictionary<long, Layer>();
|
||||||
LastId = 0;
|
RenderLayerId = 0;
|
||||||
|
|
||||||
_composerThread = new Thread(HandleComposition)
|
_composerThread = new Thread(HandleComposition)
|
||||||
{
|
{
|
||||||
|
@ -150,8 +151,6 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
|
||||||
Core = core,
|
Core = core,
|
||||||
Owner = pid
|
Owner = pid
|
||||||
});
|
});
|
||||||
|
|
||||||
LastId = layerId;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -166,7 +165,31 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
|
||||||
HOSBinderDriverServer.UnregisterBinderObject(layer.ProducerBinderId);
|
HOSBinderDriverServer.UnregisterBinderObject(layer.ProducerBinderId);
|
||||||
}
|
}
|
||||||
|
|
||||||
return _layers.Remove(layerId);
|
bool removed = _layers.Remove(layerId);
|
||||||
|
|
||||||
|
// If the layer was removed and the current in use, we need to change the current layer in use.
|
||||||
|
if (removed && RenderLayerId == layerId)
|
||||||
|
{
|
||||||
|
// If no layer is availaible, reset to default value.
|
||||||
|
if (_layers.Count == 0)
|
||||||
|
{
|
||||||
|
SetRenderLayer(0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SetRenderLayer(_layers.Last().Key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return removed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetRenderLayer(long layerId)
|
||||||
|
{
|
||||||
|
lock (Lock)
|
||||||
|
{
|
||||||
|
RenderLayerId = layerId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -263,12 +286,12 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
|
||||||
lock (Lock)
|
lock (Lock)
|
||||||
{
|
{
|
||||||
// TODO: support multilayers (& multidisplay ?)
|
// TODO: support multilayers (& multidisplay ?)
|
||||||
if (_layers.Count == 0)
|
if (RenderLayerId == 0)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Layer layer = GetLayerByIdLocked(LastId);
|
Layer layer = GetLayerByIdLocked(RenderLayerId);
|
||||||
|
|
||||||
Status acquireStatus = layer.Consumer.AcquireBuffer(out BufferItem item, 0);
|
Status acquireStatus = layer.Consumer.AcquireBuffer(out BufferItem item, 0);
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@ namespace Ryujinx.HLE.HOS.Services.Vi.RootService.ApplicationDisplayService
|
||||||
long pid = context.Device.System.AppletState.AppletResourceUserIds.GetData<long>((int)appletResourceUserId);
|
long pid = context.Device.System.AppletState.AppletResourceUserIds.GetData<long>((int)appletResourceUserId);
|
||||||
|
|
||||||
context.Device.System.SurfaceFlinger.CreateLayer(pid, out long layerId);
|
context.Device.System.SurfaceFlinger.CreateLayer(pid, out long layerId);
|
||||||
|
context.Device.System.SurfaceFlinger.SetRenderLayer(layerId);
|
||||||
|
|
||||||
context.ResponseData.Write(layerId);
|
context.ResponseData.Write(layerId);
|
||||||
|
|
||||||
|
|
|
@ -126,6 +126,8 @@ namespace Ryujinx.HLE.HOS.Services.Vi.RootService
|
||||||
|
|
||||||
IBinder producer = context.Device.System.SurfaceFlinger.OpenLayer(context.Request.HandleDesc.PId, layerId);
|
IBinder producer = context.Device.System.SurfaceFlinger.OpenLayer(context.Request.HandleDesc.PId, layerId);
|
||||||
|
|
||||||
|
context.Device.System.SurfaceFlinger.SetRenderLayer(layerId);
|
||||||
|
|
||||||
Parcel parcel = new Parcel(0x28, 0x4);
|
Parcel parcel = new Parcel(0x28, 0x4);
|
||||||
|
|
||||||
parcel.WriteObject(producer, "dispdrv\0");
|
parcel.WriteObject(producer, "dispdrv\0");
|
||||||
|
@ -164,6 +166,8 @@ namespace Ryujinx.HLE.HOS.Services.Vi.RootService
|
||||||
|
|
||||||
IBinder producer = context.Device.System.SurfaceFlinger.CreateLayer(0, out long layerId);
|
IBinder producer = context.Device.System.SurfaceFlinger.CreateLayer(0, out long layerId);
|
||||||
|
|
||||||
|
context.Device.System.SurfaceFlinger.SetRenderLayer(layerId);
|
||||||
|
|
||||||
Parcel parcel = new Parcel(0x28, 0x4);
|
Parcel parcel = new Parcel(0x28, 0x4);
|
||||||
|
|
||||||
parcel.WriteObject(producer, "dispdrv\0");
|
parcel.WriteObject(producer, "dispdrv\0");
|
||||||
|
|
Loading…
Reference in a new issue