Ejemplo n.º 1
0
        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);
            int  SrcPitch  = ReadRegister(NvGpuEngine2dReg.SrcPitch);
            int  SrcBlkDim = ReadRegister(NvGpuEngine2dReg.SrcBlockDimensions);

            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 SrcSwizzle = SrcLinear
                ? TextureSwizzle.Pitch
                : TextureSwizzle.BlockLinear;

            TextureSwizzle DstSwizzle = DstLinear
                ? TextureSwizzle.Pitch
                : TextureSwizzle.BlockLinear;

            int SrcBlockHeight = 1 << ((SrcBlkDim >> 4) & 0xf);
            int DstBlockHeight = 1 << ((DstBlkDim >> 4) & 0xf);

            long SrcAddress = MakeInt64From2xInt32(NvGpuEngine2dReg.SrcAddress);
            long DstAddress = MakeInt64From2xInt32(NvGpuEngine2dReg.DstAddress);

            long SrcKey = Vmm.GetPhysicalAddress(SrcAddress);
            long DstKey = Vmm.GetPhysicalAddress(DstAddress);

            bool IsSrcFb = Gpu.Engine3d.IsFrameBufferPosition(SrcKey);
            bool IsDstFb = Gpu.Engine3d.IsFrameBufferPosition(DstKey);

            TextureInfo SrcTexture()
            {
                return(new TextureInfo(
                           SrcAddress,
                           SrcWidth,
                           SrcHeight,
                           SrcPitch,
                           SrcBlockHeight, 1,
                           SrcSwizzle,
                           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) =>
                {
                    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
            {
                //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));
            }
        }