Allow copy between frame buffers

This commit is contained in:
gdkchan 2018-07-09 15:23:38 -03:00
parent 095db47e13
commit fdb9d53e00
3 changed files with 70 additions and 29 deletions

View file

@ -22,6 +22,18 @@ namespace Ryujinx.Graphics.Gal
void Render(); void Render();
void Copy(
long SrcKey,
long DstKey,
int SrcX0,
int SrcY0,
int SrcX1,
int SrcY1,
int DstX0,
int DstY0,
int DstX1,
int DstY1);
void GetBufferData(long Key, Action<byte[]> Callback); void GetBufferData(long Key, Action<byte[]> Callback);
} }
} }

View file

@ -304,6 +304,34 @@ namespace Ryujinx.Graphics.Gal.OpenGL
} }
} }
public void Copy(
long SrcKey,
long DstKey,
int SrcX0,
int SrcY0,
int SrcX1,
int SrcY1,
int DstX0,
int DstY0,
int DstX1,
int DstY1)
{
if (Fbs.TryGetValue(SrcKey, out FrameBuffer SrcFb) &&
Fbs.TryGetValue(DstKey, out FrameBuffer DstFb))
{
GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, SrcFb.Handle);
GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, DstFb.Handle);
GL.Clear(ClearBufferMask.ColorBufferBit);
GL.BlitFramebuffer(
SrcX0, SrcY0, SrcX1, SrcY1,
DstX0, DstY0, DstX1, DstY1,
ClearBufferMask.ColorBufferBit,
BlitFramebufferFilter.Linear);
}
}
public void GetBufferData(long Key, Action<byte[]> Callback) public void GetBufferData(long Key, Action<byte[]> Callback)
{ {
if (Fbs.TryGetValue(Key, out FrameBuffer Fb)) if (Fbs.TryGetValue(Key, out FrameBuffer Fb))

View file

@ -77,14 +77,16 @@ namespace Ryujinx.HLE.Gpu.Engines
int DstBlockHeight = 1 << ((DstBlkDim >> 4) & 0xf); int DstBlockHeight = 1 << ((DstBlkDim >> 4) & 0xf);
long Key = Vmm.GetPhysicalAddress(MakeInt64From2xInt32(NvGpuEngine2dReg.SrcAddress));
long SrcAddress = MakeInt64From2xInt32(NvGpuEngine2dReg.SrcAddress); long SrcAddress = MakeInt64From2xInt32(NvGpuEngine2dReg.SrcAddress);
long DstAddress = MakeInt64From2xInt32(NvGpuEngine2dReg.DstAddress); long DstAddress = MakeInt64From2xInt32(NvGpuEngine2dReg.DstAddress);
bool IsFbTexture = Gpu.Engine3d.IsFrameBufferPosition(Key); long SrcKey = Vmm.GetPhysicalAddress(SrcAddress);
long DstKey = Vmm.GetPhysicalAddress(DstAddress);
if (IsFbTexture && DstLinear) bool IsSrcFb = Gpu.Engine3d.IsFrameBufferPosition(SrcKey);
bool IsDstFb = Gpu.Engine3d.IsFrameBufferPosition(DstKey);
if (IsSrcFb && DstLinear)
{ {
DstSwizzle = TextureSwizzle.BlockLinear; DstSwizzle = TextureSwizzle.BlockLinear;
} }
@ -93,26 +95,40 @@ namespace Ryujinx.HLE.Gpu.Engines
DstAddress, DstAddress,
DstWidth, DstWidth,
DstHeight, DstHeight,
DstBlockHeight, DstPitch,
DstBlockHeight, DstBlockHeight,
DstSwizzle, DstSwizzle,
GalTextureFormat.A8B8G8R8); GalTextureFormat.A8B8G8R8);
if (IsFbTexture) if (IsSrcFb && IsDstFb)
{
//TODO: Change this when the correct frame buffer resolution is used.
//Currently, the frame buffer size is hardcoded to 1280x720.
DstWidth = 1280;
DstHeight = 720;
Gpu.Renderer.FrameBuffer.Copy(
SrcKey,
DstKey,
0,
0,
SrcWidth,
SrcHeight,
0,
0,
DstWidth,
DstHeight);
}
else if (IsSrcFb)
{ {
//TODO: Change this when the correct frame buffer resolution is used. //TODO: Change this when the correct frame buffer resolution is used.
//Currently, the frame buffer size is hardcoded to 1280x720. //Currently, the frame buffer size is hardcoded to 1280x720.
SrcWidth = 1280; SrcWidth = 1280;
SrcHeight = 720; SrcHeight = 720;
Gpu.Renderer.FrameBuffer.GetBufferData(Key, (byte[] Buffer) => Gpu.Renderer.FrameBuffer.GetBufferData(SrcKey, (byte[] Buffer) =>
{ {
CopyTexture( TextureWriter.Write(Vmm, DstTexture, Buffer, SrcWidth, SrcHeight);
Vmm,
DstTexture,
Buffer,
SrcWidth,
SrcHeight);
}); });
} }
else else
@ -121,25 +137,10 @@ namespace Ryujinx.HLE.Gpu.Engines
byte[] Buffer = Vmm.ReadBytes(SrcAddress, Size); byte[] Buffer = Vmm.ReadBytes(SrcAddress, Size);
CopyTexture( TextureWriter.Write(Vmm, DstTexture, Buffer, SrcWidth, SrcHeight);
Vmm,
DstTexture,
Buffer,
SrcWidth,
SrcHeight);
} }
} }
private void CopyTexture(
NvGpuVmm Vmm,
TextureInfo Texture,
byte[] Buffer,
int Width,
int Height)
{
TextureWriter.Write(Vmm, Texture, Buffer, Width, Height);
}
private long MakeInt64From2xInt32(NvGpuEngine2dReg Reg) private long MakeInt64From2xInt32(NvGpuEngine2dReg Reg)
{ {
return return