McSwaggens
McSwaggens

Reputation: 113

OpenTK multithreading?

Is there a way to draw to the screen using OpenTK/OpenGL in another thread? The code I'm trying to use is

GL.Clear(ClearBufferMask.ColorBufferBit);
GL.ClearColor(Color.Black);

GL.Begin(PrimitiveType.Quads);

GL.Color3(Color.FromArgb(255, 0, 0));
GL.Vertex2(-1, 1);
GL.Color3(Color.FromArgb(0, 255, 0));
GL.Vertex2(1, 1);
GL.Color3(Color.FromArgb(0, 0, 255));
GL.Vertex2(1, -1);
GL.Color3(Color.FromArgb(0, 255, 255));
GL.Vertex2(-1, -1f);

GL.End();
SwapBuffers();

The code above works in the same thread the GameWindow was created in but not when called from another thread.

Upvotes: -1

Views: 3098

Answers (2)

user3391690
user3391690

Reputation: 11

Here is an example of how this can be achieved by using IGLFWGraphicsContext MakeNoneCurrent() method. Just be careful it is easy to get busy resource exceptions. Also don't forget to stop the thread before disposing game window. And same can be achieved with GLControl.

Image

using OpenTK.Graphics.OpenGL;
using OpenTK.Mathematics;
using OpenTK.Windowing.Desktop;
using OpenTK.Windowing.GraphicsLibraryFramework;

namespace Display.Presentation.Views;

public class MainWindow : GameWindow
{
    public MainWindow(GameWindowSettings gameWindowSettings, NativeWindowSettings nativeWindowSettings) : base(gameWindowSettings, nativeWindowSettings)
    {
    }

    // Do the setup when OpenTK is fully loaded.
    protected override void OnLoad()
    {
        base.OnLoad();
        this.Context.MakeNoneCurrent(); // Must be called to release thread and make sure you dont call 'Context' on parent thread.

        var windowPrt = this.Context.WindowPtr;
        new Thread(() =>
        {
            unsafe
            {
                var context = new GLFWGraphicsContext((Window*)windowPrt);
                context.MakeCurrent();

                GL.ClearColor(Color.Aqua);
                GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);

                context.SwapBuffers();
                context.MakeNoneCurrent(); // Very important to release thread.
            }
        }).Start();
    }
}


public class Test2
{
    public Test2()
    {
        var gameWindowSettings = new GameWindowSettings()
        {
            UpdateFrequency = 60
        };


        var nativeWindowSettings = new NativeWindowSettings()
        {
            Size = new Vector2i(800, 600),
            Title = "Game window test title",
        };

        using var game = new MainWindow(gameWindowSettings, nativeWindowSettings);
        game.Run();
    }
}

Upvotes: 1

McSwaggens
McSwaggens

Reputation: 113

I was able to swap the thread OpenGL accepts with this code

thread = new Thread(() =>
{
    IGraphicsContext context = new GraphicsContext(GraphicsMode.Default, window.WindowInfo);
    context.MakeCurrent(window.WindowInfo);
    //Render code here
}).Start();

Upvotes: 4

Related Questions