Support deswizzle of sparse tiled textures and some frame buffer fixes (#275)

* Attempt to support deswizzle of sparse tiled textures

* Use correct frame buffer and viewport sizes, started to clean up the copy engine

* Correct texture width alignment

* Use Scale/Translate registers to calculate viewport rect

* Allow texture copy between frame buffers
This commit is contained in:
gdkchan 2018-07-19 02:30:21 -03:00 committed by GitHub
parent 8b685b12f0
commit 60f2198a1e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 237 additions and 116 deletions

View file

@ -22,6 +22,25 @@ 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);
void SetBufferData(
long Key,
int Width,
int Height,
GalTextureFormat Format,
byte[] Buffer);
} }
} }

View file

@ -78,11 +78,6 @@ namespace Ryujinx.Graphics.Gal.OpenGL
public void Create(long Key, int Width, int Height) public void Create(long Key, int Width, int Height)
{ {
//TODO: We should either use the original frame buffer size,
//or just remove the Width/Height arguments.
Width = Window.Width;
Height = Window.Height;
if (Fbs.TryGetValue(Key, out FrameBuffer Fb)) if (Fbs.TryGetValue(Key, out FrameBuffer Fb))
{ {
if (Fb.Width != Width || if (Fb.Width != Width ||
@ -125,8 +120,6 @@ namespace Ryujinx.Graphics.Gal.OpenGL
GL.DrawBuffer(DrawBufferMode.ColorAttachment0); GL.DrawBuffer(DrawBufferMode.ColorAttachment0);
GL.Viewport(0, 0, Width, Height);
Fbs.Add(Key, Fb); Fbs.Add(Key, Fb);
} }
@ -230,7 +223,16 @@ namespace Ryujinx.Graphics.Gal.OpenGL
{ {
Viewport = new Rect(X, Y, Width, Height); Viewport = new Rect(X, Y, Width, Height);
//TODO SetViewport(Viewport);
}
private void SetViewport(Rect Viewport)
{
GL.Viewport(
Viewport.X,
Viewport.Y,
Viewport.Width,
Viewport.Height);
} }
public void Render() public void Render()
@ -300,7 +302,35 @@ namespace Ryujinx.Graphics.Gal.OpenGL
GL.Enable(EnableCap.Blend); GL.Enable(EnableCap.Blend);
} }
//GL.Viewport(0, 0, 1280, 720); SetViewport(Viewport);
}
}
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);
} }
} }
@ -329,13 +359,35 @@ namespace Ryujinx.Graphics.Gal.OpenGL
} }
} }
private void SetViewport(Rect Viewport) public void SetBufferData(
long Key,
int Width,
int Height,
GalTextureFormat Format,
byte[] Buffer)
{ {
GL.Viewport( if (Fbs.TryGetValue(Key, out FrameBuffer Fb))
Viewport.X, {
Viewport.Y, GL.BindTexture(TextureTarget.Texture2D, Fb.TexHandle);
Viewport.Width,
Viewport.Height); 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() private void EnsureInitialized()

View file

@ -1,6 +1,7 @@
using Ryujinx.Graphics.Gal; using Ryujinx.Graphics.Gal;
using Ryujinx.HLE.Gpu.Memory; using Ryujinx.HLE.Gpu.Memory;
using Ryujinx.HLE.Gpu.Texture; using Ryujinx.HLE.Gpu.Texture;
using System;
using System.Collections.Generic; using System.Collections.Generic;
namespace Ryujinx.HLE.Gpu.Engines namespace Ryujinx.HLE.Gpu.Engines
@ -64,6 +65,8 @@ namespace Ryujinx.HLE.Gpu.Engines
bool SrcLinear = ReadRegister(NvGpuEngine2dReg.SrcLinear) != 0; bool SrcLinear = ReadRegister(NvGpuEngine2dReg.SrcLinear) != 0;
int SrcWidth = ReadRegister(NvGpuEngine2dReg.SrcWidth); int SrcWidth = ReadRegister(NvGpuEngine2dReg.SrcWidth);
int SrcHeight = ReadRegister(NvGpuEngine2dReg.SrcHeight); int SrcHeight = ReadRegister(NvGpuEngine2dReg.SrcHeight);
int SrcPitch = ReadRegister(NvGpuEngine2dReg.SrcPitch);
int SrcBlkDim = ReadRegister(NvGpuEngine2dReg.SrcBlockDimensions);
bool DstLinear = ReadRegister(NvGpuEngine2dReg.DstLinear) != 0; bool DstLinear = ReadRegister(NvGpuEngine2dReg.DstLinear) != 0;
int DstWidth = ReadRegister(NvGpuEngine2dReg.DstWidth); int DstWidth = ReadRegister(NvGpuEngine2dReg.DstWidth);
@ -71,73 +74,112 @@ namespace Ryujinx.HLE.Gpu.Engines
int DstPitch = ReadRegister(NvGpuEngine2dReg.DstPitch); int DstPitch = ReadRegister(NvGpuEngine2dReg.DstPitch);
int DstBlkDim = ReadRegister(NvGpuEngine2dReg.DstBlockDimensions); int DstBlkDim = ReadRegister(NvGpuEngine2dReg.DstBlockDimensions);
TextureSwizzle SrcSwizzle = SrcLinear
? TextureSwizzle.Pitch
: TextureSwizzle.BlockLinear;
TextureSwizzle DstSwizzle = DstLinear TextureSwizzle DstSwizzle = DstLinear
? TextureSwizzle.Pitch ? TextureSwizzle.Pitch
: TextureSwizzle.BlockLinear; : TextureSwizzle.BlockLinear;
int SrcBlockHeight = 1 << ((SrcBlkDim >> 4) & 0xf);
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);
TextureInfo SrcTexture()
{ {
DstSwizzle = TextureSwizzle.BlockLinear; return new TextureInfo(
SrcAddress,
SrcWidth,
SrcHeight,
SrcPitch,
SrcBlockHeight, 1,
SrcSwizzle,
GalTextureFormat.A8B8G8R8);
} }
TextureInfo DstTexture = new TextureInfo( TextureInfo DstTexture()
{
return new TextureInfo(
DstAddress, DstAddress,
DstWidth, DstWidth,
DstHeight, DstHeight,
DstBlockHeight, DstPitch,
DstBlockHeight, DstBlockHeight, 1,
DstSwizzle, DstSwizzle,
GalTextureFormat.A8B8G8R8); GalTextureFormat.A8B8G8R8);
}
if (IsFbTexture) //TODO: fb -> fb copies, tex -> fb copies, formats other than RGBA8,
//make it throw for unimpl stuff (like the copy mode)...
if (IsSrcFb && IsDstFb)
{ {
//TODO: Change this when the correct frame buffer resolution is used. //Frame Buffer -> Frame Buffer copy.
//Currently, the frame buffer size is hardcoded to 1280x720. Gpu.Renderer.FrameBuffer.Copy(
SrcWidth = 1280; SrcKey,
SrcHeight = 720; DstKey,
0,
Gpu.Renderer.FrameBuffer.GetBufferData(Key, (byte[] Buffer) => 0,
{
CopyTexture(
Vmm,
DstTexture,
Buffer,
SrcWidth, SrcWidth,
SrcHeight); SrcHeight,
0,
0,
DstWidth,
DstHeight);
}
if (IsSrcFb)
{
//Frame Buffer -> Texture copy.
Gpu.Renderer.FrameBuffer.GetBufferData(SrcKey, (byte[] 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 else
{ {
long Size = SrcWidth * SrcHeight * 4; //Texture -> Texture copy.
TextureInfo Src = SrcTexture();
TextureInfo Dst = DstTexture();
byte[] Buffer = Vmm.ReadBytes(SrcAddress, Size); if (Src.Width != Dst.Width ||
Src.Height != Dst.Height)
CopyTexture(
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); throw new NotImplementedException("Texture resizing is not supported");
}
TextureWriter.Write(Vmm, Dst, TextureReader.Read(Vmm, Src));
}
} }
private long MakeInt64From2xInt32(NvGpuEngine2dReg Reg) private long MakeInt64From2xInt32(NvGpuEngine2dReg Reg)

View file

@ -132,10 +132,22 @@ namespace Ryujinx.HLE.Gpu.Engines
int Width = ReadRegister(NvGpuEngine3dReg.FrameBufferNWidth + FbIndex * 0x10); int Width = ReadRegister(NvGpuEngine3dReg.FrameBufferNWidth + FbIndex * 0x10);
int Height = ReadRegister(NvGpuEngine3dReg.FrameBufferNHeight + FbIndex * 0x10); int Height = ReadRegister(NvGpuEngine3dReg.FrameBufferNHeight + FbIndex * 0x10);
//Note: Using the Width/Height results seems to give incorrect results. float TX = ReadRegisterFloat(NvGpuEngine3dReg.ViewportNTranslateX + FbIndex * 4);
//Maybe the size of all frame buffers is hardcoded to screen size? This seems unlikely. float TY = ReadRegisterFloat(NvGpuEngine3dReg.ViewportNTranslateY + FbIndex * 4);
Gpu.Renderer.FrameBuffer.Create(Key, 1280, 720);
float SX = ReadRegisterFloat(NvGpuEngine3dReg.ViewportNScaleX + FbIndex * 4);
float SY = ReadRegisterFloat(NvGpuEngine3dReg.ViewportNScaleY + FbIndex * 4);
int VpX = (int)MathF.Max(0, TX - MathF.Abs(SX));
int VpY = (int)MathF.Max(0, TY - MathF.Abs(SY));
int VpW = (int)(TX + MathF.Abs(SX)) - VpX;
int VpH = (int)(TY + MathF.Abs(SY)) - VpY;
Gpu.Renderer.FrameBuffer.Create(Key, Width, Height);
Gpu.Renderer.FrameBuffer.Bind(Key); Gpu.Renderer.FrameBuffer.Bind(Key);
Gpu.Renderer.FrameBuffer.SetViewport(VpX, VpY, VpW, VpH);
} }
private long[] UploadShaders(NvGpuVmm Vmm) private long[] UploadShaders(NvGpuVmm Vmm)
@ -195,8 +207,8 @@ namespace Ryujinx.HLE.Gpu.Engines
Gpu.Renderer.Shader.Bind(Key); Gpu.Renderer.Shader.Bind(Key);
} }
float SignX = GetFlipSign(NvGpuEngine3dReg.ViewportScaleX); float SignX = GetFlipSign(NvGpuEngine3dReg.ViewportNScaleX);
float SignY = GetFlipSign(NvGpuEngine3dReg.ViewportScaleY); float SignY = GetFlipSign(NvGpuEngine3dReg.ViewportNScaleY);
Gpu.Renderer.Shader.SetFlip(SignX, SignY); Gpu.Renderer.Shader.SetFlip(SignX, SignY);
@ -220,8 +232,8 @@ namespace Ryujinx.HLE.Gpu.Engines
private void SetFrontFace() private void SetFrontFace()
{ {
float SignX = GetFlipSign(NvGpuEngine3dReg.ViewportScaleX); float SignX = GetFlipSign(NvGpuEngine3dReg.ViewportNScaleX);
float SignY = GetFlipSign(NvGpuEngine3dReg.ViewportScaleY); float SignY = GetFlipSign(NvGpuEngine3dReg.ViewportNScaleY);
GalFrontFace FrontFace = (GalFrontFace)ReadRegister(NvGpuEngine3dReg.FrontFace); GalFrontFace FrontFace = (GalFrontFace)ReadRegister(NvGpuEngine3dReg.FrontFace);

View file

@ -6,12 +6,14 @@ namespace Ryujinx.HLE.Gpu.Engines
FrameBufferNWidth = 0x202, FrameBufferNWidth = 0x202,
FrameBufferNHeight = 0x203, FrameBufferNHeight = 0x203,
FrameBufferNFormat = 0x204, FrameBufferNFormat = 0x204,
ViewportScaleX = 0x280, ViewportNScaleX = 0x280,
ViewportScaleY = 0x281, ViewportNScaleY = 0x281,
ViewportScaleZ = 0x282, ViewportNScaleZ = 0x282,
ViewportTranslateX = 0x283, ViewportNTranslateX = 0x283,
ViewportTranslateY = 0x284, ViewportNTranslateY = 0x284,
ViewportTranslateZ = 0x285, ViewportNTranslateZ = 0x285,
ViewportNHoriz = 0x300,
ViewportNVert = 0x301,
VertexArrayFirst = 0x35d, VertexArrayFirst = 0x35d,
VertexArrayCount = 0x35e, VertexArrayCount = 0x35e,
ClearDepth = 0x364, ClearDepth = 0x364,

View file

@ -56,8 +56,10 @@ namespace Ryujinx.HLE.Gpu.Texture
int Pitch = (Tic[3] & 0xffff) << 5; int Pitch = (Tic[3] & 0xffff) << 5;
int BlockHeightLog2 = (Tic[3] >> 3) & 7; int BlockHeightLog2 = (Tic[3] >> 3) & 7;
int TileWidthLog2 = (Tic[3] >> 10) & 7;
int BlockHeight = 1 << BlockHeightLog2; int BlockHeight = 1 << BlockHeightLog2;
int TileWidth = 1 << TileWidthLog2;
int Width = (Tic[4] & 0xffff) + 1; int Width = (Tic[4] & 0xffff) + 1;
int Height = (Tic[5] & 0xffff) + 1; int Height = (Tic[5] & 0xffff) + 1;
@ -68,6 +70,7 @@ namespace Ryujinx.HLE.Gpu.Texture
Height, Height,
Pitch, Pitch,
BlockHeight, BlockHeight,
TileWidth,
Swizzle, Swizzle,
Format); Format);

View file

@ -7,8 +7,14 @@ namespace Ryujinx.HLE.Gpu.Texture
{ {
static class TextureHelper static class TextureHelper
{ {
public static ISwizzle GetSwizzle(TextureInfo Texture, int Width, int Bpp) public static ISwizzle GetSwizzle(TextureInfo Texture, int BlockWidth, int Bpp)
{ {
int Width = (Texture.Width + (BlockWidth - 1)) / BlockWidth;
int AlignMask = Texture.TileWidth * (64 / Bpp) - 1;
Width = (Width + AlignMask) & ~AlignMask;
switch (Texture.Swizzle) switch (Texture.Swizzle)
{ {
case TextureSwizzle._1dBuffer: case TextureSwizzle._1dBuffer:

View file

@ -11,6 +11,7 @@ namespace Ryujinx.HLE.Gpu.Texture
public int Pitch { get; private set; } public int Pitch { get; private set; }
public int BlockHeight { get; private set; } public int BlockHeight { get; private set; }
public int TileWidth { get; private set; }
public TextureSwizzle Swizzle { get; private set; } public TextureSwizzle Swizzle { get; private set; }
@ -29,6 +30,8 @@ namespace Ryujinx.HLE.Gpu.Texture
BlockHeight = 16; BlockHeight = 16;
TileWidth = 1;
Swizzle = TextureSwizzle.BlockLinear; Swizzle = TextureSwizzle.BlockLinear;
Format = GalTextureFormat.A8B8G8R8; Format = GalTextureFormat.A8B8G8R8;
@ -40,6 +43,7 @@ namespace Ryujinx.HLE.Gpu.Texture
int Height, int Height,
int Pitch, int Pitch,
int BlockHeight, int BlockHeight,
int TileWidth,
TextureSwizzle Swizzle, TextureSwizzle Swizzle,
GalTextureFormat Format) GalTextureFormat Format)
{ {
@ -48,6 +52,7 @@ namespace Ryujinx.HLE.Gpu.Texture
this.Height = Height; this.Height = Height;
this.Pitch = Pitch; this.Pitch = Pitch;
this.BlockHeight = BlockHeight; this.BlockHeight = BlockHeight;
this.TileWidth = TileWidth;
this.Swizzle = Swizzle; this.Swizzle = Swizzle;
this.Format = Format; this.Format = Format;
} }

View file

@ -56,7 +56,7 @@ namespace Ryujinx.HLE.Gpu.Texture
byte[] Output = new byte[Width * Height]; byte[] Output = new byte[Width * Height];
ISwizzle Swizzle = TextureHelper.GetSwizzle(Texture, Width, 1); ISwizzle Swizzle = TextureHelper.GetSwizzle(Texture, 1, 1);
(AMemory CpuMem, long Position) = TextureHelper.GetMemoryAndPosition( (AMemory CpuMem, long Position) = TextureHelper.GetMemoryAndPosition(
Memory, Memory,
@ -89,7 +89,7 @@ namespace Ryujinx.HLE.Gpu.Texture
byte[] Output = new byte[Width * Height * 2]; byte[] Output = new byte[Width * Height * 2];
ISwizzle Swizzle = TextureHelper.GetSwizzle(Texture, Width, 2); ISwizzle Swizzle = TextureHelper.GetSwizzle(Texture, 1, 2);
(AMemory CpuMem, long Position) = TextureHelper.GetMemoryAndPosition( (AMemory CpuMem, long Position) = TextureHelper.GetMemoryAndPosition(
Memory, Memory,
@ -127,7 +127,7 @@ namespace Ryujinx.HLE.Gpu.Texture
byte[] Output = new byte[Width * Height * 2]; byte[] Output = new byte[Width * Height * 2];
ISwizzle Swizzle = TextureHelper.GetSwizzle(Texture, Width, 2); ISwizzle Swizzle = TextureHelper.GetSwizzle(Texture, 1, 2);
(AMemory CpuMem, long Position) = TextureHelper.GetMemoryAndPosition( (AMemory CpuMem, long Position) = TextureHelper.GetMemoryAndPosition(
Memory, Memory,
@ -164,7 +164,7 @@ namespace Ryujinx.HLE.Gpu.Texture
byte[] Output = new byte[Width * Height * 2]; byte[] Output = new byte[Width * Height * 2];
ISwizzle Swizzle = TextureHelper.GetSwizzle(Texture, Width, 2); ISwizzle Swizzle = TextureHelper.GetSwizzle(Texture, 1, 2);
(AMemory CpuMem, long Position) = TextureHelper.GetMemoryAndPosition( (AMemory CpuMem, long Position) = TextureHelper.GetMemoryAndPosition(
Memory, Memory,
@ -197,7 +197,7 @@ namespace Ryujinx.HLE.Gpu.Texture
byte[] Output = new byte[Width * Height * 4]; byte[] Output = new byte[Width * Height * 4];
ISwizzle Swizzle = TextureHelper.GetSwizzle(Texture, Width, 4); ISwizzle Swizzle = TextureHelper.GetSwizzle(Texture, 1, 4);
(AMemory CpuMem, long Position) = TextureHelper.GetMemoryAndPosition( (AMemory CpuMem, long Position) = TextureHelper.GetMemoryAndPosition(
Memory, Memory,
@ -230,7 +230,7 @@ namespace Ryujinx.HLE.Gpu.Texture
byte[] Output = new byte[Width * Height * 8]; byte[] Output = new byte[Width * Height * 8];
ISwizzle Swizzle = TextureHelper.GetSwizzle(Texture, Width, 8); ISwizzle Swizzle = TextureHelper.GetSwizzle(Texture, 1, 8);
(AMemory CpuMem, long Position) = TextureHelper.GetMemoryAndPosition( (AMemory CpuMem, long Position) = TextureHelper.GetMemoryAndPosition(
Memory, Memory,
@ -263,7 +263,7 @@ namespace Ryujinx.HLE.Gpu.Texture
byte[] Output = new byte[Width * Height * 16]; byte[] Output = new byte[Width * Height * 16];
ISwizzle Swizzle = TextureHelper.GetSwizzle(Texture, Width, 16); ISwizzle Swizzle = TextureHelper.GetSwizzle(Texture, 1, 16);
(AMemory CpuMem, long Position) = TextureHelper.GetMemoryAndPosition( (AMemory CpuMem, long Position) = TextureHelper.GetMemoryAndPosition(
Memory, Memory,
@ -298,7 +298,7 @@ namespace Ryujinx.HLE.Gpu.Texture
byte[] Output = new byte[Width * Height * 8]; byte[] Output = new byte[Width * Height * 8];
ISwizzle Swizzle = TextureHelper.GetSwizzle(Texture, Width, 8); ISwizzle Swizzle = TextureHelper.GetSwizzle(Texture, 4, 8);
(AMemory CpuMem, long Position) = TextureHelper.GetMemoryAndPosition( (AMemory CpuMem, long Position) = TextureHelper.GetMemoryAndPosition(
Memory, Memory,
@ -331,7 +331,7 @@ namespace Ryujinx.HLE.Gpu.Texture
byte[] Output = new byte[Width * Height * 16]; byte[] Output = new byte[Width * Height * 16];
ISwizzle Swizzle = TextureHelper.GetSwizzle(Texture, Width, 16); ISwizzle Swizzle = TextureHelper.GetSwizzle(Texture, BlockWidth, 16);
(AMemory CpuMem, long Position) = TextureHelper.GetMemoryAndPosition( (AMemory CpuMem, long Position) = TextureHelper.GetMemoryAndPosition(
Memory, Memory,

View file

@ -6,29 +6,9 @@ namespace Ryujinx.HLE.Gpu.Texture
{ {
static class TextureWriter static class TextureWriter
{ {
public static void Write( public unsafe static void Write(IAMemory Memory, TextureInfo Texture, byte[] Data)
IAMemory Memory,
TextureInfo Texture,
byte[] Data,
int Width,
int Height)
{ {
switch (Texture.Format) ISwizzle Swizzle = TextureHelper.GetSwizzle(Texture, 1, 4);
{
case GalTextureFormat.A8B8G8R8: Write4Bpp(Memory, Texture, Data, Width, Height); break;
default: throw new NotImplementedException(Texture.Format.ToString());
}
}
private unsafe static void Write4Bpp(
IAMemory Memory,
TextureInfo Texture,
byte[] Data,
int Width,
int Height)
{
ISwizzle Swizzle = TextureHelper.GetSwizzle(Texture, Width, 4);
(AMemory CpuMem, long Position) = TextureHelper.GetMemoryAndPosition( (AMemory CpuMem, long Position) = TextureHelper.GetMemoryAndPosition(
Memory, Memory,
@ -38,8 +18,8 @@ namespace Ryujinx.HLE.Gpu.Texture
{ {
long InOffs = 0; long InOffs = 0;
for (int Y = 0; Y < Height; Y++) for (int Y = 0; Y < Texture.Height; Y++)
for (int X = 0; X < Width; X++) for (int X = 0; X < Texture.Width; X++)
{ {
long Offset = (uint)Swizzle.GetSwizzleOffset(X, Y); long Offset = (uint)Swizzle.GetSwizzleOffset(X, Y);

View file

@ -279,8 +279,8 @@ namespace Ryujinx.HLE.OsHle.Services.Android
private void SendFrameBuffer(ServiceCtx Context, int Slot) private void SendFrameBuffer(ServiceCtx Context, int Slot)
{ {
int FbWidth = 1280; int FbWidth = BufferQueue[Slot].Data.Width;
int FbHeight = 720; int FbHeight = BufferQueue[Slot].Data.Height;
int NvMapHandle = BitConverter.ToInt32(BufferQueue[Slot].Data.RawData, 0x4c); int NvMapHandle = BitConverter.ToInt32(BufferQueue[Slot].Data.RawData, 0x4c);
int BufferOffset = BitConverter.ToInt32(BufferQueue[Slot].Data.RawData, 0x50); int BufferOffset = BitConverter.ToInt32(BufferQueue[Slot].Data.RawData, 0x50);