private void TextureCopy(NvGpuVmm Vmm, NvGpuPBEntry PBEntry) { CopyOperation Operation = (CopyOperation)ReadRegister(NvGpuEngine2dReg.CopyOperation); bool SrcLinear = ReadRegister(NvGpuEngine2dReg.SrcLinear) != 0; int SrcWidth = ReadRegister(NvGpuEngine2dReg.SrcWidth); int SrcHeight = ReadRegister(NvGpuEngine2dReg.SrcHeight); bool DstLinear = ReadRegister(NvGpuEngine2dReg.DstLinear) != 0; int DstWidth = ReadRegister(NvGpuEngine2dReg.DstWidth); int DstHeight = ReadRegister(NvGpuEngine2dReg.DstHeight); int DstPitch = ReadRegister(NvGpuEngine2dReg.DstPitch); int DstBlkDim = ReadRegister(NvGpuEngine2dReg.DstBlockDimensions); TextureSwizzle DstSwizzle = DstLinear ? TextureSwizzle.Pitch : TextureSwizzle.BlockLinear; int DstBlockHeight = 1 << ((DstBlkDim >> 4) & 0xf); long Tag = Vmm.GetPhysicalAddress(MakeInt64From2xInt32(NvGpuEngine2dReg.SrcAddress)); long SrcAddress = MakeInt64From2xInt32(NvGpuEngine2dReg.SrcAddress); long DstAddress = MakeInt64From2xInt32(NvGpuEngine2dReg.DstAddress); bool IsFbTexture = Gpu.Engine3d.IsFrameBufferPosition(Tag); if (IsFbTexture && DstLinear) { DstSwizzle = TextureSwizzle.BlockLinear; } Texture DstTexture = new Texture( DstAddress, DstWidth, DstHeight, DstBlockHeight, DstBlockHeight, DstSwizzle, GalTextureFormat.A8B8G8R8); if (IsFbTexture) { Gpu.Renderer.GetFrameBufferData(Tag, (byte[] Buffer) => { CopyTexture(Vmm, DstTexture, Buffer); }); } else { long Size = SrcWidth * SrcHeight * 4; byte[] Buffer = Vmm.ReadBytes(SrcAddress, Size); CopyTexture(Vmm, DstTexture, Buffer); } }
private void SetFrameBuffer(NvGpuVmm Vmm, int FbIndex) { long VA = MakeInt64From2xInt32(NvGpuEngine3dReg.FrameBufferNAddress + FbIndex * 0x10); long PA = Vmm.GetPhysicalAddress(VA); FrameBuffers.Add(PA); int Width = ReadRegister(NvGpuEngine3dReg.FrameBufferNWidth + FbIndex * 0x10); int Height = ReadRegister(NvGpuEngine3dReg.FrameBufferNHeight + FbIndex * 0x10); //Note: Using the Width/Height results seems to give incorrect results. //Maybe the size of all frame buffers is hardcoded to screen size? This seems unlikely. Gpu.Renderer.CreateFrameBuffer(PA, 1280, 720); Gpu.Renderer.BindFrameBuffer(PA); }
private void UploadTexture(NvGpuVmm Vmm, long BasePosition, int TexIndex, int HndIndex) { long Position = BasePosition + HndIndex * 4; int TextureHandle = Vmm.ReadInt32(Position); int TicIndex = (TextureHandle >> 0) & 0xfffff; int TscIndex = (TextureHandle >> 20) & 0xfff; long TicPosition = MakeInt64From2xInt32(NvGpuEngine3dReg.TexHeaderPoolOffset); long TscPosition = MakeInt64From2xInt32(NvGpuEngine3dReg.TexSamplerPoolOffset); TicPosition += TicIndex * 0x20; TscPosition += TscIndex * 0x20; GalTextureSampler Sampler = TextureFactory.MakeSampler(Gpu, Vmm, TscPosition); long TextureAddress = Vmm.ReadInt64(TicPosition + 4) & 0xffffffffffff; TextureAddress = Vmm.GetPhysicalAddress(TextureAddress); if (IsFrameBufferPosition(TextureAddress)) { //This texture is a frame buffer texture, //we shouldn't read anything from memory and bind //the frame buffer texture instead, since we're not //really writing anything to memory. Gpu.Renderer.BindFrameBufferTexture(TextureAddress, TexIndex, Sampler); } else { GalTexture Texture = TextureFactory.MakeTexture(Gpu, Vmm, TicPosition); Gpu.Renderer.SetTextureAndSampler(TexIndex, Texture, Sampler); Gpu.Renderer.BindTexture(TexIndex); } }