Allow texture copy between frame buffers
This commit is contained in:
parent
9069e17222
commit
efab5d7d06
3 changed files with 152 additions and 18 deletions
|
@ -22,6 +22,25 @@ namespace Ryujinx.Graphics.Gal
|
|||
|
||||
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 SetBufferData(
|
||||
long Key,
|
||||
int Width,
|
||||
int Height,
|
||||
GalTextureFormat Format,
|
||||
byte[] Buffer);
|
||||
}
|
||||
}
|
|
@ -306,6 +306,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)
|
||||
{
|
||||
if (Fbs.TryGetValue(Key, out FrameBuffer Fb))
|
||||
|
@ -331,6 +359,37 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
|||
}
|
||||
}
|
||||
|
||||
public void SetBufferData(
|
||||
long Key,
|
||||
int Width,
|
||||
int Height,
|
||||
GalTextureFormat Format,
|
||||
byte[] Buffer)
|
||||
{
|
||||
if (Fbs.TryGetValue(Key, out FrameBuffer Fb))
|
||||
{
|
||||
GL.BindTexture(TextureTarget.Texture2D, Fb.TexHandle);
|
||||
|
||||
const int Level = 0;
|
||||
const int Border = 0;
|
||||
|
||||
const PixelInternalFormat InternalFmt = PixelInternalFormat.Rgba;
|
||||
|
||||
(PixelFormat GlFormat, PixelType Type) = OGLEnumConverter.GetTextureFormat(Format);
|
||||
|
||||
GL.TexImage2D(
|
||||
TextureTarget.Texture2D,
|
||||
Level,
|
||||
InternalFmt,
|
||||
Width,
|
||||
Height,
|
||||
Border,
|
||||
GlFormat,
|
||||
Type,
|
||||
Buffer);
|
||||
}
|
||||
}
|
||||
|
||||
private void EnsureInitialized()
|
||||
{
|
||||
if (!IsInitialized)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
using Ryujinx.Graphics.Gal;
|
||||
using Ryujinx.HLE.Gpu.Memory;
|
||||
using Ryujinx.HLE.Gpu.Texture;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ryujinx.HLE.Gpu.Engines
|
||||
|
@ -93,36 +94,91 @@ namespace Ryujinx.HLE.Gpu.Engines
|
|||
bool IsSrcFb = Gpu.Engine3d.IsFrameBufferPosition(SrcKey);
|
||||
bool IsDstFb = Gpu.Engine3d.IsFrameBufferPosition(DstKey);
|
||||
|
||||
TextureInfo SrcTexture = new TextureInfo(
|
||||
SrcAddress,
|
||||
SrcWidth,
|
||||
SrcHeight,
|
||||
SrcPitch,
|
||||
SrcBlockHeight, 1,
|
||||
SrcSwizzle,
|
||||
GalTextureFormat.A8B8G8R8);
|
||||
TextureInfo SrcTexture()
|
||||
{
|
||||
return new TextureInfo(
|
||||
SrcAddress,
|
||||
SrcWidth,
|
||||
SrcHeight,
|
||||
SrcPitch,
|
||||
SrcBlockHeight, 1,
|
||||
SrcSwizzle,
|
||||
GalTextureFormat.A8B8G8R8);
|
||||
}
|
||||
|
||||
TextureInfo DstTexture = new TextureInfo(
|
||||
DstAddress,
|
||||
DstWidth,
|
||||
DstHeight,
|
||||
DstPitch,
|
||||
DstBlockHeight, 1,
|
||||
DstSwizzle,
|
||||
GalTextureFormat.A8B8G8R8);
|
||||
TextureInfo DstTexture()
|
||||
{
|
||||
return new TextureInfo(
|
||||
DstAddress,
|
||||
DstWidth,
|
||||
DstHeight,
|
||||
DstPitch,
|
||||
DstBlockHeight, 1,
|
||||
DstSwizzle,
|
||||
GalTextureFormat.A8B8G8R8);
|
||||
}
|
||||
|
||||
//TODO: fb -> fb copies, tex -> fb copies, formats other than RGBA8,
|
||||
//make it throw for unimpl stuff (like the copy mode)...
|
||||
if (IsSrcFb && IsDstFb)
|
||||
{
|
||||
//Frame Buffer -> Frame Buffer copy.
|
||||
Gpu.Renderer.FrameBuffer.Copy(
|
||||
SrcKey,
|
||||
DstKey,
|
||||
0,
|
||||
0,
|
||||
SrcWidth,
|
||||
SrcHeight,
|
||||
0,
|
||||
0,
|
||||
DstWidth,
|
||||
DstHeight);
|
||||
}
|
||||
if (IsSrcFb)
|
||||
{
|
||||
//Frame Buffer -> Texture copy.
|
||||
Gpu.Renderer.FrameBuffer.GetBufferData(SrcKey, (byte[] Buffer) =>
|
||||
{
|
||||
TextureWriter.Write(Vmm, DstTexture, Buffer);
|
||||
TextureInfo Src = SrcTexture();
|
||||
TextureInfo Dst = DstTexture();
|
||||
|
||||
if (Src.Width != Dst.Width ||
|
||||
Src.Height != Dst.Height)
|
||||
{
|
||||
throw new NotImplementedException("Texture resizing is not supported");
|
||||
}
|
||||
|
||||
TextureWriter.Write(Vmm, Dst, Buffer);
|
||||
});
|
||||
}
|
||||
else if (IsDstFb)
|
||||
{
|
||||
//Texture -> Frame Buffer copy.
|
||||
const GalTextureFormat Format = GalTextureFormat.A8B8G8R8;
|
||||
|
||||
byte[] Buffer = TextureReader.Read(Vmm, SrcTexture());
|
||||
|
||||
Gpu.Renderer.FrameBuffer.SetBufferData(
|
||||
DstKey,
|
||||
DstWidth,
|
||||
DstHeight,
|
||||
Format,
|
||||
Buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
TextureWriter.Write(Vmm, DstTexture, TextureReader.Read(Vmm, SrcTexture));
|
||||
//Texture -> Texture copy.
|
||||
TextureInfo Src = SrcTexture();
|
||||
TextureInfo Dst = DstTexture();
|
||||
|
||||
if (Src.Width != Dst.Width ||
|
||||
Src.Height != Dst.Height)
|
||||
{
|
||||
throw new NotImplementedException("Texture resizing is not supported");
|
||||
}
|
||||
|
||||
TextureWriter.Write(Vmm, Dst, TextureReader.Read(Vmm, Src));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue