Implement BGRA texture support (#1418)
* Implement BGRA texture support * Missing AppendLine * Remove empty lines * Address PR feedback
This commit is contained in:
parent
2678bf0010
commit
8dbcae1ff8
14 changed files with 232 additions and 61 deletions
|
@ -8,7 +8,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
|||
{
|
||||
public int Handle { get; protected set; }
|
||||
|
||||
protected TextureCreateInfo Info { get; }
|
||||
public TextureCreateInfo Info { get; }
|
||||
|
||||
public int Width { get; }
|
||||
public int Height { get; }
|
||||
|
|
|
@ -11,6 +11,9 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
|||
private int _srcFramebuffer;
|
||||
private int _dstFramebuffer;
|
||||
|
||||
private int _copyPboHandle;
|
||||
private int _copyPboSize;
|
||||
|
||||
public TextureCopy(Renderer renderer)
|
||||
{
|
||||
_renderer = renderer;
|
||||
|
@ -23,12 +26,14 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
|||
Extents2D dstRegion,
|
||||
bool linearFilter)
|
||||
{
|
||||
TextureView srcConverted = src.Format.IsBgra8() != dst.Format.IsBgra8() ? BgraSwap(src) : src;
|
||||
|
||||
(int oldDrawFramebufferHandle, int oldReadFramebufferHandle) = ((Pipeline)_renderer.Pipeline).GetBoundFramebuffers();
|
||||
|
||||
GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, GetSrcFramebufferLazy());
|
||||
GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, GetDstFramebufferLazy());
|
||||
|
||||
Attach(FramebufferTarget.ReadFramebuffer, src.Format, src.Handle);
|
||||
Attach(FramebufferTarget.ReadFramebuffer, src.Format, srcConverted.Handle);
|
||||
Attach(FramebufferTarget.DrawFramebuffer, dst.Format, dst.Handle);
|
||||
|
||||
ClearBufferMask mask = GetMask(src.Format);
|
||||
|
@ -68,6 +73,11 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
|||
|
||||
((Pipeline)_renderer.Pipeline).RestoreScissor0Enable();
|
||||
((Pipeline)_renderer.Pipeline).RestoreRasterizerDiscard();
|
||||
|
||||
if (srcConverted != src)
|
||||
{
|
||||
srcConverted.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
private static void Attach(FramebufferTarget target, Format format, int handle)
|
||||
|
@ -117,6 +127,52 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
|||
format == Format.D32Float;
|
||||
}
|
||||
|
||||
public TextureView BgraSwap(TextureView from)
|
||||
{
|
||||
TextureView to = (TextureView)_renderer.CreateTexture(from.Info, 1f);
|
||||
|
||||
EnsurePbo(from);
|
||||
|
||||
GL.BindBuffer(BufferTarget.PixelPackBuffer, _copyPboHandle);
|
||||
|
||||
from.WriteToPbo(0, forceBgra: true);
|
||||
|
||||
GL.BindBuffer(BufferTarget.PixelPackBuffer, 0);
|
||||
GL.BindBuffer(BufferTarget.PixelUnpackBuffer, _copyPboHandle);
|
||||
|
||||
to.ReadFromPbo(0, _copyPboSize);
|
||||
|
||||
GL.BindBuffer(BufferTarget.PixelUnpackBuffer, 0);
|
||||
|
||||
return to;
|
||||
}
|
||||
|
||||
private void EnsurePbo(TextureView view)
|
||||
{
|
||||
int requiredSize = 0;
|
||||
|
||||
for (int level = 0; level < view.Info.Levels; level++)
|
||||
{
|
||||
requiredSize += view.Info.GetMipSize(level);
|
||||
}
|
||||
|
||||
if (_copyPboSize < requiredSize && _copyPboHandle != 0)
|
||||
{
|
||||
GL.DeleteBuffer(_copyPboHandle);
|
||||
|
||||
_copyPboHandle = 0;
|
||||
}
|
||||
|
||||
if (_copyPboHandle == 0)
|
||||
{
|
||||
_copyPboHandle = GL.GenBuffer();
|
||||
_copyPboSize = requiredSize;
|
||||
|
||||
GL.BindBuffer(BufferTarget.PixelPackBuffer, _copyPboHandle);
|
||||
GL.BufferData(BufferTarget.PixelPackBuffer, requiredSize, IntPtr.Zero, BufferUsageHint.DynamicCopy);
|
||||
}
|
||||
}
|
||||
|
||||
private int GetSrcFramebufferLazy()
|
||||
{
|
||||
if (_srcFramebuffer == 0)
|
||||
|
@ -152,6 +208,13 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
|||
|
||||
_dstFramebuffer = 0;
|
||||
}
|
||||
|
||||
if (_copyPboHandle != 0)
|
||||
{
|
||||
GL.DeleteBuffer(_copyPboHandle);
|
||||
|
||||
_copyPboHandle = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -72,6 +72,15 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
|||
(int)Info.SwizzleA.Convert()
|
||||
};
|
||||
|
||||
if (Info.Format.IsBgra8())
|
||||
{
|
||||
// Swap B <-> R for BGRA formats, as OpenGL has no support for them
|
||||
// and we need to manually swap the components on read/write on the GPU.
|
||||
int temp = swizzleRgba[0];
|
||||
swizzleRgba[0] = swizzleRgba[2];
|
||||
swizzleRgba[2] = temp;
|
||||
}
|
||||
|
||||
GL.TexParameter(target, TextureParameterName.TextureSwizzleRgba, swizzleRgba);
|
||||
|
||||
int maxLevel = Info.Levels - 1;
|
||||
|
@ -189,7 +198,12 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
|||
return data;
|
||||
}
|
||||
|
||||
private void WriteTo(IntPtr ptr)
|
||||
public void WriteToPbo(int offset, bool forceBgra)
|
||||
{
|
||||
WriteTo(IntPtr.Zero + offset, forceBgra);
|
||||
}
|
||||
|
||||
private void WriteTo(IntPtr data, bool forceBgra = false)
|
||||
{
|
||||
TextureTarget target = Target.Convert();
|
||||
|
||||
|
@ -197,6 +211,14 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
|||
|
||||
FormatInfo format = FormatTable.GetFormatInfo(Info.Format);
|
||||
|
||||
PixelFormat pixelFormat = format.PixelFormat;
|
||||
PixelType pixelType = format.PixelType;
|
||||
|
||||
if (forceBgra)
|
||||
{
|
||||
pixelFormat = PixelFormat.Bgra;
|
||||
}
|
||||
|
||||
int faces = 1;
|
||||
|
||||
if (target == TextureTarget.TextureCubeMap)
|
||||
|
@ -214,20 +236,15 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
|||
|
||||
if (format.IsCompressed)
|
||||
{
|
||||
GL.GetCompressedTexImage(target + face, level, ptr + faceOffset);
|
||||
GL.GetCompressedTexImage(target + face, level, data + faceOffset);
|
||||
}
|
||||
else
|
||||
{
|
||||
GL.GetTexImage(
|
||||
target + face,
|
||||
level,
|
||||
format.PixelFormat,
|
||||
format.PixelType,
|
||||
ptr + faceOffset);
|
||||
GL.GetTexImage(target + face, level, pixelFormat, pixelType, data + faceOffset);
|
||||
}
|
||||
}
|
||||
|
||||
ptr += Info.GetMipSize(level);
|
||||
data += Info.GetMipSize(level);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -237,12 +254,17 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
|||
{
|
||||
fixed (byte* ptr = data)
|
||||
{
|
||||
SetData((IntPtr)ptr, data.Length);
|
||||
ReadFrom((IntPtr)ptr, data.Length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void SetData(IntPtr data, int size)
|
||||
public void ReadFromPbo(int offset, int size)
|
||||
{
|
||||
ReadFrom(IntPtr.Zero + offset, size);
|
||||
}
|
||||
|
||||
private void ReadFrom(IntPtr data, int size)
|
||||
{
|
||||
TextureTarget target = Target.Convert();
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue