prep work for easier OpenGL interop for cores
This commit is contained in:
parent
78f5e75534
commit
8ae947fed7
|
@ -159,7 +159,7 @@ namespace BizHawk.Bizware.BizwareGL
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// In case you already have the texture ID (from an opengl emulator gpu core) you can get a Texture2d with it this way.
|
/// In case you already have the texture ID (from an opengl emulator gpu core) you can get a Texture2d with it this way.
|
||||||
/// Otherwise, if this isn't an OpenGL frontend implementation, I guess... try reading the texturedata out of it and making a new texture?
|
/// Otherwise, if this isn't an OpenGL frontend implementation, the core is expected to readback the texture for GetVideoBuffer()
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Texture2d WrapGLTexture2d(IntPtr glTexId, int width, int height);
|
Texture2d WrapGLTexture2d(IntPtr glTexId, int width, int height);
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,6 @@ namespace BizHawk.Bizware.BizwareGL
|
||||||
Owner = owner;
|
Owner = owner;
|
||||||
Opaque = opaque;
|
Opaque = opaque;
|
||||||
Texture2d = tex;
|
Texture2d = tex;
|
||||||
tex.IsUpsideDown = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
|
|
|
@ -683,8 +683,7 @@ namespace BizHawk.Bizware.Graphics
|
||||||
|
|
||||||
public Texture2d WrapGLTexture2d(IntPtr glTexId, int width, int height)
|
public Texture2d WrapGLTexture2d(IntPtr glTexId, int width, int height)
|
||||||
{
|
{
|
||||||
// not needed 1st pass (except for GL cores)
|
// only used for OpenGL
|
||||||
// TODO - need to rip the texture data. we had code for that somewhere...
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,10 +37,7 @@ namespace BizHawk.Bizware.Graphics
|
||||||
{
|
{
|
||||||
public EDispMethod DispMethodEnum => EDispMethod.OpenGL;
|
public EDispMethod DispMethodEnum => EDispMethod.OpenGL;
|
||||||
|
|
||||||
private readonly SDL2OpenGLContext OffscreenContext;
|
private readonly GL GL;
|
||||||
private SDL2OpenGLContext ActiveContext;
|
|
||||||
private GL GL => ActiveContext.GL;
|
|
||||||
|
|
||||||
private readonly int _majorVersion, _minorVersion;
|
private readonly int _majorVersion, _minorVersion;
|
||||||
private readonly bool _forwardCompatible;
|
private readonly bool _forwardCompatible;
|
||||||
|
|
||||||
|
@ -50,36 +47,20 @@ namespace BizHawk.Bizware.Graphics
|
||||||
|
|
||||||
public string API => "OPENGL";
|
public string API => "OPENGL";
|
||||||
|
|
||||||
public int Version
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
// doesnt work on older than gl3 maybe
|
|
||||||
// int major, minor;
|
|
||||||
// // other overloads may not exist...
|
|
||||||
// GL.GetInteger(GetPName.MajorVersion, out major);
|
|
||||||
// GL.GetInteger(GetPName.MinorVersion, out minor);
|
|
||||||
|
|
||||||
// supposedly the standard dictates that whatever junk is in the version string, some kind of version is at the beginning
|
|
||||||
// can be either in major_number.minor_number or major_number.minor_number.release_number, with vendor specific info afterwards
|
|
||||||
var versionString = GL.GetStringS(StringName.Version);
|
|
||||||
var versionParts = versionString.Split('.');
|
|
||||||
var major = int.Parse(versionParts[0]);
|
|
||||||
var minor = int.Parse(versionParts[1][0].ToString());
|
|
||||||
// getting a release number is too hard and not needed now
|
|
||||||
return major * 100 + minor * 10;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public IGL_OpenGL(int majorVersion, int minorVersion, bool forwardCompatible)
|
public IGL_OpenGL(int majorVersion, int minorVersion, bool forwardCompatible)
|
||||||
{
|
{
|
||||||
// create an offscreen context, so things can be done without a control
|
|
||||||
ActiveContext = OffscreenContext = new(majorVersion, minorVersion, forwardCompatible);
|
|
||||||
|
|
||||||
_majorVersion = majorVersion;
|
_majorVersion = majorVersion;
|
||||||
_minorVersion = minorVersion;
|
_minorVersion = minorVersion;
|
||||||
_forwardCompatible = forwardCompatible;
|
_forwardCompatible = forwardCompatible;
|
||||||
|
|
||||||
|
// we need an active context in order to acquire these functions
|
||||||
|
// technically, they could be different between contexts
|
||||||
|
// but with the exact same requested version and config that is highly unlikely in practice
|
||||||
|
using (new SDL2OpenGLContext(majorVersion, minorVersion, forwardCompatible))
|
||||||
|
{
|
||||||
|
GL = GL.GetApi(SDL2OpenGLContext.GetGLProcAddress);
|
||||||
|
}
|
||||||
|
|
||||||
// misc initialization
|
// misc initialization
|
||||||
CreateRenderStates();
|
CreateRenderStates();
|
||||||
}
|
}
|
||||||
|
@ -94,7 +75,6 @@ namespace BizHawk.Bizware.Graphics
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
OffscreenContext.Dispose();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Clear(BizClearBufferMask mask)
|
public void Clear(BizClearBufferMask mask)
|
||||||
|
@ -477,7 +457,7 @@ namespace BizHawk.Bizware.Graphics
|
||||||
|
|
||||||
public Texture2d WrapGLTexture2d(IntPtr glTexId, int width, int height)
|
public Texture2d WrapGLTexture2d(IntPtr glTexId, int width, int height)
|
||||||
{
|
{
|
||||||
return new(this, glTexId.ToInt32(), width, height);
|
return new(this, (uint)glTexId.ToInt32(), width, height) { IsUpsideDown = true };
|
||||||
}
|
}
|
||||||
|
|
||||||
public unsafe void LoadTextureData(Texture2d tex, BitmapBuffer bmp)
|
public unsafe void LoadTextureData(Texture2d tex, BitmapBuffer bmp)
|
||||||
|
@ -505,7 +485,7 @@ namespace BizHawk.Bizware.Graphics
|
||||||
{
|
{
|
||||||
// create a texture for it
|
// create a texture for it
|
||||||
var texId = GenTexture();
|
var texId = GenTexture();
|
||||||
var tex = new Texture2d(this, texId, w, h);
|
var tex = new Texture2d(this, texId, w, h) { IsUpsideDown = true }; // TODO: The IsUpsideDown doesn't ever get used here it seems
|
||||||
|
|
||||||
GL.BindTexture(TextureTarget.Texture2D, texId);
|
GL.BindTexture(TextureTarget.Texture2D, texId);
|
||||||
GL.TexImage2D(TextureTarget.Texture2D, 0, InternalFormat.Rgba8, (uint)w, (uint)h, 0, PixelFormat.Bgra, PixelType.UnsignedByte, IntPtr.Zero.ToPointer());
|
GL.TexImage2D(TextureTarget.Texture2D, 0, InternalFormat.Rgba8, (uint)w, (uint)h, 0, PixelFormat.Bgra, PixelType.UnsignedByte, IntPtr.Zero.ToPointer());
|
||||||
|
@ -839,26 +819,11 @@ namespace BizHawk.Bizware.Graphics
|
||||||
private VertexLayout sStatePendingVertexLayout;
|
private VertexLayout sStatePendingVertexLayout;
|
||||||
private readonly HashSet<uint> sVertexAttribEnables = new();
|
private readonly HashSet<uint> sVertexAttribEnables = new();
|
||||||
|
|
||||||
private void ContextChangeCallback(SDL2OpenGLContext context)
|
private void ContextChangeCallback()
|
||||||
{
|
{
|
||||||
// null means the current context is being cleared
|
|
||||||
// set it back to the offscreen context
|
|
||||||
if (context is null)
|
|
||||||
{
|
|
||||||
OffscreenContext.MakeContextCurrent();
|
|
||||||
context = OffscreenContext;
|
|
||||||
}
|
|
||||||
|
|
||||||
sActiveTexture = -1;
|
sActiveTexture = -1;
|
||||||
sStatePendingVertexLayout = null;
|
sStatePendingVertexLayout = null;
|
||||||
sVertexAttribEnables.Clear();
|
sVertexAttribEnables.Clear();
|
||||||
ActiveContext = context;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void MakeOffscreenContextCurrent()
|
|
||||||
{
|
|
||||||
OffscreenContext.MakeContextCurrent();
|
|
||||||
ContextChangeCallback(OffscreenContext);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ namespace BizHawk.Bizware.Graphics
|
||||||
private readonly int _majorVersion;
|
private readonly int _majorVersion;
|
||||||
private readonly int _minorVersion;
|
private readonly int _minorVersion;
|
||||||
private readonly bool _forwardCompatible;
|
private readonly bool _forwardCompatible;
|
||||||
private readonly Action<SDL2OpenGLContext> _contextChangeCallback;
|
private readonly Action _contextChangeCallback;
|
||||||
|
|
||||||
public SDL2OpenGLContext Context { get; private set; }
|
public SDL2OpenGLContext Context { get; private set; }
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ namespace BizHawk.Bizware.Graphics
|
||||||
set => throw new NotImplementedException();
|
set => throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public OpenGLControl(int majorVersion, int minorVersion, bool forwardCompatible, Action<SDL2OpenGLContext> contextChangeCallback)
|
public OpenGLControl(int majorVersion, int minorVersion, bool forwardCompatible, Action contextChangeCallback)
|
||||||
{
|
{
|
||||||
_majorVersion = majorVersion;
|
_majorVersion = majorVersion;
|
||||||
_minorVersion = minorVersion;
|
_minorVersion = minorVersion;
|
||||||
|
@ -59,8 +59,7 @@ namespace BizHawk.Bizware.Graphics
|
||||||
{
|
{
|
||||||
base.OnHandleCreated(e);
|
base.OnHandleCreated(e);
|
||||||
Context = new(Handle, _majorVersion, _minorVersion, _forwardCompatible);
|
Context = new(Handle, _majorVersion, _minorVersion, _forwardCompatible);
|
||||||
|
_contextChangeCallback();
|
||||||
_contextChangeCallback(Context);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnHandleDestroyed(EventArgs e)
|
protected override void OnHandleDestroyed(EventArgs e)
|
||||||
|
@ -69,7 +68,7 @@ namespace BizHawk.Bizware.Graphics
|
||||||
|
|
||||||
if (Context.IsCurrent)
|
if (Context.IsCurrent)
|
||||||
{
|
{
|
||||||
_contextChangeCallback(null);
|
_contextChangeCallback();
|
||||||
}
|
}
|
||||||
|
|
||||||
Context.Dispose();
|
Context.Dispose();
|
||||||
|
@ -92,7 +91,7 @@ namespace BizHawk.Bizware.Graphics
|
||||||
if (!Context.IsCurrent)
|
if (!Context.IsCurrent)
|
||||||
{
|
{
|
||||||
Context.MakeContextCurrent();
|
Context.MakeContextCurrent();
|
||||||
_contextChangeCallback(Context);
|
_contextChangeCallback();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -110,7 +109,8 @@ namespace BizHawk.Bizware.Graphics
|
||||||
|
|
||||||
public void End()
|
public void End()
|
||||||
{
|
{
|
||||||
_contextChangeCallback(null);
|
SDL2OpenGLContext.MakeNoneCurrent();
|
||||||
|
_contextChangeCallback();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SwapBuffers()
|
public void SwapBuffers()
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
using Silk.NET.OpenGL.Legacy;
|
|
||||||
|
|
||||||
using static SDL2.SDL;
|
using static SDL2.SDL;
|
||||||
|
|
||||||
|
@ -9,7 +8,7 @@ namespace BizHawk.Bizware.Graphics
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Wraps an SDL2 OpenGL context
|
/// Wraps an SDL2 OpenGL context
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal class SDL2OpenGLContext : IDisposable
|
public class SDL2OpenGLContext : IDisposable
|
||||||
{
|
{
|
||||||
static SDL2OpenGLContext()
|
static SDL2OpenGLContext()
|
||||||
{
|
{
|
||||||
|
@ -41,11 +40,50 @@ namespace BizHawk.Bizware.Graphics
|
||||||
SDL_SetHint(SDL_HINT_VIDEO_FOREIGN_WINDOW_OPENGL, "1");
|
SDL_SetHint(SDL_HINT_VIDEO_FOREIGN_WINDOW_OPENGL, "1");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedFunctionPointer(CallingConvention.Winapi)]
|
||||||
|
private delegate IntPtr glGetStringDelegate(int name);
|
||||||
|
|
||||||
|
private static readonly Lazy<int> _version = new(() =>
|
||||||
|
{
|
||||||
|
var prevWindow = SDL_GL_GetCurrentWindow();
|
||||||
|
var prevContext = SDL_GL_GetCurrentContext();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (new SDL2OpenGLContext(2, 0, false))
|
||||||
|
{
|
||||||
|
var getStringFp = GetGLProcAddress("glGetString");
|
||||||
|
if (getStringFp == IntPtr.Zero) // uhhh?
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
var getStringFunc = Marshal.GetDelegateForFunctionPointer<glGetStringDelegate>(getStringFp);
|
||||||
|
const int GL_VERSION = 0x1F02;
|
||||||
|
var version = getStringFunc(GL_VERSION);
|
||||||
|
if (version == IntPtr.Zero)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
var versionString = Marshal.PtrToStringAnsi(version);
|
||||||
|
var versionParts = versionString!.Split('.');
|
||||||
|
var major = int.Parse(versionParts[0]);
|
||||||
|
var minor = int.Parse(versionParts[1][0].ToString());
|
||||||
|
return major * 100 + minor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
SDL_GL_MakeCurrent(prevWindow, prevContext);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
public static int Version => _version.Value;
|
||||||
|
|
||||||
private IntPtr _sdlWindow;
|
private IntPtr _sdlWindow;
|
||||||
private IntPtr _glContext;
|
private IntPtr _glContext;
|
||||||
|
|
||||||
public GL GL { get; private set; }
|
|
||||||
|
|
||||||
private void CreateContext(int majorVersion, int minorVersion, bool forwardCompatible)
|
private void CreateContext(int majorVersion, int minorVersion, bool forwardCompatible)
|
||||||
{
|
{
|
||||||
if (SDL_GL_SetAttribute(SDL_GLattr.SDL_GL_CONTEXT_MAJOR_VERSION, majorVersion) != 0)
|
if (SDL_GL_SetAttribute(SDL_GLattr.SDL_GL_CONTEXT_MAJOR_VERSION, majorVersion) != 0)
|
||||||
|
@ -80,10 +118,6 @@ namespace BizHawk.Bizware.Graphics
|
||||||
{
|
{
|
||||||
throw new($"Could not create GL Context! SDL Error: {SDL_GetError()}");
|
throw new($"Could not create GL Context! SDL Error: {SDL_GetError()}");
|
||||||
}
|
}
|
||||||
|
|
||||||
// get GL functions
|
|
||||||
// these are specific towards a context, and so these are owned by the context here
|
|
||||||
GL = GL.GetApi(SDL_GL_GetProcAddress);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public SDL2OpenGLContext(IntPtr nativeWindowhandle, int majorVersion, int minorVersion, bool forwardCompatible)
|
public SDL2OpenGLContext(IntPtr nativeWindowhandle, int majorVersion, int minorVersion, bool forwardCompatible)
|
||||||
|
@ -146,6 +180,15 @@ namespace BizHawk.Bizware.Graphics
|
||||||
_ = SDL_GL_MakeCurrent(_sdlWindow, _glContext);
|
_ = SDL_GL_MakeCurrent(_sdlWindow, _glContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void MakeNoneCurrent()
|
||||||
|
{
|
||||||
|
// no-op if nothing is current
|
||||||
|
_ = SDL_GL_MakeCurrent(IntPtr.Zero, IntPtr.Zero);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IntPtr GetGLProcAddress(string proc)
|
||||||
|
=> SDL_GL_GetProcAddress(proc);
|
||||||
|
|
||||||
public void SetVsync(bool state)
|
public void SetVsync(bool state)
|
||||||
{
|
{
|
||||||
if (!IsCurrent)
|
if (!IsCurrent)
|
||||||
|
|
|
@ -196,7 +196,9 @@ namespace BizHawk.Client.Common
|
||||||
|
|
||||||
private RetroShaderChain _shaderChainUser;
|
private RetroShaderChain _shaderChainUser;
|
||||||
|
|
||||||
protected virtual void ActivateGLContext() => throw new NotImplementedException();
|
public virtual void ActivateOpenGLContext() => throw new NotImplementedException();
|
||||||
|
|
||||||
|
protected virtual void ActivateGraphicsControlContext() => throw new NotImplementedException();
|
||||||
|
|
||||||
protected virtual void SwapBuffersOfGraphicsControl() => throw new NotImplementedException();
|
protected virtual void SwapBuffersOfGraphicsControl() => throw new NotImplementedException();
|
||||||
|
|
||||||
|
@ -771,12 +773,10 @@ namespace BizHawk.Client.Common
|
||||||
|
|
||||||
private FilterProgram UpdateSourceInternal(JobInfo job)
|
private FilterProgram UpdateSourceInternal(JobInfo job)
|
||||||
{
|
{
|
||||||
//no drawing actually happens. it's important not to begin drawing on a control
|
// no drawing actually happens
|
||||||
if (!job.Simulate/* && !job.Offscreen*/)
|
if (!job.Simulate)
|
||||||
{
|
{
|
||||||
// i don't want to do this for offscreen jobs
|
ActivateGraphicsControlContext();
|
||||||
// but it seems that would be required in case this context isn't active
|
|
||||||
ActivateGLContext();
|
|
||||||
|
|
||||||
if (job.ChainOutsize.Width == 0 || job.ChainOutsize.Height == 0)
|
if (job.ChainOutsize.Width == 0 || job.ChainOutsize.Height == 0)
|
||||||
{
|
{
|
||||||
|
@ -791,17 +791,14 @@ namespace BizHawk.Client.Common
|
||||||
}
|
}
|
||||||
|
|
||||||
var videoProvider = job.VideoProvider;
|
var videoProvider = job.VideoProvider;
|
||||||
|
var glTextureProvider = videoProvider as IGLTextureProvider;
|
||||||
var simulate = job.Simulate;
|
var simulate = job.Simulate;
|
||||||
var chainOutsize = job.ChainOutsize;
|
var chainOutsize = job.ChainOutsize;
|
||||||
|
|
||||||
//simulate = true;
|
|
||||||
|
|
||||||
var videoBuffer = videoProvider.GetVideoBuffer();
|
|
||||||
var bufferWidth = videoProvider.BufferWidth;
|
var bufferWidth = videoProvider.BufferWidth;
|
||||||
var bufferHeight = videoProvider.BufferHeight;
|
var bufferHeight = videoProvider.BufferHeight;
|
||||||
var presenterTextureWidth = bufferWidth;
|
var presenterTextureWidth = bufferWidth;
|
||||||
var presenterTextureHeight = bufferHeight;
|
var presenterTextureHeight = bufferHeight;
|
||||||
var isGlTextureId = videoBuffer.Length == 1;
|
|
||||||
|
|
||||||
var vw = videoProvider.VirtualWidth;
|
var vw = videoProvider.VirtualWidth;
|
||||||
var vh = videoProvider.VirtualHeight;
|
var vh = videoProvider.VirtualHeight;
|
||||||
|
@ -854,23 +851,22 @@ namespace BizHawk.Client.Common
|
||||||
Texture2d videoTexture = null;
|
Texture2d videoTexture = null;
|
||||||
if (!simulate)
|
if (!simulate)
|
||||||
{
|
{
|
||||||
if (isGlTextureId)
|
if (glTextureProvider != null && _gl.DispMethodEnum == EDispMethod.OpenGL)
|
||||||
{
|
{
|
||||||
// FYI: this is a million years from happening on n64, since it's all geriatric non-FBO code
|
// FYI: this is a million years from happening on n64, since it's all geriatric non-FBO code
|
||||||
// is it workable for saturn?
|
videoTexture = _gl.WrapGLTexture2d(new(glTextureProvider.GetGLTexture()), bufferWidth, bufferHeight);
|
||||||
videoTexture = _gl.WrapGLTexture2d(new(videoBuffer[0]), bufferWidth, bufferHeight);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// wrap the VideoProvider data in a BitmapBuffer (no point to refactoring that many IVideoProviders)
|
// wrap the VideoProvider data in a BitmapBuffer (no point to refactoring that many IVideoProviders)
|
||||||
bb = new(bufferWidth, bufferHeight, videoBuffer);
|
bb = new(bufferWidth, bufferHeight, videoProvider.GetVideoBuffer());
|
||||||
bb.DiscardAlpha();
|
bb.DiscardAlpha();
|
||||||
|
|
||||||
//now, acquire the data sent from the videoProvider into a texture
|
//now, acquire the data sent from the videoProvider into a texture
|
||||||
videoTexture = _videoTextureFrugalizer.Get(bb);
|
videoTexture = _videoTextureFrugalizer.Get(bb);
|
||||||
|
|
||||||
// lets not use this. lets define BizwareGL to make clamp by default (TBD: check opengl)
|
// lets not use this. lets define BizwareGL to make clamp by default (TBD: check opengl)
|
||||||
// GL.SetTextureWrapMode(videoTexture, true);
|
// _gl.SetTextureWrapMode(videoTexture, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -897,7 +893,6 @@ namespace BizHawk.Client.Common
|
||||||
fPresent.TextureSize = new(presenterTextureWidth, presenterTextureHeight);
|
fPresent.TextureSize = new(presenterTextureWidth, presenterTextureHeight);
|
||||||
fPresent.BackgroundColor = videoProvider.BackgroundColor;
|
fPresent.BackgroundColor = videoProvider.BackgroundColor;
|
||||||
fPresent.GuiRenderer = _renderer;
|
fPresent.GuiRenderer = _renderer;
|
||||||
fPresent.Flip = isGlTextureId;
|
|
||||||
fPresent.Config_FixAspectRatio = GlobalConfig.DispFixAspectRatio;
|
fPresent.Config_FixAspectRatio = GlobalConfig.DispFixAspectRatio;
|
||||||
fPresent.Config_FixScaleInteger = GlobalConfig.DispFixScaleInteger;
|
fPresent.Config_FixScaleInteger = GlobalConfig.DispFixScaleInteger;
|
||||||
fPresent.Padding = (ClientExtraPadding.Left, ClientExtraPadding.Top, ClientExtraPadding.Right, ClientExtraPadding.Bottom);
|
fPresent.Padding = (ClientExtraPadding.Left, ClientExtraPadding.Top, ClientExtraPadding.Right, ClientExtraPadding.Bottom);
|
||||||
|
@ -932,7 +927,7 @@ namespace BizHawk.Client.Common
|
||||||
|
|
||||||
public void Blank()
|
public void Blank()
|
||||||
{
|
{
|
||||||
ActivateGLContext();
|
ActivateGraphicsControlContext();
|
||||||
_gl.BeginScene();
|
_gl.BeginScene();
|
||||||
_gl.BindRenderTarget(null);
|
_gl.BindRenderTarget(null);
|
||||||
_gl.SetClearColor(Color.Black);
|
_gl.SetClearColor(Color.Black);
|
||||||
|
|
|
@ -435,7 +435,6 @@ namespace BizHawk.Client.Common.Filters
|
||||||
public int BackgroundColor;
|
public int BackgroundColor;
|
||||||
public bool AutoPrescale;
|
public bool AutoPrescale;
|
||||||
public IGuiRenderer GuiRenderer;
|
public IGuiRenderer GuiRenderer;
|
||||||
public bool Flip;
|
|
||||||
public IGL GL;
|
public IGL GL;
|
||||||
private bool nop;
|
private bool nop;
|
||||||
private LetterboxingLogic LL;
|
private LetterboxingLogic LL;
|
||||||
|
@ -491,7 +490,7 @@ namespace BizHawk.Client.Common.Filters
|
||||||
|
|
||||||
public override void SetInputFormat(string channel, SurfaceState state)
|
public override void SetInputFormat(string channel, SurfaceState state)
|
||||||
{
|
{
|
||||||
bool need = state.SurfaceFormat.Size != OutputSize || FilterOption != eFilterOption.None || Flip;
|
bool need = state.SurfaceFormat.Size != OutputSize || FilterOption != eFilterOption.None;
|
||||||
|
|
||||||
if (!need)
|
if (!need)
|
||||||
{
|
{
|
||||||
|
@ -575,14 +574,7 @@ namespace BizHawk.Client.Common.Filters
|
||||||
//this was handled earlier by another filter
|
//this was handled earlier by another filter
|
||||||
}
|
}
|
||||||
|
|
||||||
GuiRenderer.Modelview.Translate(LL.vx, LL.vy);
|
GuiRenderer.Draw(InputTexture, LL.vx, LL.vy, LL.vw, LL.vh);
|
||||||
if (Flip)
|
|
||||||
{
|
|
||||||
GuiRenderer.Modelview.Scale(1, -1);
|
|
||||||
GuiRenderer.Modelview.Translate(0, -LL.vh);
|
|
||||||
}
|
|
||||||
GuiRenderer.Draw(InputTexture,0,0,LL.vw,LL.vh);
|
|
||||||
|
|
||||||
GuiRenderer.End();
|
GuiRenderer.End();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,8 +20,6 @@ namespace BizHawk.Client.EmuHawk
|
||||||
|
|
||||||
private readonly PresentationPanel _presentationPanel; // well, its the final layer's target, at least
|
private readonly PresentationPanel _presentationPanel; // well, its the final layer's target, at least
|
||||||
|
|
||||||
private readonly GLManager.ContextRef _crGraphicsControl;
|
|
||||||
|
|
||||||
private GraphicsControl _graphicsControl => _presentationPanel.GraphicsControl;
|
private GraphicsControl _graphicsControl => _presentationPanel.GraphicsControl;
|
||||||
|
|
||||||
public DisplayManager(
|
public DisplayManager(
|
||||||
|
@ -36,14 +34,17 @@ namespace BizHawk.Client.EmuHawk
|
||||||
{
|
{
|
||||||
_presentationPanel = presentationPanel;
|
_presentationPanel = presentationPanel;
|
||||||
_getIsSecondaryThrottlingDisabled = getIsSecondaryThrottlingDisabled;
|
_getIsSecondaryThrottlingDisabled = getIsSecondaryThrottlingDisabled;
|
||||||
|
|
||||||
// setup the GL context manager, needed for coping with multiple opengl cores vs opengl display method
|
|
||||||
// but is it tho? --yoshi
|
|
||||||
// turns out it was, calling Instance getter here initialises it, and the encapsulated Activate call is necessary too --yoshi
|
|
||||||
_crGraphicsControl = GLManager.GetContextForGraphicsControl(_graphicsControl);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void ActivateGLContext() => GLManager.Instance.Activate(_crGraphicsControl);
|
public override void ActivateOpenGLContext()
|
||||||
|
{
|
||||||
|
if (_gl.DispMethodEnum == EDispMethod.OpenGL)
|
||||||
|
{
|
||||||
|
_graphicsControl.Begin();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void ActivateGraphicsControlContext() => _graphicsControl.Begin();
|
||||||
|
|
||||||
protected override Size GetGraphicsControlSize() => _graphicsControl.Size;
|
protected override Size GetGraphicsControlSize() => _graphicsControl.Size;
|
||||||
|
|
||||||
|
|
|
@ -1,91 +0,0 @@
|
||||||
using System;
|
|
||||||
using BizHawk.Bizware.BizwareGL;
|
|
||||||
using BizHawk.Bizware.Graphics;
|
|
||||||
|
|
||||||
namespace BizHawk.Client.EmuHawk
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// This singleton class manages OpenGL contexts, in an effort to minimize context changes.
|
|
||||||
/// </summary>
|
|
||||||
public class GLManager : IDisposable
|
|
||||||
{
|
|
||||||
private GLManager()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
private static readonly Lazy<GLManager> _lazyInstance = new(() => new());
|
|
||||||
|
|
||||||
public static GLManager Instance => _lazyInstance.Value;
|
|
||||||
|
|
||||||
public void ReleaseGLContext(object o)
|
|
||||||
{
|
|
||||||
var cr = (ContextRef)o;
|
|
||||||
cr.GL.Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
public ContextRef CreateGLContext(int majorVersion, int minorVersion, bool forwardCompatible)
|
|
||||||
{
|
|
||||||
var gl = new IGL_OpenGL(majorVersion, minorVersion, forwardCompatible);
|
|
||||||
return new() { GL = gl };
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ContextRef GetContextForGraphicsControl(GraphicsControl gc)
|
|
||||||
{
|
|
||||||
return new()
|
|
||||||
{
|
|
||||||
Gc = gc,
|
|
||||||
GL = gc.IGL
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private ContextRef _activeContext;
|
|
||||||
|
|
||||||
public void Invalidate()
|
|
||||||
{
|
|
||||||
_activeContext = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Activate(ContextRef cr)
|
|
||||||
{
|
|
||||||
if (cr == _activeContext)
|
|
||||||
{
|
|
||||||
// D3D9 needs a begin signal to set the swap chain to the next backbuffer
|
|
||||||
if (cr.GL.DispMethodEnum is EDispMethod.D3D9)
|
|
||||||
{
|
|
||||||
cr.Gc.Begin();
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_activeContext = cr;
|
|
||||||
|
|
||||||
if (cr.Gc != null)
|
|
||||||
{
|
|
||||||
cr.Gc.Begin();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (cr.GL is IGL_OpenGL gl)
|
|
||||||
{
|
|
||||||
gl.MakeOffscreenContextCurrent();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Deactivate()
|
|
||||||
{
|
|
||||||
//this is here for future use and tracking purposes.. however.. instead of relying on this, we should just make sure we always activate what we need before we use it
|
|
||||||
}
|
|
||||||
|
|
||||||
public class ContextRef
|
|
||||||
{
|
|
||||||
public IGL GL { get; set; }
|
|
||||||
public GraphicsControl Gc { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
using BizHawk.Bizware.Graphics;
|
||||||
|
using BizHawk.Emulation.Common;
|
||||||
|
|
||||||
|
namespace BizHawk.Client.EmuHawk
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Provides a way for a core to use OpenGL
|
||||||
|
/// </summary>
|
||||||
|
public class OpenGLProvider : IOpenGLProvider
|
||||||
|
{
|
||||||
|
public int GLVersion => SDL2OpenGLContext.Version;
|
||||||
|
|
||||||
|
public object RequestGLContext(int major, int minor, bool forwardCompatible)
|
||||||
|
=> new SDL2OpenGLContext(major, minor, forwardCompatible);
|
||||||
|
|
||||||
|
public void ReleaseGLContext(object context)
|
||||||
|
=> ((SDL2OpenGLContext)context).Dispose();
|
||||||
|
|
||||||
|
public void ActivateGLContext(object context)
|
||||||
|
=> ((SDL2OpenGLContext)context).MakeContextCurrent();
|
||||||
|
|
||||||
|
public void DeactivateGLContext()
|
||||||
|
=> SDL2OpenGLContext.MakeNoneCurrent();
|
||||||
|
|
||||||
|
public IntPtr GetGLProcAddress(string proc)
|
||||||
|
=> SDL2OpenGLContext.GetGLProcAddress(proc);
|
||||||
|
}
|
||||||
|
}
|
|
@ -226,7 +226,8 @@ namespace BizHawk.Client.EmuHawk
|
||||||
message => this.ModalMessageBox(message, "Warning", EMsgBoxIcon.Warning),
|
message => this.ModalMessageBox(message, "Warning", EMsgBoxIcon.Warning),
|
||||||
AddOnScreenMessage,
|
AddOnScreenMessage,
|
||||||
cfp,
|
cfp,
|
||||||
prefs);
|
prefs,
|
||||||
|
new OpenGLProvider());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetImages()
|
private void SetImages()
|
||||||
|
@ -3837,6 +3838,7 @@ namespace BizHawk.Client.EmuHawk
|
||||||
//path = ioa_openrom.Path;
|
//path = ioa_openrom.Path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DisplayManager.ActivateOpenGLContext(); // required in case the core wants to created a shared OpenGL context
|
||||||
var result = loader.LoadRom(path, nextComm, ioaRetro?.CorePath, forcedCoreName: MovieSession.QueuedCoreName);
|
var result = loader.LoadRom(path, nextComm, ioaRetro?.CorePath, forcedCoreName: MovieSession.QueuedCoreName);
|
||||||
|
|
||||||
if (result) Game = loader.Game;
|
if (result) Game = loader.Game;
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
@ -227,16 +226,14 @@ namespace BizHawk.Client.EmuHawk
|
||||||
return TryInitIGL(initialConfig.DispMethod = fallback.Method);
|
return TryInitIGL(initialConfig.DispMethod = fallback.Method);
|
||||||
}
|
}
|
||||||
case EDispMethod.OpenGL:
|
case EDispMethod.OpenGL:
|
||||||
var glOpenGL = new IGL_OpenGL(2, 0, false);
|
if (SDL2OpenGLContext.Version < 200)
|
||||||
if (glOpenGL.Version < 200)
|
|
||||||
{
|
{
|
||||||
// too old to use, GDI+ will be better
|
// too old to use, GDI+ will be better
|
||||||
glOpenGL.Dispose();
|
|
||||||
var fallback = ChooseFallback();
|
var fallback = ChooseFallback();
|
||||||
new ExceptionBox(new Exception($"Initialization of OpenGL Display Method failed; falling back to {fallback.Name}")).ShowDialog();
|
new ExceptionBox(new Exception($"Initialization of OpenGL Display Method failed; falling back to {fallback.Name}")).ShowDialog();
|
||||||
return TryInitIGL(initialConfig.DispMethod = fallback.Method);
|
return TryInitIGL(initialConfig.DispMethod = fallback.Method);
|
||||||
}
|
}
|
||||||
return CheckRenderer(glOpenGL);
|
return CheckRenderer(new IGL_OpenGL(2, 0, false));
|
||||||
default:
|
default:
|
||||||
case EDispMethod.GdiPlus:
|
case EDispMethod.GdiPlus:
|
||||||
static GLControlWrapper_GdiPlus CreateGLControlWrapper(IGL_GdiPlus self) => new(self); // inlining as lambda causes crash, don't wanna know why --yoshi
|
static GLControlWrapper_GdiPlus CreateGLControlWrapper(IGL_GdiPlus self) => new(self); // inlining as lambda causes crash, don't wanna know why --yoshi
|
||||||
|
|
|
@ -14,13 +14,15 @@ namespace BizHawk.Emulation.Common
|
||||||
Action<string> showMessage,
|
Action<string> showMessage,
|
||||||
Action<string, int?> notifyMessage,
|
Action<string, int?> notifyMessage,
|
||||||
ICoreFileProvider coreFileProvider,
|
ICoreFileProvider coreFileProvider,
|
||||||
CorePreferencesFlags prefs
|
CorePreferencesFlags prefs,
|
||||||
|
IOpenGLProvider oglProvider
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
ShowMessage = showMessage;
|
ShowMessage = showMessage;
|
||||||
Notify = notifyMessage;
|
Notify = notifyMessage;
|
||||||
CoreFileProvider = coreFileProvider;
|
CoreFileProvider = coreFileProvider;
|
||||||
CorePreferences = prefs;
|
CorePreferences = prefs;
|
||||||
|
OpenGLProvider = oglProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ICoreFileProvider CoreFileProvider { get; }
|
public ICoreFileProvider CoreFileProvider { get; }
|
||||||
|
@ -47,5 +49,10 @@ namespace BizHawk.Emulation.Common
|
||||||
/// Yeah, I put more stuff in corecomm. If you don't like it, change the settings/syncsettings stuff to support multiple "settings sets" to act like ini file sections kind of, so that we can hand a generic settings object to cores instead of strictly ones defined by the cores
|
/// Yeah, I put more stuff in corecomm. If you don't like it, change the settings/syncsettings stuff to support multiple "settings sets" to act like ini file sections kind of, so that we can hand a generic settings object to cores instead of strictly ones defined by the cores
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public CorePreferencesFlags CorePreferences { get; }
|
public CorePreferencesFlags CorePreferences { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Interface to provide OpenGL resources to the core
|
||||||
|
/// </summary>
|
||||||
|
public IOpenGLProvider OpenGLProvider { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace BizHawk.Emulation.Common
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Defines an interface for cores to obtain OpenGL contexts and functions
|
||||||
|
/// </summary>
|
||||||
|
public interface IOpenGLProvider
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// OpenGL version, using major.minor.build format with decimal points ommitted (e.g. 1.2.3 turns into 123)
|
||||||
|
/// </summary>
|
||||||
|
public int GLVersion { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Requests an OpenGL context with specified major / minor / forwardCompatible
|
||||||
|
/// The requested OpenGL context will be shared with the current context
|
||||||
|
/// Note: creating a context implicitly makes that created context current
|
||||||
|
/// </summary>
|
||||||
|
public object RequestGLContext(int major, int minor, bool forwardCompatible);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Frees this OpenGL context
|
||||||
|
/// </summary>
|
||||||
|
public void ReleaseGLContext(object context);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets this OpenGL context to current
|
||||||
|
/// </summary>
|
||||||
|
public void ActivateGLContext(object context);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Deactivates the current OpenGL context
|
||||||
|
/// No context will be current after this call
|
||||||
|
/// </summary>
|
||||||
|
public void DeactivateGLContext();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets an OpenGL function pointer
|
||||||
|
/// The user must make a context active before using this
|
||||||
|
/// </summary>
|
||||||
|
public IntPtr GetGLProcAddress(string proc);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
namespace BizHawk.Emulation.Common
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// This service is an extension of IVideoProvider, providing the ability to pass an OpenGL texture to the client
|
||||||
|
/// If available and the client is using OpenGL for display, this texture will be used
|
||||||
|
/// If unavailable or the client is not using OpenGL for display, the client will fall back to the base <see cref="IVideoProvider"/>
|
||||||
|
/// </summary>
|
||||||
|
public interface IGLTextureProvider : IVideoProvider, ISpecializedEmulatorService
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Returns an OpenGL texture of the current video content
|
||||||
|
/// </summary>
|
||||||
|
int GetGLTexture();
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue