public void addWindow(final String id, final Lwjgl3Application app) {
    if (app.autoloop) // cannot have a running loop
    return;

    Thread thisThread = Thread.currentThread();

    if (thisThread == mainThread) {
      if (getWindow(id) == null) {
        app.id = id;
        queueWindows.add(app);
      }
    } else {
      Runnable run =
          new Runnable() {

            @Override
            public void run() {
              if (getWindow(id) == null) {
                app.id = id;
                queueWindows.add(app);
              }
            }
          };
      postMainRunnable(run);
    }
  }
  /** Main Loop for GLFW. This call will block <br> */
  public void start() {
    mainThread = Thread.currentThread();
    windowThread.start();
    running = true;
    while (running) {
      executeMainRunnables();

      for (int i = 0; i < queueWindows.size; ) {
        final Lwjgl3Application app = queueWindows.removeIndex(i);
        i--;

        Runnable run =
            new Runnable() {
              @Override
              public void run() {
                glfwMakeContextCurrent(0);
                jumpLoop = true;
              }
            };
        postWindowRunnableAndWait(run);

        initWindow(app);
        glfwShowWindow(app.graphics.window);

        Runnable run2 =
            new Runnable() {
              @Override
              public void run() {
                initContext(app);
                windows.add(app);
                tmpfirst = true;
              }
            };
        postWindowRunnable(run2);
        jumpLoop = false;
        break;
      }

      if (tmpfirst && windows.size == 0) {
        running = false;
      }

      glfwWaitEvents();
    }
    try {
      windowThread.join();
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
    glfwTerminate();
    if (errorCallback != null) errorCallback.release();
  }
 public static boolean isInRenderThread() {
   return Thread.currentThread().getId() == RENDER_THREAD_ID;
 }
  @Override
  protected void onStart() {
    INSTANCE = this;

    RENDER_THREAD_ID = Thread.currentThread().getId();

    try {
      loadIcons();
      Display.setIcon(icons);
      Display.setVSyncEnabled(GameSettings.Graphics.vsync);
    } catch (IOException e) {
      e.printStackTrace();
    }

    try {
      setDisplayMode(
          GameSettings.Display.window_width,
          GameSettings.Display.window_height,
          GameSettings.Display.fullscreen);
      Display.create();
      // ROBO //todo get all this changed to proper OGL
      glClearColor(0f, 0f, 0f, 1f);
      glClearDepth(1f);
      glViewport(0, 0, GameSettings.Display.window_width, GameSettings.Display.window_height);
      glMatrixMode(GL_PROJECTION);
      glLoadIdentity();

      glOrtho(
          0.0f,
          GameSettings.Display.resolution.getWidth(),
          GameSettings.Display.resolution.getHeight(),
          0.0f,
          0.1f,
          -1f);
      glMatrixMode(GL_MODELVIEW);
      glEnable(GL_TEXTURE_2D);
      glEnable(GL_BLEND);
      glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
      glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
      glLoadIdentity();
      curAlpha = 1f;
      capabilities = GLContext.getCapabilities();

      System.out.println("OpenGL version: " + glGetString(GL_VERSION));

      System.out.println("Building shaders..");
      long ms = getTime();
      ShaderFactory.buildAllShaders();
      System.out.println("Done! Took " + (getTime() - ms) + "ms.");

    } catch (LWJGLException e) {
      e.printStackTrace();
      System.exit(0);
    } catch (Exception e) {
      e.printStackTrace();
      System.exit(0);
    } finally {
      if (looping) {
        looping = false;
        Display.destroy();
      }
    }

    started = getTime();
    next_tick = getTime();
    getDelta();
  }