mirror of
https://github.com/ryujinx-mirror/ryujinx.git
synced 2024-11-22 18:15:11 +00:00
Fix OpenGL issues with RTSS overlays and OBS Game Capture (#3217)
OpenGL game overlays and hooks tend to make a lot of assumptions about how games present frames to the screen, since presentation in OpenGL kind of sucks and they would like to have info such as the size of the screen, or if the contents are SRGB rather than linear. There are two ways of getting this. OBS hooks swap buffers to get a frame for video capture, but it actually checks the bound framebuffer at the time. I made sure that this matches the output framebuffer (the window) so that the output matches the size. RTSS checks the viewport size by default, but this was actually set to the last used viewport by the game, causing the OSD to fly all across the screen depending on how it was used (or res scale). The viewport is now manually set to match the output framebuffer size. In the case of RTSS, it also loads its resources by destructively setting a pixel pack parameter without regard to what it was set to by the guest application. OpenGL state can be set for a long period of time and is not expected to be set before each call to a method, so randomly changing it isn't great practice. To fix this, I've added a line to set the pixel unpack alignment back to 4 after presentation, which should cover RTSS loading its incredibly ugly font. - RTSS and overlays that use it should no longer cause certain textures to load incorrectly. (mario kart 8, pokemon legends arceus) - OBS Game Capture should no longer crop the game output incorrectly, flicker randomly, or capture with incorrect gamma. This doesn't fix issues with how RTSS reports our frame timings.
This commit is contained in:
parent
b45d30acf8
commit
d461d4f68b
2 changed files with 23 additions and 3 deletions
|
@ -1478,6 +1478,11 @@ namespace Ryujinx.Graphics.OpenGL
|
||||||
_currentComponentMasks |= componentMaskAtIndex;
|
_currentComponentMasks |= componentMaskAtIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void RestoreClipControl()
|
||||||
|
{
|
||||||
|
GL.ClipControl(_clipOrigin, _clipDepthMode);
|
||||||
|
}
|
||||||
|
|
||||||
public void RestoreScissor0Enable()
|
public void RestoreScissor0Enable()
|
||||||
{
|
{
|
||||||
if ((_scissorEnables & 1u) != 0)
|
if ((_scissorEnables & 1u) != 0)
|
||||||
|
@ -1494,6 +1499,11 @@ namespace Ryujinx.Graphics.OpenGL
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void RestoreViewport0()
|
||||||
|
{
|
||||||
|
GL.ViewportArray(0, 1, _viewportArray);
|
||||||
|
}
|
||||||
|
|
||||||
public bool TryHostConditionalRendering(ICounterEvent value, ulong compare, bool isEqual)
|
public bool TryHostConditionalRendering(ICounterEvent value, ulong compare, bool isEqual)
|
||||||
{
|
{
|
||||||
if (value is CounterQueueEvent)
|
if (value is CounterQueueEvent)
|
||||||
|
|
|
@ -27,11 +27,12 @@ namespace Ryujinx.Graphics.OpenGL
|
||||||
{
|
{
|
||||||
GL.Disable(EnableCap.FramebufferSrgb);
|
GL.Disable(EnableCap.FramebufferSrgb);
|
||||||
|
|
||||||
CopyTextureToFrameBufferRGB(0, GetCopyFramebufferHandleLazy(), (TextureView)texture, crop);
|
CopyTextureToFrameBufferRGB(0, GetCopyFramebufferHandleLazy(), (TextureView)texture, crop, swapBuffersCallback);
|
||||||
|
|
||||||
GL.Enable(EnableCap.FramebufferSrgb);
|
GL.Enable(EnableCap.FramebufferSrgb);
|
||||||
|
|
||||||
swapBuffersCallback();
|
// Restore unpack alignment to 4, as performance overlays such as RTSS may change this to load their resources.
|
||||||
|
GL.PixelStore(PixelStoreParameter.UnpackAlignment, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetSize(int width, int height)
|
public void SetSize(int width, int height)
|
||||||
|
@ -40,7 +41,7 @@ namespace Ryujinx.Graphics.OpenGL
|
||||||
_height = height;
|
_height = height;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CopyTextureToFrameBufferRGB(int drawFramebuffer, int readFramebuffer, TextureView view, ImageCrop crop)
|
private void CopyTextureToFrameBufferRGB(int drawFramebuffer, int readFramebuffer, TextureView view, ImageCrop crop, Action swapBuffersCallback)
|
||||||
{
|
{
|
||||||
(int oldDrawFramebufferHandle, int oldReadFramebufferHandle) = ((Pipeline)_renderer.Pipeline).GetBoundFramebuffers();
|
(int oldDrawFramebufferHandle, int oldReadFramebufferHandle) = ((Pipeline)_renderer.Pipeline).GetBoundFramebuffers();
|
||||||
|
|
||||||
|
@ -139,11 +140,20 @@ namespace Ryujinx.Graphics.OpenGL
|
||||||
((Pipeline)_renderer.Pipeline).RestoreComponentMask(i);
|
((Pipeline)_renderer.Pipeline).RestoreComponentMask(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set clip control, viewport and the framebuffer to the output to placate overlays and OBS capture.
|
||||||
|
GL.ClipControl(ClipOrigin.LowerLeft, ClipDepthMode.NegativeOneToOne);
|
||||||
|
GL.Viewport(0, 0, _width, _height);
|
||||||
|
GL.BindFramebuffer(FramebufferTarget.Framebuffer, drawFramebuffer);
|
||||||
|
|
||||||
|
swapBuffersCallback();
|
||||||
|
|
||||||
GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, oldReadFramebufferHandle);
|
GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, oldReadFramebufferHandle);
|
||||||
GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, oldDrawFramebufferHandle);
|
GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, oldDrawFramebufferHandle);
|
||||||
|
|
||||||
|
((Pipeline)_renderer.Pipeline).RestoreClipControl();
|
||||||
((Pipeline)_renderer.Pipeline).RestoreScissor0Enable();
|
((Pipeline)_renderer.Pipeline).RestoreScissor0Enable();
|
||||||
((Pipeline)_renderer.Pipeline).RestoreRasterizerDiscard();
|
((Pipeline)_renderer.Pipeline).RestoreRasterizerDiscard();
|
||||||
|
((Pipeline)_renderer.Pipeline).RestoreViewport0();
|
||||||
|
|
||||||
if (viewConverted != view)
|
if (viewConverted != view)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue