diff --git a/src/BizHawk.Bizware.BizwareGL/IGL.cs b/src/BizHawk.Bizware.BizwareGL/IGL.cs index 6b6f57d324..d6353bf10d 100644 --- a/src/BizHawk.Bizware.BizwareGL/IGL.cs +++ b/src/BizHawk.Bizware.BizwareGL/IGL.cs @@ -159,7 +159,7 @@ namespace BizHawk.Bizware.BizwareGL /// /// 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() /// Texture2d WrapGLTexture2d(IntPtr glTexId, int width, int height); diff --git a/src/BizHawk.Bizware.BizwareGL/RenderTarget.cs b/src/BizHawk.Bizware.BizwareGL/RenderTarget.cs index 999dd8e9bc..8285cbbfb3 100644 --- a/src/BizHawk.Bizware.BizwareGL/RenderTarget.cs +++ b/src/BizHawk.Bizware.BizwareGL/RenderTarget.cs @@ -9,7 +9,6 @@ namespace BizHawk.Bizware.BizwareGL Owner = owner; Opaque = opaque; Texture2d = tex; - tex.IsUpsideDown = true; } public override string ToString() diff --git a/src/BizHawk.Bizware.Graphics/D3D9/IGL_D3D9.cs b/src/BizHawk.Bizware.Graphics/D3D9/IGL_D3D9.cs index f1bbb4a735..782d8f8eea 100644 --- a/src/BizHawk.Bizware.Graphics/D3D9/IGL_D3D9.cs +++ b/src/BizHawk.Bizware.Graphics/D3D9/IGL_D3D9.cs @@ -683,8 +683,7 @@ namespace BizHawk.Bizware.Graphics public Texture2d WrapGLTexture2d(IntPtr glTexId, int width, int height) { - // not needed 1st pass (except for GL cores) - // TODO - need to rip the texture data. we had code for that somewhere... + // only used for OpenGL return null; } diff --git a/src/BizHawk.Bizware.Graphics/OpenGL/IGL_OpenGL.cs b/src/BizHawk.Bizware.Graphics/OpenGL/IGL_OpenGL.cs index fa23167641..8c771af9cd 100644 --- a/src/BizHawk.Bizware.Graphics/OpenGL/IGL_OpenGL.cs +++ b/src/BizHawk.Bizware.Graphics/OpenGL/IGL_OpenGL.cs @@ -37,10 +37,7 @@ namespace BizHawk.Bizware.Graphics { public EDispMethod DispMethodEnum => EDispMethod.OpenGL; - private readonly SDL2OpenGLContext OffscreenContext; - private SDL2OpenGLContext ActiveContext; - private GL GL => ActiveContext.GL; - + private readonly GL GL; private readonly int _majorVersion, _minorVersion; private readonly bool _forwardCompatible; @@ -50,36 +47,20 @@ namespace BizHawk.Bizware.Graphics 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) { - // create an offscreen context, so things can be done without a control - ActiveContext = OffscreenContext = new(majorVersion, minorVersion, forwardCompatible); - _majorVersion = majorVersion; _minorVersion = minorVersion; _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 CreateRenderStates(); } @@ -94,7 +75,6 @@ namespace BizHawk.Bizware.Graphics public void Dispose() { - OffscreenContext.Dispose(); } public void Clear(BizClearBufferMask mask) @@ -477,7 +457,7 @@ namespace BizHawk.Bizware.Graphics 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) @@ -505,7 +485,7 @@ namespace BizHawk.Bizware.Graphics { // create a texture for it 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.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 readonly HashSet 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; sStatePendingVertexLayout = null; sVertexAttribEnables.Clear(); - ActiveContext = context; - } - - public void MakeOffscreenContextCurrent() - { - OffscreenContext.MakeContextCurrent(); - ContextChangeCallback(OffscreenContext); } } } diff --git a/src/BizHawk.Bizware.Graphics/OpenGL/OpenGLControl.cs b/src/BizHawk.Bizware.Graphics/OpenGL/OpenGLControl.cs index f04cc6c325..0dd2efbbbf 100644 --- a/src/BizHawk.Bizware.Graphics/OpenGL/OpenGLControl.cs +++ b/src/BizHawk.Bizware.Graphics/OpenGL/OpenGLControl.cs @@ -11,7 +11,7 @@ namespace BizHawk.Bizware.Graphics private readonly int _majorVersion; private readonly int _minorVersion; private readonly bool _forwardCompatible; - private readonly Action _contextChangeCallback; + private readonly Action _contextChangeCallback; public SDL2OpenGLContext Context { get; private set; } @@ -21,7 +21,7 @@ namespace BizHawk.Bizware.Graphics set => throw new NotImplementedException(); } - public OpenGLControl(int majorVersion, int minorVersion, bool forwardCompatible, Action contextChangeCallback) + public OpenGLControl(int majorVersion, int minorVersion, bool forwardCompatible, Action contextChangeCallback) { _majorVersion = majorVersion; _minorVersion = minorVersion; @@ -59,8 +59,7 @@ namespace BizHawk.Bizware.Graphics { base.OnHandleCreated(e); Context = new(Handle, _majorVersion, _minorVersion, _forwardCompatible); - - _contextChangeCallback(Context); + _contextChangeCallback(); } protected override void OnHandleDestroyed(EventArgs e) @@ -69,7 +68,7 @@ namespace BizHawk.Bizware.Graphics if (Context.IsCurrent) { - _contextChangeCallback(null); + _contextChangeCallback(); } Context.Dispose(); @@ -92,7 +91,7 @@ namespace BizHawk.Bizware.Graphics if (!Context.IsCurrent) { Context.MakeContextCurrent(); - _contextChangeCallback(Context); + _contextChangeCallback(); } } } @@ -110,7 +109,8 @@ namespace BizHawk.Bizware.Graphics public void End() { - _contextChangeCallback(null); + SDL2OpenGLContext.MakeNoneCurrent(); + _contextChangeCallback(); } public void SwapBuffers() diff --git a/src/BizHawk.Bizware.Graphics/OpenGL/SDL2OpenGLContext.cs b/src/BizHawk.Bizware.Graphics/OpenGL/SDL2OpenGLContext.cs index 6b882c72df..7d03136eec 100644 --- a/src/BizHawk.Bizware.Graphics/OpenGL/SDL2OpenGLContext.cs +++ b/src/BizHawk.Bizware.Graphics/OpenGL/SDL2OpenGLContext.cs @@ -1,6 +1,5 @@ using System; - -using Silk.NET.OpenGL.Legacy; +using System.Runtime.InteropServices; using static SDL2.SDL; @@ -9,7 +8,7 @@ namespace BizHawk.Bizware.Graphics /// /// Wraps an SDL2 OpenGL context /// - internal class SDL2OpenGLContext : IDisposable + public class SDL2OpenGLContext : IDisposable { static SDL2OpenGLContext() { @@ -41,11 +40,50 @@ namespace BizHawk.Bizware.Graphics SDL_SetHint(SDL_HINT_VIDEO_FOREIGN_WINDOW_OPENGL, "1"); } + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + private delegate IntPtr glGetStringDelegate(int name); + + private static readonly Lazy _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(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 _glContext; - public GL GL { get; private set; } - private void CreateContext(int majorVersion, int minorVersion, bool forwardCompatible) { 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()}"); } - - // 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) @@ -146,6 +180,15 @@ namespace BizHawk.Bizware.Graphics _ = 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) { if (!IsCurrent) diff --git a/src/BizHawk.Client.Common/DisplayManager/DisplayManagerBase.cs b/src/BizHawk.Client.Common/DisplayManager/DisplayManagerBase.cs index 21a69d9f4a..9e9b9fd64f 100644 --- a/src/BizHawk.Client.Common/DisplayManager/DisplayManagerBase.cs +++ b/src/BizHawk.Client.Common/DisplayManager/DisplayManagerBase.cs @@ -196,7 +196,9 @@ namespace BizHawk.Client.Common 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(); @@ -771,12 +773,10 @@ namespace BizHawk.Client.Common private FilterProgram UpdateSourceInternal(JobInfo job) { - //no drawing actually happens. it's important not to begin drawing on a control - if (!job.Simulate/* && !job.Offscreen*/) + // no drawing actually happens + if (!job.Simulate) { - // i don't want to do this for offscreen jobs - // but it seems that would be required in case this context isn't active - ActivateGLContext(); + ActivateGraphicsControlContext(); if (job.ChainOutsize.Width == 0 || job.ChainOutsize.Height == 0) { @@ -791,17 +791,14 @@ namespace BizHawk.Client.Common } var videoProvider = job.VideoProvider; + var glTextureProvider = videoProvider as IGLTextureProvider; var simulate = job.Simulate; var chainOutsize = job.ChainOutsize; - //simulate = true; - - var videoBuffer = videoProvider.GetVideoBuffer(); var bufferWidth = videoProvider.BufferWidth; var bufferHeight = videoProvider.BufferHeight; var presenterTextureWidth = bufferWidth; var presenterTextureHeight = bufferHeight; - var isGlTextureId = videoBuffer.Length == 1; var vw = videoProvider.VirtualWidth; var vh = videoProvider.VirtualHeight; @@ -854,23 +851,22 @@ namespace BizHawk.Client.Common Texture2d videoTexture = null; 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 - // is it workable for saturn? - videoTexture = _gl.WrapGLTexture2d(new(videoBuffer[0]), bufferWidth, bufferHeight); + videoTexture = _gl.WrapGLTexture2d(new(glTextureProvider.GetGLTexture()), bufferWidth, bufferHeight); } else { // 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(); //now, acquire the data sent from the videoProvider into a texture videoTexture = _videoTextureFrugalizer.Get(bb); // 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.BackgroundColor = videoProvider.BackgroundColor; fPresent.GuiRenderer = _renderer; - fPresent.Flip = isGlTextureId; fPresent.Config_FixAspectRatio = GlobalConfig.DispFixAspectRatio; fPresent.Config_FixScaleInteger = GlobalConfig.DispFixScaleInteger; fPresent.Padding = (ClientExtraPadding.Left, ClientExtraPadding.Top, ClientExtraPadding.Right, ClientExtraPadding.Bottom); @@ -932,7 +927,7 @@ namespace BizHawk.Client.Common public void Blank() { - ActivateGLContext(); + ActivateGraphicsControlContext(); _gl.BeginScene(); _gl.BindRenderTarget(null); _gl.SetClearColor(Color.Black); diff --git a/src/BizHawk.Client.Common/DisplayManager/Filters/Gui.cs b/src/BizHawk.Client.Common/DisplayManager/Filters/Gui.cs index 95d4cae720..72badbcf27 100644 --- a/src/BizHawk.Client.Common/DisplayManager/Filters/Gui.cs +++ b/src/BizHawk.Client.Common/DisplayManager/Filters/Gui.cs @@ -435,7 +435,6 @@ namespace BizHawk.Client.Common.Filters public int BackgroundColor; public bool AutoPrescale; public IGuiRenderer GuiRenderer; - public bool Flip; public IGL GL; private bool nop; private LetterboxingLogic LL; @@ -491,7 +490,7 @@ namespace BizHawk.Client.Common.Filters 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) { @@ -575,14 +574,7 @@ namespace BizHawk.Client.Common.Filters //this was handled earlier by another filter } - GuiRenderer.Modelview.Translate(LL.vx, LL.vy); - if (Flip) - { - GuiRenderer.Modelview.Scale(1, -1); - GuiRenderer.Modelview.Translate(0, -LL.vh); - } - GuiRenderer.Draw(InputTexture,0,0,LL.vw,LL.vh); - + GuiRenderer.Draw(InputTexture, LL.vx, LL.vy, LL.vw, LL.vh); GuiRenderer.End(); } } diff --git a/src/BizHawk.Client.EmuHawk/DisplayManager/DisplayManager.cs b/src/BizHawk.Client.EmuHawk/DisplayManager/DisplayManager.cs index d2516549bd..3c65e9a219 100644 --- a/src/BizHawk.Client.EmuHawk/DisplayManager/DisplayManager.cs +++ b/src/BizHawk.Client.EmuHawk/DisplayManager/DisplayManager.cs @@ -20,8 +20,6 @@ namespace BizHawk.Client.EmuHawk private readonly PresentationPanel _presentationPanel; // well, its the final layer's target, at least - private readonly GLManager.ContextRef _crGraphicsControl; - private GraphicsControl _graphicsControl => _presentationPanel.GraphicsControl; public DisplayManager( @@ -36,14 +34,17 @@ namespace BizHawk.Client.EmuHawk { _presentationPanel = presentationPanel; _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; diff --git a/src/BizHawk.Client.EmuHawk/GLManager.cs b/src/BizHawk.Client.EmuHawk/GLManager.cs deleted file mode 100644 index 712b65b36d..0000000000 --- a/src/BizHawk.Client.EmuHawk/GLManager.cs +++ /dev/null @@ -1,91 +0,0 @@ -using System; -using BizHawk.Bizware.BizwareGL; -using BizHawk.Bizware.Graphics; - -namespace BizHawk.Client.EmuHawk -{ - /// - /// This singleton class manages OpenGL contexts, in an effort to minimize context changes. - /// - public class GLManager : IDisposable - { - private GLManager() - { - } - - public void Dispose() - { - } - - private static readonly Lazy _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; } - } - } -} \ No newline at end of file diff --git a/src/BizHawk.Client.EmuHawk/GraphicsImplementations/OpenGLProvider.cs b/src/BizHawk.Client.EmuHawk/GraphicsImplementations/OpenGLProvider.cs new file mode 100644 index 0000000000..8b1b5530c8 --- /dev/null +++ b/src/BizHawk.Client.EmuHawk/GraphicsImplementations/OpenGLProvider.cs @@ -0,0 +1,30 @@ +using System; + +using BizHawk.Bizware.Graphics; +using BizHawk.Emulation.Common; + +namespace BizHawk.Client.EmuHawk +{ + /// + /// Provides a way for a core to use OpenGL + /// + 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); + } +} diff --git a/src/BizHawk.Client.EmuHawk/MainForm.cs b/src/BizHawk.Client.EmuHawk/MainForm.cs index d16067653a..c929c6c3fd 100644 --- a/src/BizHawk.Client.EmuHawk/MainForm.cs +++ b/src/BizHawk.Client.EmuHawk/MainForm.cs @@ -226,7 +226,8 @@ namespace BizHawk.Client.EmuHawk message => this.ModalMessageBox(message, "Warning", EMsgBoxIcon.Warning), AddOnScreenMessage, cfp, - prefs); + prefs, + new OpenGLProvider()); } private void SetImages() @@ -3837,6 +3838,7 @@ namespace BizHawk.Client.EmuHawk //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); if (result) Game = loader.Game; diff --git a/src/BizHawk.Client.EmuHawk/Program.cs b/src/BizHawk.Client.EmuHawk/Program.cs index 9ac125af41..e12e756901 100644 --- a/src/BizHawk.Client.EmuHawk/Program.cs +++ b/src/BizHawk.Client.EmuHawk/Program.cs @@ -1,7 +1,6 @@ using System; using System.Diagnostics; using System.IO; -using System.Linq; using System.Collections.Generic; using System.Reflection; using System.Runtime.InteropServices; @@ -227,16 +226,14 @@ namespace BizHawk.Client.EmuHawk return TryInitIGL(initialConfig.DispMethod = fallback.Method); } case EDispMethod.OpenGL: - var glOpenGL = new IGL_OpenGL(2, 0, false); - if (glOpenGL.Version < 200) + if (SDL2OpenGLContext.Version < 200) { // too old to use, GDI+ will be better - glOpenGL.Dispose(); var fallback = ChooseFallback(); new ExceptionBox(new Exception($"Initialization of OpenGL Display Method failed; falling back to {fallback.Name}")).ShowDialog(); return TryInitIGL(initialConfig.DispMethod = fallback.Method); } - return CheckRenderer(glOpenGL); + return CheckRenderer(new IGL_OpenGL(2, 0, false)); default: case EDispMethod.GdiPlus: static GLControlWrapper_GdiPlus CreateGLControlWrapper(IGL_GdiPlus self) => new(self); // inlining as lambda causes crash, don't wanna know why --yoshi diff --git a/src/BizHawk.Emulation.Common/CoreComms.cs b/src/BizHawk.Emulation.Common/CoreComms.cs index 9c7410dd4b..d8572275e1 100644 --- a/src/BizHawk.Emulation.Common/CoreComms.cs +++ b/src/BizHawk.Emulation.Common/CoreComms.cs @@ -14,13 +14,15 @@ namespace BizHawk.Emulation.Common Action showMessage, Action notifyMessage, ICoreFileProvider coreFileProvider, - CorePreferencesFlags prefs + CorePreferencesFlags prefs, + IOpenGLProvider oglProvider ) { ShowMessage = showMessage; Notify = notifyMessage; CoreFileProvider = coreFileProvider; CorePreferences = prefs; + OpenGLProvider = oglProvider; } 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 /// public CorePreferencesFlags CorePreferences { get; } + + /// + /// Interface to provide OpenGL resources to the core + /// + public IOpenGLProvider OpenGLProvider { get; } } } diff --git a/src/BizHawk.Emulation.Common/Interfaces/IOpenGLProvider.cs b/src/BizHawk.Emulation.Common/Interfaces/IOpenGLProvider.cs new file mode 100644 index 0000000000..cc530aa767 --- /dev/null +++ b/src/BizHawk.Emulation.Common/Interfaces/IOpenGLProvider.cs @@ -0,0 +1,44 @@ +using System; + +namespace BizHawk.Emulation.Common +{ + /// + /// Defines an interface for cores to obtain OpenGL contexts and functions + /// + public interface IOpenGLProvider + { + /// + /// OpenGL version, using major.minor.build format with decimal points ommitted (e.g. 1.2.3 turns into 123) + /// + public int GLVersion { get; } + + /// + /// 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 + /// + public object RequestGLContext(int major, int minor, bool forwardCompatible); + + /// + /// Frees this OpenGL context + /// + public void ReleaseGLContext(object context); + + /// + /// Sets this OpenGL context to current + /// + public void ActivateGLContext(object context); + + /// + /// Deactivates the current OpenGL context + /// No context will be current after this call + /// + public void DeactivateGLContext(); + + /// + /// Gets an OpenGL function pointer + /// The user must make a context active before using this + /// + public IntPtr GetGLProcAddress(string proc); + } +} diff --git a/src/BizHawk.Emulation.Common/Interfaces/Services/IGLTextureProvider.cs b/src/BizHawk.Emulation.Common/Interfaces/Services/IGLTextureProvider.cs new file mode 100644 index 0000000000..dcf4248e78 --- /dev/null +++ b/src/BizHawk.Emulation.Common/Interfaces/Services/IGLTextureProvider.cs @@ -0,0 +1,15 @@ +namespace BizHawk.Emulation.Common +{ + /// + /// 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 + /// + public interface IGLTextureProvider : IVideoProvider, ISpecializedEmulatorService + { + /// + /// Returns an OpenGL texture of the current video content + /// + int GetGLTexture(); + } +}