Search code examples
javalwjgl

LWJGL Error: GLFW may only be used on the main thread. This check may be disabled with Configuration.GLFW_CHECK_THREAD0


I am trying to create a window using LWJGL and it has one thread game. When I try and run my code i get an error: GLFW may only be used on the main thread. This check may be disabled with Configuration.GLFW_CHECK_THREAD0.. At first, it suggested adding a JVM parameter -XstartOnFirstThread, and I configured my IDE to do so but now it suggests: This check may be disabled with Configuration.GLFW_CHECK_THREAD0.. How do I implement this or fix it another way?

Main.java:

package main;

import engine.io.Window;

public class Main implements Runnable {
    public Thread game;
    
    public static Window window;
    
    public static final int WIDTH = 1280, HEIGHT = 760;
    
    public void start() {
        game = new Thread(this, "game");
        game.start();
    }
    
    public static void init() {
        System.out.println("Initializing game!");
        window = new Window(WIDTH, HEIGHT, "game");
        
        window.create();
    }
    
    public void run() {
        init();
        while (true) {
            update();
            render();
        }
    }
    
    private void update() {
        System.out.println("Updating game");
    }
    
    private void render() {
        System.out.println("Rendering game");
    }
    
    public static void main(String[] args) {
        new Main().start();
    }
}

Window.java:

package engine.io;

import org.lwjgl.glfw.GLFW;
import org.lwjgl.glfw.GLFWVidMode;

public class Window {
    private int width, height;
    private String title;
    private long window;
    
    public Window(int width, int height, String title) {
        this.width = width;
        this.height = height;
        this.title = title;
    }
    
    public void create() {
        if (!GLFW.glfwInit()) {
            System.err.println("ERROR: GLFW wasn't initialized");
            return;
        }
        
        window = GLFW.glfwCreateWindow(width, height, title, 0, 0);
        
        if (window == 0) {
            System.err.println("ERROR: Window wasn't created");
            return;
        }
        
        GLFWVidMode videoMode = GLFW.glfwGetVideoMode(GLFW.glfwGetPrimaryMonitor());
        GLFW.glfwSetWindowPos(window, (videoMode.width() - width)/2, (videoMode.height() - height)/2);
        GLFW.glfwShowWindow(window);
    }
}

Solution

  • You are calling GLFW methods/functions from a separately spawned thread. This is not possible on macOS. See GLFW's own documentation e.g. for glfwCreateWindow, under section "Thread safety":

    Thread safety

    This function must only be called from the main thread.

    The same is true for most other functions, like glfwInit, glfwShowWindow, glfwPollEvents/glfwWaitEvents, etc. Please consult GLFW's documentation for this.

    So, most GLFW functions must be called from the main thread, which is the thread implicitly created by the JVM process which initially calls your main method.

    Currently, the only thing that the main thread in your program does is to spawn a new thread and then it lays dormant until the JVM exits. This is completely unnecessary. You could just as well have used the main thread to do the work.

    In order to fix this, simply do not spawn/create a separate thread.