diff options
| author | gdkchan <gab.dark.100@gmail.com> | 2018-09-18 01:30:35 -0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2018-09-18 01:30:35 -0300 |
| commit | d4187aaa9d7194aa26d04aee838edbc3a38f1862 (patch) | |
| tree | 06fe725c1067b4aeca21749799b835d85e7d2787 /Ryujinx.Graphics/Gal/OpenGL | |
| parent | bec95cacc1061f91373a1e3a1411981af7fe2e4e (diff) | |
Allow "reinterpretation" of framebuffer/zeta formats (#418)
* (Re)Implement format reinterpretation, other changes
* Implement writeback to guest memory, some refactoring
* More refactoring, implement reinterpretation the old way again
* Clean up
* Some fixes on M2MF (old Dma engine), added partial support for P2MF, fix conditional ssy, add Z24S8 zeta format, other fixes
* nit: Formatting
* Address PR feedback
Diffstat (limited to 'Ryujinx.Graphics/Gal/OpenGL')
| -rw-r--r-- | Ryujinx.Graphics/Gal/OpenGL/ImageHandler.cs | 143 | ||||
| -rw-r--r-- | Ryujinx.Graphics/Gal/OpenGL/OGLCachedResource.cs | 6 | ||||
| -rw-r--r-- | Ryujinx.Graphics/Gal/OpenGL/OGLEnumConverter.cs | 4 | ||||
| -rw-r--r-- | Ryujinx.Graphics/Gal/OpenGL/OGLPipeline.cs | 11 | ||||
| -rw-r--r-- | Ryujinx.Graphics/Gal/OpenGL/OGLRasterizer.cs | 6 | ||||
| -rw-r--r-- | Ryujinx.Graphics/Gal/OpenGL/OGLRenderTarget.cs | 336 | ||||
| -rw-r--r-- | Ryujinx.Graphics/Gal/OpenGL/OGLTexture.cs | 161 |
7 files changed, 240 insertions, 427 deletions
diff --git a/Ryujinx.Graphics/Gal/OpenGL/ImageHandler.cs b/Ryujinx.Graphics/Gal/OpenGL/ImageHandler.cs index dda82538..8db0b8a8 100644 --- a/Ryujinx.Graphics/Gal/OpenGL/ImageHandler.cs +++ b/Ryujinx.Graphics/Gal/OpenGL/ImageHandler.cs @@ -1,14 +1,9 @@ -using OpenTK.Graphics.OpenGL; -using Ryujinx.Graphics.Texture; -using System; +using Ryujinx.Graphics.Texture; namespace Ryujinx.Graphics.Gal.OpenGL { class ImageHandler { - private static int CopyBuffer = 0; - private static int CopyBufferSize = 0; - public GalImage Image { get; private set; } public int Width => Image.Width; @@ -16,144 +11,16 @@ namespace Ryujinx.Graphics.Gal.OpenGL public GalImageFormat Format => Image.Format; - public PixelInternalFormat InternalFormat { get; private set; } - public PixelFormat PixelFormat { get; private set; } - public PixelType PixelType { get; private set; } - public int Handle { get; private set; } - private bool Initialized; - - public ImageHandler() - { - Handle = GL.GenTexture(); - } + public bool HasColor => ImageUtils.HasColor(Image.Format); + public bool HasDepth => ImageUtils.HasDepth(Image.Format); + public bool HasStencil => ImageUtils.HasStencil(Image.Format); public ImageHandler(int Handle, GalImage Image) { this.Handle = Handle; - - this.Image = Image; - } - - public void EnsureSetup(GalImage NewImage) - { - if (Width == NewImage.Width && - Height == NewImage.Height && - Format == NewImage.Format && - Initialized) - { - return; - } - - PixelInternalFormat InternalFmt; - PixelFormat PixelFormat; - PixelType PixelType; - - if (ImageUtils.IsCompressed(NewImage.Format)) - { - InternalFmt = (PixelInternalFormat)OGLEnumConverter.GetCompressedImageFormat(NewImage.Format); - - PixelFormat = default(PixelFormat); - PixelType = default(PixelType); - } - else - { - (InternalFmt, PixelFormat, PixelType) = OGLEnumConverter.GetImageFormat(NewImage.Format); - } - - GL.BindTexture(TextureTarget.Texture2D, Handle); - - if (Initialized) - { - if (CopyBuffer == 0) - { - CopyBuffer = GL.GenBuffer(); - } - - int CurrentSize = Math.Max(ImageUtils.GetSize(NewImage), - ImageUtils.GetSize(Image)); - - GL.BindBuffer(BufferTarget.PixelPackBuffer, CopyBuffer); - GL.BindBuffer(BufferTarget.PixelUnpackBuffer, CopyBuffer); - - if (CopyBufferSize < CurrentSize) - { - CopyBufferSize = CurrentSize; - - GL.BufferData(BufferTarget.PixelPackBuffer, CurrentSize, IntPtr.Zero, BufferUsageHint.StreamCopy); - } - - if (ImageUtils.IsCompressed(Image.Format)) - { - GL.GetCompressedTexImage(TextureTarget.Texture2D, 0, IntPtr.Zero); - } - else - { - GL.GetTexImage(TextureTarget.Texture2D, 0, this.PixelFormat, this.PixelType, IntPtr.Zero); - } - - GL.DeleteTexture(Handle); - - Handle = GL.GenTexture(); - - GL.BindTexture(TextureTarget.Texture2D, Handle); - } - - const int MinFilter = (int)TextureMinFilter.Linear; - const int MagFilter = (int)TextureMagFilter.Linear; - - GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, MinFilter); - GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, MagFilter); - - const int Level = 0; - const int Border = 0; - - if (ImageUtils.IsCompressed(NewImage.Format)) - { - Console.WriteLine("Hit"); - - GL.CompressedTexImage2D( - TextureTarget.Texture2D, - Level, - (InternalFormat)InternalFmt, - NewImage.Width, - NewImage.Height, - Border, - ImageUtils.GetSize(NewImage), - IntPtr.Zero); - } - else - { - GL.TexImage2D( - TextureTarget.Texture2D, - Level, - InternalFmt, - NewImage.Width, - NewImage.Height, - Border, - PixelFormat, - PixelType, - IntPtr.Zero); - } - - if (Initialized) - { - GL.BindBuffer(BufferTarget.PixelPackBuffer, 0); - GL.BindBuffer(BufferTarget.PixelUnpackBuffer, 0); - } - - Image = NewImage; - - this.InternalFormat = InternalFmt; - this.PixelFormat = PixelFormat; - this.PixelType = PixelType; - - Initialized = true; + this.Image = Image; } - - public bool HasColor => ImageUtils.HasColor(Image.Format); - public bool HasDepth => ImageUtils.HasDepth(Image.Format); - public bool HasStencil => ImageUtils.HasStencil(Image.Format); } } diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLCachedResource.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLCachedResource.cs index 01ebf982..839915ea 100644 --- a/Ryujinx.Graphics/Gal/OpenGL/OGLCachedResource.cs +++ b/Ryujinx.Graphics/Gal/OpenGL/OGLCachedResource.cs @@ -22,9 +22,9 @@ namespace Ryujinx.Graphics.Gal.OpenGL public CacheBucket(T Value, long DataSize, LinkedListNode<long> Node) { - this.Value = Value; - this.DataSize = DataSize; - this.Node = Node; + this.Value = Value; + this.DataSize = DataSize; + this.Node = Node; Timestamp = Environment.TickCount; } diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLEnumConverter.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLEnumConverter.cs index 876c7b99..fac3875e 100644 --- a/Ryujinx.Graphics/Gal/OpenGL/OGLEnumConverter.cs +++ b/Ryujinx.Graphics/Gal/OpenGL/OGLEnumConverter.cs @@ -149,8 +149,8 @@ namespace Ryujinx.Graphics.Gal.OpenGL case GalImageFormat.R32 | GalImageFormat.Sfloat: return (PixelInternalFormat.R32f, PixelFormat.Red, PixelType.Float); case GalImageFormat.R32 | GalImageFormat.Sint: return (PixelInternalFormat.R32i, PixelFormat.Red, PixelType.Int); case GalImageFormat.R32 | GalImageFormat.Uint: return (PixelInternalFormat.R32ui, PixelFormat.Red, PixelType.UnsignedInt); - case GalImageFormat.A1R5G5B5 | GalImageFormat.Unorm: return (PixelInternalFormat.Rgb5A1, PixelFormat.Rgba, PixelType.UnsignedShort5551); - case GalImageFormat.B5G6R5 | GalImageFormat.Unorm: return (PixelInternalFormat.Rgba, PixelFormat.Rgb, PixelType.UnsignedShort565); + case GalImageFormat.A1R5G5B5 | GalImageFormat.Unorm: return (PixelInternalFormat.Rgb5A1, PixelFormat.Rgba, PixelType.UnsignedShort1555Reversed); + case GalImageFormat.B5G6R5 | GalImageFormat.Unorm: return (PixelInternalFormat.Rgba, PixelFormat.Rgb, PixelType.UnsignedShort565Reversed); case GalImageFormat.R16G16 | GalImageFormat.Sfloat: return (PixelInternalFormat.Rg16f, PixelFormat.Rg, PixelType.HalfFloat); case GalImageFormat.R16G16 | GalImageFormat.Sint: return (PixelInternalFormat.Rg16i, PixelFormat.RgInteger, PixelType.Short); case GalImageFormat.R16G16 | GalImageFormat.Snorm: return (PixelInternalFormat.Rg16Snorm, PixelFormat.Rg, PixelType.Byte); diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLPipeline.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLPipeline.cs index 051b1050..cf856a15 100644 --- a/Ryujinx.Graphics/Gal/OpenGL/OGLPipeline.cs +++ b/Ryujinx.Graphics/Gal/OpenGL/OGLPipeline.cs @@ -126,6 +126,11 @@ namespace Ryujinx.Graphics.Gal.OpenGL BindVertexLayout(New); + if (New.FramebufferSrgb != Old.FramebufferSrgb) + { + Enable(EnableCap.FramebufferSrgb, New.FramebufferSrgb); + } + if (New.FlipX != Old.FlipX || New.FlipY != Old.FlipY || New.Instance != Old.Instance) { Shader.SetExtraData(New.FlipX, New.FlipY, New.Instance); @@ -337,6 +342,12 @@ namespace Ryujinx.Graphics.Gal.OpenGL foreach (GalVertexAttrib Attrib in Binding.Attribs) { + //Skip uninitialized attributes. + if (Attrib.Size == 0) + { + continue; + } + GL.EnableVertexAttribArray(Attrib.Index); GL.BindBuffer(BufferTarget.ArrayBuffer, VboHandle); diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLRasterizer.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLRasterizer.cs index 45106692..ebfba63d 100644 --- a/Ryujinx.Graphics/Gal/OpenGL/OGLRasterizer.cs +++ b/Ryujinx.Graphics/Gal/OpenGL/OGLRasterizer.cs @@ -113,14 +113,14 @@ namespace Ryujinx.Graphics.Gal.OpenGL IndexBuffer.ElemSizeLog2 = (int)Format; } - public void DrawArrays(int First, int PrimCount, GalPrimitiveType PrimType) + public void DrawArrays(int First, int Count, GalPrimitiveType PrimType) { - if (PrimCount == 0) + if (Count == 0) { return; } - GL.DrawArrays(OGLEnumConverter.GetPrimitiveType(PrimType), First, PrimCount); + GL.DrawArrays(OGLEnumConverter.GetPrimitiveType(PrimType), First, Count); } public void DrawElements(long IboKey, int First, int VertexBase, GalPrimitiveType PrimType) diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLRenderTarget.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLRenderTarget.cs index 99bfa350..7dde32d8 100644 --- a/Ryujinx.Graphics/Gal/OpenGL/OGLRenderTarget.cs +++ b/Ryujinx.Graphics/Gal/OpenGL/OGLRenderTarget.cs @@ -15,9 +15,9 @@ namespace Ryujinx.Graphics.Gal.OpenGL public Rect(int X, int Y, int Width, int Height) { - this.X = X; - this.Y = Y; - this.Width = Width; + this.X = X; + this.Y = Y; + this.Width = Width; this.Height = Height; } } @@ -29,7 +29,6 @@ namespace Ryujinx.Graphics.Gal.OpenGL private OGLTexture Texture; - private ImageHandler RawTex; private ImageHandler ReadTex; private Rect Viewport; @@ -64,13 +63,13 @@ namespace Ryujinx.Graphics.Gal.OpenGL this.Texture = Texture; } - public void BindColor(long Key, int Attachment) + public void BindColor(long Key, int Attachment, GalImage Image) { - if (Texture.TryGetImage(Key, out ImageHandler Tex)) + if (Texture.TryGetImageHandler(Key, out ImageHandler CachedImage)) { EnsureFrameBuffer(); - Attach(ref ColorAttachments[Attachment], Tex.Handle, FramebufferAttachment.ColorAttachment0 + Attachment); + Attach(ref ColorAttachments[Attachment], CachedImage.Handle, FramebufferAttachment.ColorAttachment0 + Attachment); } else { @@ -84,40 +83,39 @@ namespace Ryujinx.Graphics.Gal.OpenGL Attach(ref ColorAttachments[Attachment], 0, FramebufferAttachment.ColorAttachment0 + Attachment); } - - public void BindZeta(long Key) + + public void BindZeta(long Key, GalImage Image) { - if (Texture.TryGetImage(Key, out ImageHandler Tex)) + if (Texture.TryGetImageHandler(Key, out ImageHandler CachedImage)) { EnsureFrameBuffer(); - if (Tex.HasDepth && Tex.HasStencil) + if (CachedImage.HasDepth && CachedImage.HasStencil) { - if (DepthAttachment != Tex.Handle || - StencilAttachment != Tex.Handle) + if (DepthAttachment != CachedImage.Handle || + StencilAttachment != CachedImage.Handle) { GL.FramebufferTexture( FramebufferTarget.DrawFramebuffer, FramebufferAttachment.DepthStencilAttachment, - Tex.Handle, + CachedImage.Handle, 0); - DepthAttachment = Tex.Handle; - - StencilAttachment = Tex.Handle; + DepthAttachment = CachedImage.Handle; + StencilAttachment = CachedImage.Handle; } } - else if (Tex.HasDepth) + else if (CachedImage.HasDepth) { - Attach(ref DepthAttachment, Tex.Handle, FramebufferAttachment.DepthAttachment); + Attach(ref DepthAttachment, CachedImage.Handle, FramebufferAttachment.DepthAttachment); Attach(ref StencilAttachment, 0, FramebufferAttachment.StencilAttachment); } - else if (Tex.HasStencil) + else if (CachedImage.HasStencil) { Attach(ref DepthAttachment, 0, FramebufferAttachment.DepthAttachment); - Attach(ref StencilAttachment, Tex.Handle, FramebufferAttachment.StencilAttachment); + Attach(ref StencilAttachment, CachedImage.Handle, FramebufferAttachment.StencilAttachment); } else { @@ -130,57 +128,40 @@ namespace Ryujinx.Graphics.Gal.OpenGL } } - public void UnbindZeta() + private void Attach(ref int OldHandle, int NewHandle, FramebufferAttachment FbAttachment) { - EnsureFrameBuffer(); - - if (DepthAttachment != 0 || - StencilAttachment != 0) + if (OldHandle != NewHandle) { GL.FramebufferTexture( FramebufferTarget.DrawFramebuffer, - FramebufferAttachment.DepthStencilAttachment, - 0, + FbAttachment, + NewHandle, 0); - DepthAttachment = 0; - - StencilAttachment = 0; + OldHandle = NewHandle; } } - public void BindTexture(long Key, int Index) + public void UnbindZeta() { - if (Texture.TryGetImage(Key, out ImageHandler Tex)) + EnsureFrameBuffer(); + + if (DepthAttachment != 0 || StencilAttachment != 0) { - GL.ActiveTexture(TextureUnit.Texture0 + Index); + GL.FramebufferTexture( + FramebufferTarget.DrawFramebuffer, + FramebufferAttachment.DepthStencilAttachment, + 0, + 0); - GL.BindTexture(TextureTarget.Texture2D, Tex.Handle); + DepthAttachment = 0; + StencilAttachment = 0; } } public void Set(long Key) { - if (Texture.TryGetImage(Key, out ImageHandler Tex)) - { - ReadTex = Tex; - } - } - - public void Set(byte[] Data, int Width, int Height) - { - if (RawTex == null) - { - RawTex = new ImageHandler(); - } - - RawTex.EnsureSetup(new GalImage(Width, Height, RawFormat)); - - GL.BindTexture(TextureTarget.Texture2D, RawTex.Handle); - - GL.TexSubImage2D(TextureTarget.Texture2D, 0, 0, 0, Width, Height, RawTex.PixelFormat, RawTex.PixelType, Data); - - ReadTex = RawTex; + Texture.TryGetImageHandler(Key, out ReadTex); } public void SetMap(int[] Map) @@ -280,13 +261,15 @@ namespace Ryujinx.Graphics.Gal.OpenGL int DstY0 = FlipY ? DstPaddingY : Window.Height - DstPaddingY; int DstY1 = FlipY ? Window.Height - DstPaddingY : DstPaddingY; - if (SrcFb == 0) SrcFb = GL.GenFramebuffer(); - - GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, 0); - GL.Viewport(0, 0, Window.Width, Window.Height); + if (SrcFb == 0) + { + SrcFb = GL.GenFramebuffer(); + } + GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, SrcFb); + GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, 0); GL.FramebufferTexture(FramebufferTarget.ReadFramebuffer, FramebufferAttachment.ColorAttachment0, ReadTex.Handle, 0); @@ -298,7 +281,8 @@ namespace Ryujinx.Graphics.Gal.OpenGL GL.BlitFramebuffer( SrcX0, SrcY0, SrcX1, SrcY1, DstX0, DstY0, DstX1, DstY1, - ClearBufferMask.ColorBufferBit, BlitFramebufferFilter.Linear); + ClearBufferMask.ColorBufferBit, + BlitFramebufferFilter.Linear); EnsureFrameBuffer(); } @@ -315,183 +299,145 @@ namespace Ryujinx.Graphics.Gal.OpenGL int DstX1, int DstY1) { - if (Texture.TryGetImage(SrcKey, out ImageHandler SrcTex) && - Texture.TryGetImage(DstKey, out ImageHandler DstTex)) + if (Texture.TryGetImageHandler(SrcKey, out ImageHandler SrcTex) && + Texture.TryGetImageHandler(DstKey, out ImageHandler DstTex)) { - if (SrcTex.HasColor != DstTex.HasColor || - SrcTex.HasDepth != DstTex.HasDepth || + if (SrcTex.HasColor != DstTex.HasColor || + SrcTex.HasDepth != DstTex.HasDepth || SrcTex.HasStencil != DstTex.HasStencil) { throw new NotImplementedException(); } - if (SrcTex.HasColor) + if (SrcFb == 0) { - CopyTextures( - SrcX0, SrcY0, SrcX1, SrcY1, - DstX0, DstY0, DstX1, DstY1, - SrcTex.Handle, - DstTex.Handle, - FramebufferAttachment.ColorAttachment0, - ClearBufferMask.ColorBufferBit, - true); + SrcFb = GL.GenFramebuffer(); } - else if (SrcTex.HasDepth && SrcTex.HasStencil) - { - CopyTextures( - SrcX0, SrcY0, SrcX1, SrcY1, - DstX0, DstY0, DstX1, DstY1, - SrcTex.Handle, - DstTex.Handle, - FramebufferAttachment.DepthStencilAttachment, - ClearBufferMask.DepthBufferBit | ClearBufferMask.StencilBufferBit, - false); - } - else if (SrcTex.HasDepth) - { - CopyTextures( - SrcX0, SrcY0, SrcX1, SrcY1, - DstX0, DstY0, DstX1, DstY1, - SrcTex.Handle, - DstTex.Handle, - FramebufferAttachment.DepthAttachment, - ClearBufferMask.DepthBufferBit, - false); - } - else if (SrcTex.HasStencil) + + if (DstFb == 0) { - CopyTextures( - SrcX0, SrcY0, SrcX1, SrcY1, - DstX0, DstY0, DstX1, DstY1, - SrcTex.Handle, - DstTex.Handle, - FramebufferAttachment.StencilAttachment, - ClearBufferMask.StencilBufferBit, - false); + DstFb = GL.GenFramebuffer(); } - else + + GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, SrcFb); + GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, DstFb); + + FramebufferAttachment Attachment = GetAttachment(SrcTex); + + GL.FramebufferTexture(FramebufferTarget.ReadFramebuffer, Attachment, SrcTex.Handle, 0); + GL.FramebufferTexture(FramebufferTarget.DrawFramebuffer, Attachment, DstTex.Handle, 0); + + BlitFramebufferFilter Filter = BlitFramebufferFilter.Nearest; + + if (SrcTex.HasColor) { - throw new InvalidOperationException(); + GL.DrawBuffer(DrawBufferMode.ColorAttachment0); + + Filter = BlitFramebufferFilter.Linear; } - } - } - public void GetBufferData(long Key, Action<byte[]> Callback) - { - if (Texture.TryGetImage(Key, out ImageHandler Tex)) - { - byte[] Data = new byte[ImageUtils.GetSize(Tex.Image)]; + ClearBufferMask Mask = GetClearMask(SrcTex); - GL.BindTexture(TextureTarget.Texture2D, Tex.Handle); + GL.Clear(Mask); - GL.GetTexImage( - TextureTarget.Texture2D, - 0, - Tex.PixelFormat, - Tex.PixelType, - Data); + GL.BlitFramebuffer(SrcX0, SrcY0, SrcX1, SrcY1, DstX0, DstY0, DstX1, DstY1, Mask, Filter); - Callback(Data); + EnsureFrameBuffer(); } } - public void SetBufferData( - long Key, - int Width, - int Height, - byte[] Buffer) + public void Reinterpret(long Key, GalImage NewImage) { - if (Texture.TryGetImage(Key, out ImageHandler Tex)) + if (!Texture.TryGetImage(Key, out GalImage OldImage)) { - GL.BindTexture(TextureTarget.Texture2D, Tex.Handle); - - const int Level = 0; - const int Border = 0; - - GL.TexImage2D( - TextureTarget.Texture2D, - Level, - Tex.InternalFormat, - Width, - Height, - Border, - Tex.PixelFormat, - Tex.PixelType, - Buffer); + return; } - } - private void EnsureFrameBuffer() - { - if (DummyFrameBuffer == 0) + if (NewImage.Format == OldImage.Format) { - DummyFrameBuffer = GL.GenFramebuffer(); + return; } - GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, DummyFrameBuffer); + byte[] Data = GetData(Key); + + GL.PixelStore(PixelStoreParameter.UnpackRowLength, OldImage.Width); + + Texture.Create(Key, Data, NewImage); + + GL.PixelStore(PixelStoreParameter.UnpackRowLength, 0); } - private void Attach(ref int OldHandle, int NewHandle, FramebufferAttachment FbAttachment) + public byte[] GetData(long Key) { - if (OldHandle != NewHandle) + if (!Texture.TryGetImageHandler(Key, out ImageHandler CachedImage)) { - GL.FramebufferTexture( - FramebufferTarget.DrawFramebuffer, - FbAttachment, - NewHandle, - 0); - - OldHandle = NewHandle; + return null; } - } - private void CopyTextures( - int SrcX0, - int SrcY0, - int SrcX1, - int SrcY1, - int DstX0, - int DstY0, - int DstX1, - int DstY1, - int SrcTexture, - int DstTexture, - FramebufferAttachment Attachment, - ClearBufferMask Mask, - bool Color) - { - if (SrcFb == 0) SrcFb = GL.GenFramebuffer(); - if (DstFb == 0) DstFb = GL.GenFramebuffer(); + if (SrcFb == 0) + { + SrcFb = GL.GenFramebuffer(); + } GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, SrcFb); - GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, DstFb); - GL.FramebufferTexture( - FramebufferTarget.ReadFramebuffer, - Attachment, - SrcTexture, - 0); + FramebufferAttachment Attachment = GetAttachment(CachedImage); + + GL.FramebufferTexture(FramebufferTarget.ReadFramebuffer, Attachment, CachedImage.Handle, 0); + + int Size = ImageUtils.GetSize(CachedImage.Image); + + byte[] Data = new byte[Size]; - GL.FramebufferTexture( - FramebufferTarget.DrawFramebuffer, - Attachment, - DstTexture, - 0); + int Width = CachedImage.Width; + int Height = CachedImage.Height; - if (Color) + (_, PixelFormat Format, PixelType Type) = OGLEnumConverter.GetImageFormat(CachedImage.Format); + + GL.ReadPixels(0, 0, Width, Height, Format, Type, Data); + + return Data; + } + + private static FramebufferAttachment GetAttachment(ImageHandler CachedImage) + { + if (CachedImage.HasColor) { - GL.DrawBuffer(DrawBufferMode.ColorAttachment0); + return FramebufferAttachment.ColorAttachment0; + } + else if (CachedImage.HasDepth && CachedImage.HasStencil) + { + return FramebufferAttachment.DepthStencilAttachment; + } + else if (CachedImage.HasDepth) + { + return FramebufferAttachment.DepthAttachment; + } + else if (CachedImage.HasStencil) + { + return FramebufferAttachment.StencilAttachment; + } + else + { + throw new InvalidOperationException(); } + } - GL.Clear(Mask); + private static ClearBufferMask GetClearMask(ImageHandler CachedImage) + { + return (CachedImage.HasColor ? ClearBufferMask.ColorBufferBit : 0) | + (CachedImage.HasDepth ? ClearBufferMask.DepthBufferBit : 0) | + (CachedImage.HasStencil ? ClearBufferMask.StencilBufferBit : 0); + } - GL.BlitFramebuffer( - SrcX0, SrcY0, SrcX1, SrcY1, - DstX0, DstY0, DstX1, DstY1, - Mask, - Color ? BlitFramebufferFilter.Linear : BlitFramebufferFilter.Nearest); + private void EnsureFrameBuffer() + { + if (DummyFrameBuffer == 0) + { + DummyFrameBuffer = GL.GenFramebuffer(); + } - EnsureFrameBuffer(); + GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, DummyFrameBuffer); } } }
\ No newline at end of file diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLTexture.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLTexture.cs index 7e1c0e53..3347afbd 100644 --- a/Ryujinx.Graphics/Gal/OpenGL/OGLTexture.cs +++ b/Ryujinx.Graphics/Gal/OpenGL/OGLTexture.cs @@ -28,17 +28,65 @@ namespace Ryujinx.Graphics.Gal.OpenGL GL.DeleteTexture(CachedImage.Handle); } - public void Create(long Key, byte[] Data, GalImage Image) + public void Create(long Key, int Size, GalImage Image) { int Handle = GL.GenTexture(); - TextureCache.AddOrUpdate(Key, new ImageHandler(Handle, Image), (uint)Data.Length); + GL.BindTexture(TextureTarget.Texture2D, Handle); + + const int Level = 0; //TODO: Support mipmap textures. + const int Border = 0; + + TextureCache.AddOrUpdate(Key, new ImageHandler(Handle, Image), (uint)Size); + + GalImageFormat TypeLess = Image.Format & GalImageFormat.FormatMask; + + bool IsASTC = TypeLess >= GalImageFormat.ASTC_BEGIN && TypeLess <= GalImageFormat.ASTC_END; + + if (ImageUtils.IsCompressed(Image.Format) && !IsASTC) + { + InternalFormat InternalFmt = OGLEnumConverter.GetCompressedImageFormat(Image.Format); + + GL.CompressedTexImage2D( + TextureTarget.Texture2D, + Level, + InternalFmt, + Image.Width, + Image.Height, + Border, + Size, + IntPtr.Zero); + } + else + { + (PixelInternalFormat InternalFmt, + PixelFormat Format, + PixelType Type) = OGLEnumConverter.GetImageFormat(Image.Format); + + GL.TexImage2D( + TextureTarget.Texture2D, + Level, + InternalFmt, + Image.Width, + Image.Height, + Border, + Format, + Type, + IntPtr.Zero); + } + } + + public void Create(long Key, byte[] Data, GalImage Image) + { + int Handle = GL.GenTexture(); GL.BindTexture(TextureTarget.Texture2D, Handle); const int Level = 0; //TODO: Support mipmap textures. const int Border = 0; + TextureCache.AddOrUpdate(Key, new ImageHandler(Handle, Image), (uint)Data.Length); + GalImageFormat TypeLess = Image.Format & GalImageFormat.FormatMask; bool IsASTC = TypeLess >= GalImageFormat.ASTC_BEGIN && TypeLess <= GalImageFormat.ASTC_END; @@ -62,8 +110,8 @@ namespace Ryujinx.Graphics.Gal.OpenGL //TODO: Use KHR_texture_compression_astc_hdr when available if (IsASTC) { - int TextureBlockWidth = GetAstcBlockWidth(Image.Format); - int TextureBlockHeight = GetAstcBlockHeight(Image.Format); + int TextureBlockWidth = ImageUtils.GetBlockWidth(Image.Format); + int TextureBlockHeight = ImageUtils.GetBlockHeight(Image.Format); Data = ASTCDecoder.DecodeToRGBA8888( Data, @@ -85,12 +133,14 @@ namespace Ryujinx.Graphics.Gal.OpenGL Image.Format = GalImageFormat.R8G8 | (Image.Format & GalImageFormat.TypeMask); } - (PixelInternalFormat InternalFormat, PixelFormat Format, PixelType Type) = OGLEnumConverter.GetImageFormat(Image.Format); + (PixelInternalFormat InternalFmt, + PixelFormat Format, + PixelType Type) = OGLEnumConverter.GetImageFormat(Image.Format); GL.TexImage2D( TextureTarget.Texture2D, Level, - InternalFormat, + InternalFmt, Image.Width, Image.Height, Border, @@ -98,112 +148,51 @@ namespace Ryujinx.Graphics.Gal.OpenGL Type, Data); } - - int SwizzleR = (int)OGLEnumConverter.GetTextureSwizzle(Image.XSource); - int SwizzleG = (int)OGLEnumConverter.GetTextureSwizzle(Image.YSource); - int SwizzleB = (int)OGLEnumConverter.GetTextureSwizzle(Image.ZSource); - int SwizzleA = (int)OGLEnumConverter.GetTextureSwizzle(Image.WSource); - - GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureSwizzleR, SwizzleR); - GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureSwizzleG, SwizzleG); - GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureSwizzleB, SwizzleB); - GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureSwizzleA, SwizzleA); } - public void CreateFb(long Key, long Size, GalImage Image) + public bool TryGetImage(long Key, out GalImage Image) { - if (!TryGetImage(Key, out ImageHandler CachedImage)) + if (TextureCache.TryGetValue(Key, out ImageHandler CachedImage)) { - CachedImage = new ImageHandler(); - - TextureCache.AddOrUpdate(Key, CachedImage, Size); - } + Image = CachedImage.Image; - CachedImage.EnsureSetup(Image); - } - - public bool TryGetImage(long Key, out ImageHandler CachedImage) - { - if (TextureCache.TryGetValue(Key, out CachedImage)) - { return true; } - CachedImage = null; + Image = default(GalImage); return false; } - private static int GetAstcBlockWidth(GalImageFormat Format) + public bool TryGetImageHandler(long Key, out ImageHandler CachedImage) { - switch (Format) - { - case GalImageFormat.ASTC_4x4 | GalImageFormat.Unorm: return 4; - case GalImageFormat.ASTC_5x5 | GalImageFormat.Unorm: return 5; - case GalImageFormat.ASTC_6x6 | GalImageFormat.Unorm: return 6; - case GalImageFormat.ASTC_8x8 | GalImageFormat.Unorm: return 8; - case GalImageFormat.ASTC_10x10 | GalImageFormat.Unorm: return 10; - case GalImageFormat.ASTC_12x12 | GalImageFormat.Unorm: return 12; - case GalImageFormat.ASTC_5x4 | GalImageFormat.Unorm: return 5; - case GalImageFormat.ASTC_6x5 | GalImageFormat.Unorm: return 6; - case GalImageFormat.ASTC_8x6 | GalImageFormat.Unorm: return 8; - case GalImageFormat.ASTC_10x8 | GalImageFormat.Unorm: return 10; - case GalImageFormat.ASTC_12x10 | GalImageFormat.Unorm: return 12; - case GalImageFormat.ASTC_8x5 | GalImageFormat.Unorm: return 8; - case GalImageFormat.ASTC_10x5 | GalImageFormat.Unorm: return 10; - case GalImageFormat.ASTC_10x6 | GalImageFormat.Unorm: return 10; - } - - throw new ArgumentException(nameof(Format)); - } - - private static int GetAstcBlockHeight(GalImageFormat Format) - { - switch (Format) - { - case GalImageFormat.ASTC_4x4 | GalImageFormat.Unorm: return 4; - case GalImageFormat.ASTC_5x5 | GalImageFormat.Unorm: return 5; - case GalImageFormat.ASTC_6x6 | GalImageFormat.Unorm: return 6; - case GalImageFormat.ASTC_8x8 | GalImageFormat.Unorm: return 8; - case GalImageFormat.ASTC_10x10 | GalImageFormat.Unorm: return 10; - case GalImageFormat.ASTC_12x12 | GalImageFormat.Unorm: return 12; - case GalImageFormat.ASTC_5x4 | GalImageFormat.Unorm: return 4; - case GalImageFormat.ASTC_6x5 | GalImageFormat.Unorm: return 5; - case GalImageFormat.ASTC_8x6 | GalImageFormat.Unorm: return 6; - case GalImageFormat.ASTC_10x8 | GalImageFormat.Unorm: return 8; - case GalImageFormat.ASTC_12x10 | GalImageFormat.Unorm: return 10; - case GalImageFormat.ASTC_8x5 | GalImageFormat.Unorm: return 5; - case GalImageFormat.ASTC_10x5 | GalImageFormat.Unorm: return 5; - case GalImageFormat.ASTC_10x6 | GalImageFormat.Unorm: return 6; - } - - throw new ArgumentException(nameof(Format)); - } - - public bool TryGetCachedTexture(long Key, long DataSize, out GalImage Image) - { - if (TextureCache.TryGetSize(Key, out long Size) && Size == DataSize) + if (TextureCache.TryGetValue(Key, out CachedImage)) { - if (TextureCache.TryGetValue(Key, out ImageHandler CachedImage)) - { - Image = CachedImage.Image; - - return true; - } + return true; } - Image = default(GalImage); + CachedImage = null; return false; } - public void Bind(long Key, int Index) + public void Bind(long Key, int Index, GalImage Image) { if (TextureCache.TryGetValue(Key, out ImageHandler CachedImage)) { GL.ActiveTexture(TextureUnit.Texture0 + Index); GL.BindTexture(TextureTarget.Texture2D, CachedImage.Handle); + + int[] SwizzleRgba = new int[] + { + (int)OGLEnumConverter.GetTextureSwizzle(Image.XSource), + (int)OGLEnumConverter.GetTextureSwizzle(Image.YSource), + (int)OGLEnumConverter.GetTextureSwizzle(Image.ZSource), + (int)OGLEnumConverter.GetTextureSwizzle(Image.WSource) + }; + + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureSwizzleRgba, SwizzleRgba); } } |
