Improved and simplified window texture presentation
This commit is contained in:
parent
b2b2e04669
commit
16d88c21fc
11 changed files with 137 additions and 497 deletions
|
@ -2,11 +2,7 @@ namespace Ryujinx.Graphics.GAL
|
||||||
{
|
{
|
||||||
public interface IWindow
|
public interface IWindow
|
||||||
{
|
{
|
||||||
void Present();
|
void Present(ITexture texture, ImageCrop crop);
|
||||||
|
|
||||||
void QueueTexture(ITexture texture, ImageCrop crop, object context);
|
|
||||||
|
|
||||||
void RegisterTextureReleaseCallback(TextureReleaseCallback callback);
|
|
||||||
|
|
||||||
void SetSize(int width, int height);
|
void SetSize(int width, int height);
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,8 +76,6 @@ namespace Ryujinx.Graphics.Gpu.Engine
|
||||||
state.RegisterCallback(MethodOffset.UniformBufferBindFragment, UniformBufferBindFragment);
|
state.RegisterCallback(MethodOffset.UniformBufferBindFragment, UniformBufferBindFragment);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Image.Texture GetTexture(ulong address) => _textureManager.Find2(address);
|
|
||||||
|
|
||||||
private void UpdateState(GpuState state)
|
private void UpdateState(GpuState state)
|
||||||
{
|
{
|
||||||
// Shaders must be the first one to be updated if modified, because
|
// Shaders must be the first one to be updated if modified, because
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
using Ryujinx.Graphics.GAL;
|
using Ryujinx.Graphics.GAL;
|
||||||
using Ryujinx.Graphics.GAL.Texture;
|
|
||||||
using Ryujinx.Graphics.Gpu.Engine;
|
using Ryujinx.Graphics.Gpu.Engine;
|
||||||
using Ryujinx.Graphics.Gpu.Image;
|
|
||||||
using Ryujinx.Graphics.Gpu.Memory;
|
using Ryujinx.Graphics.Gpu.Memory;
|
||||||
using Ryujinx.Graphics.Gpu.State;
|
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Gpu
|
namespace Ryujinx.Graphics.Gpu
|
||||||
|
@ -24,6 +21,8 @@ namespace Ryujinx.Graphics.Gpu
|
||||||
|
|
||||||
public DmaPusher DmaPusher { get; }
|
public DmaPusher DmaPusher { get; }
|
||||||
|
|
||||||
|
public Window Window { get; }
|
||||||
|
|
||||||
internal int SequenceNumber { get; private set; }
|
internal int SequenceNumber { get; private set; }
|
||||||
|
|
||||||
private Lazy<Capabilities> _caps;
|
private Lazy<Capabilities> _caps;
|
||||||
|
@ -44,6 +43,8 @@ namespace Ryujinx.Graphics.Gpu
|
||||||
|
|
||||||
DmaPusher = new DmaPusher(this);
|
DmaPusher = new DmaPusher(this);
|
||||||
|
|
||||||
|
Window = new Window(this);
|
||||||
|
|
||||||
_caps = new Lazy<Capabilities>(GetCapabilities);
|
_caps = new Lazy<Capabilities>(GetCapabilities);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,37 +53,6 @@ namespace Ryujinx.Graphics.Gpu
|
||||||
SequenceNumber++;
|
SequenceNumber++;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ITexture GetTexture(
|
|
||||||
ulong address,
|
|
||||||
int width,
|
|
||||||
int height,
|
|
||||||
int stride,
|
|
||||||
bool isLinear,
|
|
||||||
int gobBlocksInY,
|
|
||||||
Format format,
|
|
||||||
int bytesPerPixel)
|
|
||||||
{
|
|
||||||
FormatInfo formatInfo = new FormatInfo(format, 1, 1, bytesPerPixel);
|
|
||||||
|
|
||||||
TextureInfo info = new TextureInfo(
|
|
||||||
address,
|
|
||||||
width,
|
|
||||||
height,
|
|
||||||
1,
|
|
||||||
1,
|
|
||||||
1,
|
|
||||||
1,
|
|
||||||
stride,
|
|
||||||
isLinear,
|
|
||||||
gobBlocksInY,
|
|
||||||
1,
|
|
||||||
1,
|
|
||||||
Target.Texture2D,
|
|
||||||
formatInfo);
|
|
||||||
|
|
||||||
return Methods.GetTexture(address)?.HostTexture;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Capabilities GetCapabilities()
|
private Capabilities GetCapabilities()
|
||||||
{
|
{
|
||||||
return Renderer.GetCapabilities();
|
return Renderer.GetCapabilities();
|
||||||
|
|
|
@ -335,18 +335,6 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_info.FormatInfo.Format == Format.R8G8B8A8Srgb &&
|
|
||||||
info.FormatInfo.Format == Format.R8G8B8A8Unorm && !strict)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_info.FormatInfo.Format == Format.R8G8B8A8Unorm &&
|
|
||||||
info.FormatInfo.Format == Format.R8G8B8A8Srgb && !strict)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return _info.FormatInfo.Format == info.FormatInfo.Format;
|
return _info.FormatInfo.Format == info.FormatInfo.Format;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||||
private ITexture[] _rtHostColors;
|
private ITexture[] _rtHostColors;
|
||||||
private ITexture _rtHostDs;
|
private ITexture _rtHostDs;
|
||||||
|
|
||||||
private ConcurrentRangeList<Texture> _textures;
|
private RangeList<Texture> _textures;
|
||||||
|
|
||||||
private AutoDeleteCache _cache;
|
private AutoDeleteCache _cache;
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||||
|
|
||||||
_rtHostColors = new ITexture[Constants.TotalRenderTargets];
|
_rtHostColors = new ITexture[Constants.TotalRenderTargets];
|
||||||
|
|
||||||
_textures = new ConcurrentRangeList<Texture>();
|
_textures = new RangeList<Texture>();
|
||||||
|
|
||||||
_cache = new AutoDeleteCache();
|
_cache = new AutoDeleteCache();
|
||||||
}
|
}
|
||||||
|
@ -561,28 +561,6 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||||
info.SwizzleA);
|
info.SwizzleA);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Texture Find2(ulong address)
|
|
||||||
{
|
|
||||||
Texture[] ts = _textures.FindOverlaps(address, 1);
|
|
||||||
|
|
||||||
if (ts.Length == 2)
|
|
||||||
{
|
|
||||||
return ts[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ts.Length == 0)
|
|
||||||
{
|
|
||||||
ts = _textures.FindOverlaps(address - 1, 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ts.Length == 0)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ts[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Flush()
|
public void Flush()
|
||||||
{
|
{
|
||||||
foreach (Texture texture in _cache)
|
foreach (Texture texture in _cache)
|
||||||
|
|
|
@ -1,208 +0,0 @@
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Gpu.Memory
|
|
||||||
{
|
|
||||||
class ConcurrentRangeList<T> where T : IRange<T>
|
|
||||||
{
|
|
||||||
private List<T> _items;
|
|
||||||
|
|
||||||
public ConcurrentRangeList()
|
|
||||||
{
|
|
||||||
_items = new List<T>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Add(T item)
|
|
||||||
{
|
|
||||||
lock (_items)
|
|
||||||
{
|
|
||||||
int index = BinarySearch(item.Address);
|
|
||||||
|
|
||||||
if (index < 0)
|
|
||||||
{
|
|
||||||
index = ~index;
|
|
||||||
}
|
|
||||||
|
|
||||||
_items.Insert(index, item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Remove(T item)
|
|
||||||
{
|
|
||||||
lock (_items)
|
|
||||||
{
|
|
||||||
int index = BinarySearch(item.Address);
|
|
||||||
|
|
||||||
if (index >= 0)
|
|
||||||
{
|
|
||||||
while (index > 0 && _items[index - 1].Address == item.Address)
|
|
||||||
{
|
|
||||||
index--;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (index < _items.Count)
|
|
||||||
{
|
|
||||||
if (_items[index].Equals(item))
|
|
||||||
{
|
|
||||||
_items.RemoveAt(index);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_items[index].Address > item.Address)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public T FindFirstOverlap(T item)
|
|
||||||
{
|
|
||||||
return FindFirstOverlap(item.Address, item.Size);
|
|
||||||
}
|
|
||||||
|
|
||||||
public T FindFirstOverlap(ulong address, ulong size)
|
|
||||||
{
|
|
||||||
lock (_items)
|
|
||||||
{
|
|
||||||
int index = BinarySearch(address, size);
|
|
||||||
|
|
||||||
if (index < 0)
|
|
||||||
{
|
|
||||||
return default(T);
|
|
||||||
}
|
|
||||||
|
|
||||||
return _items[index];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public T[] FindOverlaps(T item)
|
|
||||||
{
|
|
||||||
return FindOverlaps(item.Address, item.Size);
|
|
||||||
}
|
|
||||||
|
|
||||||
public T[] FindOverlaps(ulong address, ulong size)
|
|
||||||
{
|
|
||||||
List<T> overlapsList = new List<T>();
|
|
||||||
|
|
||||||
ulong endAddress = address + size;
|
|
||||||
|
|
||||||
lock (_items)
|
|
||||||
{
|
|
||||||
foreach (T item in _items)
|
|
||||||
{
|
|
||||||
if (item.Address >= endAddress)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (item.OverlapsWith(address, size))
|
|
||||||
{
|
|
||||||
overlapsList.Add(item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return overlapsList.ToArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
public T[] FindOverlaps(ulong address)
|
|
||||||
{
|
|
||||||
List<T> overlapsList = new List<T>();
|
|
||||||
|
|
||||||
lock (_items)
|
|
||||||
{
|
|
||||||
int index = BinarySearch(address);
|
|
||||||
|
|
||||||
if (index >= 0)
|
|
||||||
{
|
|
||||||
while (index > 0 && _items[index - 1].Address == address)
|
|
||||||
{
|
|
||||||
index--;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (index < _items.Count)
|
|
||||||
{
|
|
||||||
T overlap = _items[index++];
|
|
||||||
|
|
||||||
if (overlap.Address != address)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
overlapsList.Add(overlap);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return overlapsList.ToArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
private int BinarySearch(ulong address)
|
|
||||||
{
|
|
||||||
int left = 0;
|
|
||||||
int right = _items.Count - 1;
|
|
||||||
|
|
||||||
while (left <= right)
|
|
||||||
{
|
|
||||||
int range = right - left;
|
|
||||||
|
|
||||||
int middle = left + (range >> 1);
|
|
||||||
|
|
||||||
T item = _items[middle];
|
|
||||||
|
|
||||||
if (item.Address == address)
|
|
||||||
{
|
|
||||||
return middle;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (address < item.Address)
|
|
||||||
{
|
|
||||||
right = middle - 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
left = middle + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ~left;
|
|
||||||
}
|
|
||||||
|
|
||||||
private int BinarySearch(ulong address, ulong size)
|
|
||||||
{
|
|
||||||
int left = 0;
|
|
||||||
int right = _items.Count - 1;
|
|
||||||
|
|
||||||
while (left <= right)
|
|
||||||
{
|
|
||||||
int range = right - left;
|
|
||||||
|
|
||||||
int middle = left + (range >> 1);
|
|
||||||
|
|
||||||
T item = _items[middle];
|
|
||||||
|
|
||||||
if (item.OverlapsWith(address, size))
|
|
||||||
{
|
|
||||||
return middle;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (address < item.Address)
|
|
||||||
{
|
|
||||||
right = middle - 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
left = middle + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ~left;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
94
Ryujinx.Graphics.Gpu/Window.cs
Normal file
94
Ryujinx.Graphics.Gpu/Window.cs
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
using Ryujinx.Graphics.GAL;
|
||||||
|
using Ryujinx.Graphics.GAL.Texture;
|
||||||
|
using Ryujinx.Graphics.Gpu.Image;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
|
|
||||||
|
namespace Ryujinx.Graphics.Gpu
|
||||||
|
{
|
||||||
|
public class Window
|
||||||
|
{
|
||||||
|
private GpuContext _context;
|
||||||
|
|
||||||
|
private struct PresentationTexture
|
||||||
|
{
|
||||||
|
public TextureInfo Info { get; }
|
||||||
|
public ImageCrop Crop { get; }
|
||||||
|
public Action<object> Callback { get; }
|
||||||
|
public object UserObj { get; }
|
||||||
|
|
||||||
|
public PresentationTexture(
|
||||||
|
TextureInfo info,
|
||||||
|
ImageCrop crop,
|
||||||
|
Action<object> callback,
|
||||||
|
object userObj)
|
||||||
|
{
|
||||||
|
Info = info;
|
||||||
|
Crop = crop;
|
||||||
|
Callback = callback;
|
||||||
|
UserObj = userObj;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ConcurrentQueue<PresentationTexture> _frameQueue;
|
||||||
|
|
||||||
|
public Window(GpuContext context)
|
||||||
|
{
|
||||||
|
_context = context;
|
||||||
|
|
||||||
|
_frameQueue = new ConcurrentQueue<PresentationTexture>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void EnqueueFrameThreadSafe(
|
||||||
|
ulong address,
|
||||||
|
int width,
|
||||||
|
int height,
|
||||||
|
int stride,
|
||||||
|
bool isLinear,
|
||||||
|
int gobBlocksInY,
|
||||||
|
Format format,
|
||||||
|
int bytesPerPixel,
|
||||||
|
ImageCrop crop,
|
||||||
|
Action<object> callback,
|
||||||
|
object userObj)
|
||||||
|
{
|
||||||
|
FormatInfo formatInfo = new FormatInfo(format, 1, 1, bytesPerPixel);
|
||||||
|
|
||||||
|
TextureInfo info = new TextureInfo(
|
||||||
|
address,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
stride,
|
||||||
|
isLinear,
|
||||||
|
gobBlocksInY,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
Target.Texture2D,
|
||||||
|
formatInfo);
|
||||||
|
|
||||||
|
_frameQueue.Enqueue(new PresentationTexture(info, crop, callback, userObj));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Present(Action swapBuffersCallback)
|
||||||
|
{
|
||||||
|
_context.AdvanceSequence();
|
||||||
|
|
||||||
|
if (_frameQueue.TryDequeue(out PresentationTexture pt))
|
||||||
|
{
|
||||||
|
Image.Texture texture = _context.Methods.TextureManager.FindOrCreateTexture(pt.Info);
|
||||||
|
|
||||||
|
texture.SynchronizeMemory();
|
||||||
|
|
||||||
|
_context.Renderer.Window.Present(texture.HostTexture, pt.Crop);
|
||||||
|
|
||||||
|
swapBuffersCallback();
|
||||||
|
|
||||||
|
pt.Callback(pt.UserObj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +1,6 @@
|
||||||
using OpenTK.Graphics.OpenGL;
|
using OpenTK.Graphics.OpenGL;
|
||||||
using Ryujinx.Graphics.GAL;
|
using Ryujinx.Graphics.GAL;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.OpenGL
|
namespace Ryujinx.Graphics.OpenGL
|
||||||
{
|
{
|
||||||
|
@ -13,53 +12,19 @@ namespace Ryujinx.Graphics.OpenGL
|
||||||
private int _width;
|
private int _width;
|
||||||
private int _height;
|
private int _height;
|
||||||
|
|
||||||
private int _resizeWidth;
|
|
||||||
private int _resizeHeight;
|
|
||||||
|
|
||||||
private bool _sizeChanged;
|
|
||||||
|
|
||||||
private object _resizeLocker;
|
|
||||||
|
|
||||||
private int _blitFramebufferHandle;
|
|
||||||
private int _copyFramebufferHandle;
|
private int _copyFramebufferHandle;
|
||||||
|
|
||||||
private int _screenTextureHandle;
|
|
||||||
|
|
||||||
private TextureReleaseCallback _release;
|
|
||||||
|
|
||||||
private struct PresentationTexture
|
|
||||||
{
|
|
||||||
public TextureView Texture { get; }
|
|
||||||
|
|
||||||
public ImageCrop Crop { get; }
|
|
||||||
|
|
||||||
public object Context { get; }
|
|
||||||
|
|
||||||
public PresentationTexture(TextureView texture, ImageCrop crop, object context)
|
|
||||||
{
|
|
||||||
Texture = texture;
|
|
||||||
Crop = crop;
|
|
||||||
Context = context;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Queue<PresentationTexture> _textures;
|
|
||||||
|
|
||||||
public Window()
|
public Window()
|
||||||
{
|
{
|
||||||
_width = NativeWidth;
|
_width = NativeWidth;
|
||||||
_height = NativeHeight;
|
_height = NativeHeight;
|
||||||
|
|
||||||
_resizeLocker = new object();
|
|
||||||
|
|
||||||
_textures = new Queue<PresentationTexture>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Present()
|
public void Present(ITexture texture, ImageCrop crop)
|
||||||
{
|
{
|
||||||
GL.Disable(EnableCap.FramebufferSrgb);
|
TextureView view = (TextureView)texture;
|
||||||
|
|
||||||
CopyTextureFromQueue();
|
GL.Disable(EnableCap.FramebufferSrgb);
|
||||||
|
|
||||||
int oldReadFramebufferHandle = GL.GetInteger(GetPName.ReadFramebufferBinding);
|
int oldReadFramebufferHandle = GL.GetInteger(GetPName.ReadFramebufferBinding);
|
||||||
int oldDrawFramebufferHandle = GL.GetInteger(GetPName.DrawFramebufferBinding);
|
int oldDrawFramebufferHandle = GL.GetInteger(GetPName.DrawFramebufferBinding);
|
||||||
|
@ -67,52 +32,10 @@ namespace Ryujinx.Graphics.OpenGL
|
||||||
GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, 0);
|
GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, 0);
|
||||||
GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, GetCopyFramebufferHandleLazy());
|
GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, GetCopyFramebufferHandleLazy());
|
||||||
|
|
||||||
GL.ReadBuffer(ReadBufferMode.ColorAttachment0);
|
|
||||||
|
|
||||||
GL.Clear(ClearBufferMask.ColorBufferBit);
|
|
||||||
|
|
||||||
int windowWidth = _width;
|
|
||||||
int windowHeight = _height;
|
|
||||||
|
|
||||||
GL.BlitFramebuffer(
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
windowWidth,
|
|
||||||
windowHeight,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
windowWidth,
|
|
||||||
windowHeight,
|
|
||||||
ClearBufferMask.ColorBufferBit,
|
|
||||||
BlitFramebufferFilter.Linear);
|
|
||||||
|
|
||||||
GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, oldReadFramebufferHandle);
|
|
||||||
GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, oldDrawFramebufferHandle);
|
|
||||||
|
|
||||||
GL.Enable(EnableCap.FramebufferSrgb);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void CopyTextureFromQueue()
|
|
||||||
{
|
|
||||||
if (!_textures.TryDequeue(out PresentationTexture presentationTexture))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
TextureView texture = presentationTexture.Texture;
|
|
||||||
ImageCrop crop = presentationTexture.Crop;
|
|
||||||
object context = presentationTexture.Context;
|
|
||||||
|
|
||||||
int oldReadFramebufferHandle = GL.GetInteger(GetPName.ReadFramebufferBinding);
|
|
||||||
int oldDrawFramebufferHandle = GL.GetInteger(GetPName.DrawFramebufferBinding);
|
|
||||||
|
|
||||||
GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, GetCopyFramebufferHandleLazy());
|
|
||||||
GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, GetBlitFramebufferHandleLazy());
|
|
||||||
|
|
||||||
GL.FramebufferTexture(
|
GL.FramebufferTexture(
|
||||||
FramebufferTarget.ReadFramebuffer,
|
FramebufferTarget.ReadFramebuffer,
|
||||||
FramebufferAttachment.ColorAttachment0,
|
FramebufferAttachment.ColorAttachment0,
|
||||||
texture.Handle,
|
view.Handle,
|
||||||
0);
|
0);
|
||||||
|
|
||||||
GL.ReadBuffer(ReadBufferMode.ColorAttachment0);
|
GL.ReadBuffer(ReadBufferMode.ColorAttachment0);
|
||||||
|
@ -124,7 +47,7 @@ namespace Ryujinx.Graphics.OpenGL
|
||||||
if (crop.Left == 0 && crop.Right == 0)
|
if (crop.Left == 0 && crop.Right == 0)
|
||||||
{
|
{
|
||||||
srcX0 = 0;
|
srcX0 = 0;
|
||||||
srcX1 = texture.Width;
|
srcX1 = view.Width;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -135,7 +58,7 @@ namespace Ryujinx.Graphics.OpenGL
|
||||||
if (crop.Top == 0 && crop.Bottom == 0)
|
if (crop.Top == 0 && crop.Bottom == 0)
|
||||||
{
|
{
|
||||||
srcY0 = 0;
|
srcY0 = 0;
|
||||||
srcY1 = texture.Height;
|
srcY1 = view.Height;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -173,128 +96,27 @@ namespace Ryujinx.Graphics.OpenGL
|
||||||
GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, oldReadFramebufferHandle);
|
GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, oldReadFramebufferHandle);
|
||||||
GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, oldDrawFramebufferHandle);
|
GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, oldDrawFramebufferHandle);
|
||||||
|
|
||||||
texture.Release();
|
GL.Enable(EnableCap.FramebufferSrgb);
|
||||||
|
|
||||||
Release(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void QueueTexture(ITexture texture, ImageCrop crop, object context)
|
|
||||||
{
|
|
||||||
if (texture == null)
|
|
||||||
{
|
|
||||||
Release(context);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
TextureView textureView = (TextureView)texture;
|
|
||||||
|
|
||||||
textureView.Acquire();
|
|
||||||
|
|
||||||
_textures.Enqueue(new PresentationTexture(textureView, crop, context));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void RegisterTextureReleaseCallback(TextureReleaseCallback callback)
|
|
||||||
{
|
|
||||||
_release = callback;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetSize(int width, int height)
|
public void SetSize(int width, int height)
|
||||||
{
|
{
|
||||||
lock (_resizeLocker)
|
_width = width;
|
||||||
{
|
_height = height;
|
||||||
_resizeWidth = width;
|
|
||||||
_resizeHeight = height;
|
|
||||||
|
|
||||||
_sizeChanged = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Release(object context)
|
|
||||||
{
|
|
||||||
if (_release != null)
|
|
||||||
{
|
|
||||||
_release(context);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private int GetBlitFramebufferHandleLazy()
|
|
||||||
{
|
|
||||||
int handle = _blitFramebufferHandle;
|
|
||||||
|
|
||||||
if (handle == 0)
|
|
||||||
{
|
|
||||||
handle = GL.GenFramebuffer();
|
|
||||||
|
|
||||||
_blitFramebufferHandle = handle;
|
|
||||||
}
|
|
||||||
|
|
||||||
return handle;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private int GetCopyFramebufferHandleLazy()
|
private int GetCopyFramebufferHandleLazy()
|
||||||
{
|
{
|
||||||
int handle = _copyFramebufferHandle;
|
int handle = _copyFramebufferHandle;
|
||||||
|
|
||||||
void GenerateAndBindTexture()
|
|
||||||
{
|
|
||||||
int textureHandle = GenerateWindowTexture();
|
|
||||||
|
|
||||||
GL.BindFramebuffer(FramebufferTarget.Framebuffer, handle);
|
|
||||||
|
|
||||||
GL.FramebufferTexture(
|
|
||||||
FramebufferTarget.Framebuffer,
|
|
||||||
FramebufferAttachment.ColorAttachment0,
|
|
||||||
textureHandle,
|
|
||||||
0);
|
|
||||||
|
|
||||||
_screenTextureHandle = textureHandle;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (handle == 0)
|
if (handle == 0)
|
||||||
{
|
{
|
||||||
handle = GL.GenFramebuffer();
|
handle = GL.GenFramebuffer();
|
||||||
|
|
||||||
_copyFramebufferHandle = handle;
|
_copyFramebufferHandle = handle;
|
||||||
|
|
||||||
GenerateAndBindTexture();
|
|
||||||
}
|
|
||||||
else if (_sizeChanged)
|
|
||||||
{
|
|
||||||
GL.DeleteTexture(_screenTextureHandle);
|
|
||||||
|
|
||||||
lock (_resizeLocker)
|
|
||||||
{
|
|
||||||
_width = _resizeWidth;
|
|
||||||
_height = _resizeHeight;
|
|
||||||
|
|
||||||
_sizeChanged = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
GenerateAndBindTexture();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return handle;
|
return handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int GenerateWindowTexture()
|
|
||||||
{
|
|
||||||
int handle = GL.GenTexture();
|
|
||||||
|
|
||||||
GL.BindTexture(TextureTarget.Texture2D, handle);
|
|
||||||
|
|
||||||
GL.TexImage2D(
|
|
||||||
TextureTarget.Texture2D,
|
|
||||||
0,
|
|
||||||
PixelInternalFormat.Rgba8,
|
|
||||||
_width,
|
|
||||||
_height,
|
|
||||||
0,
|
|
||||||
PixelFormat.Rgba,
|
|
||||||
PixelType.UnsignedByte,
|
|
||||||
IntPtr.Zero);
|
|
||||||
|
|
||||||
return handle;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.Graphics.GAL;
|
using Ryujinx.Graphics.GAL;
|
||||||
|
using Ryujinx.Graphics.Gpu;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Threading;
|
using Ryujinx.HLE.HOS.Kernel.Threading;
|
||||||
using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostAsGpu;
|
|
||||||
using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvMap;
|
using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvMap;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
@ -295,11 +295,6 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
|
||||||
|
|
||||||
_bufferQueue[slot].State = BufferState.Acquired;
|
_bufferQueue[slot].State = BufferState.Acquired;
|
||||||
|
|
||||||
Rect crop = _bufferQueue[slot].Crop;
|
|
||||||
|
|
||||||
bool flipX = _bufferQueue[slot].Transform.HasFlag(HalTransform.FlipX);
|
|
||||||
bool flipY = _bufferQueue[slot].Transform.HasFlag(HalTransform.FlipY);
|
|
||||||
|
|
||||||
Format format = ConvertColorFormat(_bufferQueue[slot].Data.Buffer.Surfaces[0].ColorFormat);
|
Format format = ConvertColorFormat(_bufferQueue[slot].Data.Buffer.Surfaces[0].ColorFormat);
|
||||||
|
|
||||||
int bytesPerPixel =
|
int bytesPerPixel =
|
||||||
|
@ -310,7 +305,20 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
|
||||||
|
|
||||||
// Note: Rotation is being ignored.
|
// Note: Rotation is being ignored.
|
||||||
|
|
||||||
ITexture texture = context.Device.Gpu.GetTexture(
|
Rect cropRect = _bufferQueue[slot].Crop;
|
||||||
|
|
||||||
|
bool flipX = _bufferQueue[slot].Transform.HasFlag(HalTransform.FlipX);
|
||||||
|
bool flipY = _bufferQueue[slot].Transform.HasFlag(HalTransform.FlipY);
|
||||||
|
|
||||||
|
ImageCrop crop = new ImageCrop(
|
||||||
|
cropRect.Left,
|
||||||
|
cropRect.Right,
|
||||||
|
cropRect.Top,
|
||||||
|
cropRect.Bottom,
|
||||||
|
flipX,
|
||||||
|
flipY);
|
||||||
|
|
||||||
|
context.Device.Gpu.Window.EnqueueFrameThreadSafe(
|
||||||
fbAddr,
|
fbAddr,
|
||||||
fbWidth,
|
fbWidth,
|
||||||
fbHeight,
|
fbHeight,
|
||||||
|
@ -318,24 +326,15 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
|
||||||
false,
|
false,
|
||||||
gobBlocksInY,
|
gobBlocksInY,
|
||||||
format,
|
format,
|
||||||
bytesPerPixel);
|
bytesPerPixel,
|
||||||
|
crop,
|
||||||
_renderer.Window.RegisterTextureReleaseCallback(ReleaseBuffer);
|
ReleaseBuffer,
|
||||||
|
slot);
|
||||||
ImageCrop imageCrop = new ImageCrop(
|
|
||||||
crop.Left,
|
|
||||||
crop.Right,
|
|
||||||
crop.Top,
|
|
||||||
crop.Bottom,
|
|
||||||
flipX,
|
|
||||||
flipY);
|
|
||||||
|
|
||||||
_renderer.Window.QueueTexture(texture, imageCrop, slot);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ReleaseBuffer(object context)
|
private void ReleaseBuffer(object slot)
|
||||||
{
|
{
|
||||||
ReleaseBuffer((int)context);
|
ReleaseBuffer((int)slot);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ReleaseBuffer(int slot)
|
private void ReleaseBuffer(int slot)
|
||||||
|
|
|
@ -122,6 +122,11 @@ namespace Ryujinx.HLE
|
||||||
Gpu.DmaPusher.DispatchCalls();
|
Gpu.DmaPusher.DispatchCalls();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void PresentFrame(Action swapBuffersCallback)
|
||||||
|
{
|
||||||
|
Gpu.Window.Present(swapBuffersCallback);
|
||||||
|
}
|
||||||
|
|
||||||
internal void Unload()
|
internal void Unload()
|
||||||
{
|
{
|
||||||
FileSystem.Dispose();
|
FileSystem.Dispose();
|
||||||
|
|
|
@ -294,7 +294,7 @@ namespace Ryujinx.Ui
|
||||||
|
|
||||||
private new void RenderFrame()
|
private new void RenderFrame()
|
||||||
{
|
{
|
||||||
_renderer.Window.Present();
|
_device.PresentFrame(SwapBuffers);
|
||||||
|
|
||||||
_device.Statistics.RecordSystemFrameTime();
|
_device.Statistics.RecordSystemFrameTime();
|
||||||
|
|
||||||
|
@ -312,8 +312,6 @@ namespace Ryujinx.Ui
|
||||||
|
|
||||||
_titleEvent = true;
|
_titleEvent = true;
|
||||||
|
|
||||||
SwapBuffers();
|
|
||||||
|
|
||||||
_device.System.SignalVsync();
|
_device.System.SignalVsync();
|
||||||
|
|
||||||
_device.VsyncEvent.Set();
|
_device.VsyncEvent.Set();
|
||||||
|
|
Reference in a new issue