173 lines
4.9 KiB
C#
173 lines
4.9 KiB
C#
using OpenTK.Graphics.OpenGL;
|
|
using Ryujinx.Graphics.GAL;
|
|
using Ryujinx.Graphics.OpenGL.Image;
|
|
using System;
|
|
using System.Runtime.CompilerServices;
|
|
|
|
namespace Ryujinx.Graphics.OpenGL
|
|
{
|
|
class Framebuffer : IDisposable
|
|
{
|
|
public int Handle { get; private set; }
|
|
|
|
private FramebufferAttachment _lastDsAttachment;
|
|
|
|
private readonly TextureView[] _colors;
|
|
|
|
private int _colorsCount;
|
|
private bool _dualSourceBlend;
|
|
|
|
public Framebuffer()
|
|
{
|
|
Handle = GL.GenFramebuffer();
|
|
|
|
_colors = new TextureView[8];
|
|
}
|
|
|
|
public int Bind()
|
|
{
|
|
GL.BindFramebuffer(FramebufferTarget.Framebuffer, Handle);
|
|
return Handle;
|
|
}
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public void AttachColor(int index, TextureView color)
|
|
{
|
|
if (_colors[index] == color)
|
|
{
|
|
return;
|
|
}
|
|
|
|
FramebufferAttachment attachment = FramebufferAttachment.ColorAttachment0 + index;
|
|
|
|
if (HwCapabilities.Vendor == HwCapabilities.GpuVendor.Amd ||
|
|
HwCapabilities.Vendor == HwCapabilities.GpuVendor.Intel)
|
|
{
|
|
GL.FramebufferTexture(FramebufferTarget.Framebuffer, attachment, color?.GetIncompatibleFormatViewHandle() ?? 0, 0);
|
|
}
|
|
else
|
|
{
|
|
GL.FramebufferTexture(FramebufferTarget.Framebuffer, attachment, color?.Handle ?? 0, 0);
|
|
}
|
|
|
|
_colors[index] = color;
|
|
}
|
|
|
|
public void AttachDepthStencil(TextureView depthStencil)
|
|
{
|
|
// Detach the last depth/stencil buffer if there is any.
|
|
if (_lastDsAttachment != 0)
|
|
{
|
|
GL.FramebufferTexture(FramebufferTarget.Framebuffer, _lastDsAttachment, 0, 0);
|
|
}
|
|
|
|
if (depthStencil != null)
|
|
{
|
|
FramebufferAttachment attachment;
|
|
|
|
if (IsPackedDepthStencilFormat(depthStencil.Format))
|
|
{
|
|
attachment = FramebufferAttachment.DepthStencilAttachment;
|
|
}
|
|
else if (IsDepthOnlyFormat(depthStencil.Format))
|
|
{
|
|
attachment = FramebufferAttachment.DepthAttachment;
|
|
}
|
|
else
|
|
{
|
|
attachment = FramebufferAttachment.StencilAttachment;
|
|
}
|
|
|
|
GL.FramebufferTexture(
|
|
FramebufferTarget.Framebuffer,
|
|
attachment,
|
|
depthStencil.Handle,
|
|
0);
|
|
|
|
_lastDsAttachment = attachment;
|
|
}
|
|
else
|
|
{
|
|
_lastDsAttachment = 0;
|
|
}
|
|
}
|
|
|
|
public void SignalModified()
|
|
{
|
|
if (HwCapabilities.Vendor == HwCapabilities.GpuVendor.Amd ||
|
|
HwCapabilities.Vendor == HwCapabilities.GpuVendor.Intel)
|
|
{
|
|
for (int i = 0; i < 8; i++)
|
|
{
|
|
if (_colors[i] != null)
|
|
{
|
|
_colors[i].SignalModified();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public void SetDualSourceBlend(bool enable)
|
|
{
|
|
bool oldEnable = _dualSourceBlend;
|
|
|
|
_dualSourceBlend = enable;
|
|
|
|
// When dual source blend is used,
|
|
// we can only have one draw buffer.
|
|
if (enable)
|
|
{
|
|
GL.DrawBuffer(DrawBufferMode.ColorAttachment0);
|
|
}
|
|
else if (oldEnable)
|
|
{
|
|
SetDrawBuffersImpl(_colorsCount);
|
|
}
|
|
}
|
|
|
|
public void SetDrawBuffers(int colorsCount)
|
|
{
|
|
if (_colorsCount != colorsCount && !_dualSourceBlend)
|
|
{
|
|
SetDrawBuffersImpl(colorsCount);
|
|
}
|
|
|
|
_colorsCount = colorsCount;
|
|
}
|
|
|
|
private void SetDrawBuffersImpl(int colorsCount)
|
|
{
|
|
DrawBuffersEnum[] drawBuffers = new DrawBuffersEnum[colorsCount];
|
|
|
|
for (int index = 0; index < colorsCount; index++)
|
|
{
|
|
drawBuffers[index] = DrawBuffersEnum.ColorAttachment0 + index;
|
|
}
|
|
|
|
GL.DrawBuffers(colorsCount, drawBuffers);
|
|
}
|
|
|
|
private static bool IsPackedDepthStencilFormat(Format format)
|
|
{
|
|
return format == Format.D24UnormS8Uint ||
|
|
format == Format.D32FloatS8Uint;
|
|
}
|
|
|
|
private static bool IsDepthOnlyFormat(Format format)
|
|
{
|
|
return format == Format.D16Unorm ||
|
|
format == Format.D24X8Unorm ||
|
|
format == Format.D32Float;
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
if (Handle != 0)
|
|
{
|
|
GL.DeleteFramebuffer(Handle);
|
|
|
|
Handle = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|