1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
using Ryujinx.Graphics.GAL;
using OpenTK.Graphics.OpenGL;
namespace Ryujinx.Graphics.OpenGL
{
class TextureCopy
{
private int _srcFramebuffer;
private int _dstFramebuffer;
public void Copy(
TextureView src,
TextureView dst,
Extents2D srcRegion,
Extents2D dstRegion,
bool linearFilter)
{
GL.Disable(EnableCap.FramebufferSrgb);
int oldReadFramebufferHandle = GL.GetInteger(GetPName.ReadFramebufferBinding);
int oldDrawFramebufferHandle = GL.GetInteger(GetPName.DrawFramebufferBinding);
GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, GetSrcFramebufferLazy());
GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, GetDstFramebufferLazy());
Attach(FramebufferTarget.ReadFramebuffer, src.Format, src.Handle);
Attach(FramebufferTarget.DrawFramebuffer, dst.Format, dst.Handle);
ClearBufferMask mask = GetMask(src.Format);
BlitFramebufferFilter filter = linearFilter
? BlitFramebufferFilter.Linear
: BlitFramebufferFilter.Nearest;
GL.ReadBuffer(ReadBufferMode.ColorAttachment0);
GL.DrawBuffer(DrawBufferMode.ColorAttachment0);
GL.BlitFramebuffer(
srcRegion.X1,
srcRegion.Y1,
srcRegion.X2,
srcRegion.Y2,
dstRegion.X1,
dstRegion.Y1,
dstRegion.X2,
dstRegion.Y2,
mask,
filter);
GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, oldReadFramebufferHandle);
GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, oldDrawFramebufferHandle);
GL.Enable(EnableCap.FramebufferSrgb);
}
private static void Detach(FramebufferTarget target, Format format)
{
Attach(target, format, 0);
}
private static void Attach(FramebufferTarget target, Format format, int handle)
{
if (format == Format.D24UnormS8Uint || format == Format.D32FloatS8Uint)
{
GL.FramebufferTexture(target, FramebufferAttachment.DepthStencilAttachment, handle, 0);
}
else if (IsDepthOnly(format))
{
GL.FramebufferTexture(target, FramebufferAttachment.DepthAttachment, handle, 0);
}
else if (format == Format.S8Uint)
{
GL.FramebufferTexture(target, FramebufferAttachment.StencilAttachment, handle, 0);
}
else
{
GL.FramebufferTexture(target, FramebufferAttachment.ColorAttachment0, handle, 0);
}
}
private static ClearBufferMask GetMask(Format format)
{
if (format == Format.D24UnormS8Uint || format == Format.D32FloatS8Uint)
{
return ClearBufferMask.DepthBufferBit | ClearBufferMask.StencilBufferBit;
}
else if (IsDepthOnly(format))
{
return ClearBufferMask.DepthBufferBit;
}
else if (format == Format.S8Uint)
{
return ClearBufferMask.StencilBufferBit;
}
else
{
return ClearBufferMask.ColorBufferBit;
}
}
private static bool IsDepthOnly(Format format)
{
return format == Format.D16Unorm ||
format == Format.D24X8Unorm ||
format == Format.D32Float;
}
private int GetSrcFramebufferLazy()
{
if (_srcFramebuffer == 0)
{
_srcFramebuffer = GL.GenFramebuffer();
}
return _srcFramebuffer;
}
private int GetDstFramebufferLazy()
{
if (_dstFramebuffer == 0)
{
_dstFramebuffer = GL.GenFramebuffer();
}
return _dstFramebuffer;
}
}
}
|