[SOLVED] LWJGL3 Not threading as expected

Started by JackDawson, June 03, 2015, 00:22:41

Previous topic - Next topic

JackDawson

Hello all. I have made a program that could run while dragging the window around using just pure java. But for some reason I am unable to do that with LWJGL3.

Here is the code. As you should be able to spot, it runs as normal. However, if I drag the window around my desktop, notice, it stops the program. Now with pure java you can do this. Repainting the screen even while dragging is very doable. But I am unable to "fix" this for LWJGL3.

Any ideas ? Here is the code I am currently working with as a test.

package main;

import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.system.MemoryUtil.*;

import java.nio.ByteBuffer;

import org.lwjgl.glfw.GLFWvidmode;

public class Main implements Runnable {

	private int width = 800;
	private int height = 600;
	
	private Thread thread;
	private boolean running = false;
	
	private long window;
	
	public void start() {
		running = true;
		thread = new Thread(this, "Test");
		thread.start();
	}
	
	private void init() {
		if(glfwInit() != GL_TRUE) {
			// To Do Later
			return;
		}
		
		glfwWindowHint(GLFW_RESIZABLE, GL_TRUE);
		window = glfwCreateWindow(width, height, "Test", NULL, NULL);
		if(window == NULL) {
			// To Do Later
			return;
		}
		
		ByteBuffer vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor());
		glfwSetWindowPos(window, (GLFWvidmode.width(vidmode) - width) / 2, (GLFWvidmode.height(vidmode) - height) / 2);
		
		glfwMakeContextCurrent(window);
		glfwShowWindow(window);
	}
	
	public void run() {
		init();
		while(running) {
			update();
			render();
			
			if(glfwWindowShouldClose(window) == GL_TRUE) {
				running = false;
			}
		}
	}
	
	private void update() {
		glfwPollEvents();
		System.out.println("This is rendering !!!!!");
	}
	
	private void render() {
		glfwSwapBuffers(window);
	}
	
	public static void main(String[] args) {
		new Main().start();
	}



}

SHC

This is the first issue on the GLFW GitHub repo.

https://github.com/glfw/glfw/issues/1

Not only moving the window, but also resizing it will block the event loop, as was required by OSX (not sure, thinking so as found on a similar issue on openframeworks). This can simply be solved by setting a refresh callback. I will try to provide an example soon. Until then, see this commit: https://github.com/glfw/glfw/commit/cb11b7ca6f06195d361c74b8db71166f1a716047

JackDawson

Quote from: SHC on June 03, 2015, 06:25:06
This is the first issue on the GLFW GitHub repo.

https://github.com/glfw/glfw/issues/1

Not only moving the window, but also resizing it will block the event loop, as was required by OSX (not sure, thinking so as found on a similar issue on openframeworks). This can simply be solved by setting a refresh callback. I will try to provide an example soon. Until then, see this commit: https://github.com/glfw/glfw/commit/cb11b7ca6f06195d361c74b8db71166f1a716047

Well that's sad. MAC OSX can't do it so no OS will be able to do it. Something about that logic just doesn't seem right. LOL

spasi

This issue exists on Windows and Linux too. If the event loop and rendering run on the same thread, blocking in the event loop will freeze rendering.

JackDawson

Quote from: SHC on June 03, 2015, 06:25:06
This can simply be solved by setting a refresh callback. I will try to provide an example soon. Until then, see this commit: https://github.com/glfw/glfw/commit/cb11b7ca6f06195d361c74b8db71166f1a716047

I was examining the COMMIT you suggested and I see this.. with an asterisk. I am not sure how to convert that to Java since that is a pointer and Java doesn't use pointers.

static void windowRefreshFun(GLFWwindow* window)

I'll just wait for your example code. Use my OP code so you don't have to write so much. ;)

JackDawson

@ SHC

Hey there, well apparently my PMs do not reach you so I am asking here. You ever get around to making that example of the refresh screen while dragging the window around ? Wasn't sure if you forgot me. ;)

Just to let you know, I tried to make a class like this to invoke it.. but it didn't work.

public class RefreshCallback extends GLFWWindowRefreshCallback {

	public void invoke(long window) {
		System.out.println("Testing !!");
	}

}

SHC

Your PMs did reach me, but I needed some time to work on my personal works (college is starting again in a few weeks), and I did get this working. All you need is two additional callbacks, glfwRefreshFun and glfwWindowSizeFun, and just trigger a render from those callbacks and swap the buffers.

https://github.com/sriharshachilakapati/SilenceEngine/blob/master/src/main/java/com/shc/silenceengine/tests/GLFWTest.java

I'm sorry, I used my OOP GLFW wrapper here, but I think you get the idea. Will convert that to a plain LWJGL example soon when I have got time.

JackDawson

Quote from: SHC on June 08, 2015, 14:00:10
Your PMs did reach me, but I needed some time to work on my personal works (college is starting again in a few weeks), and I did get this working. All you need is two additional callbacks, glfwRefreshFun and glfwWindowSizeFun, and just trigger a render from those callbacks and swap the buffers.

https://github.com/sriharshachilakapati/SilenceEngine/blob/master/src/main/java/com/shc/silenceengine/tests/GLFWTest.java

I'm sorry, I used my OOP GLFW wrapper here, but I think you get the idea. Will convert that to a plain LWJGL example soon when I have got time.

I just tested out your engine. Nice work. I tested all your test java samples in your test package. Love the text. None of the examples allowed the window to continue "painting" while dragging window around though. So I am still confused about it. I might just have to give up on the idea.

But I wanted to say thanks for sharing the engine. Great stuff.

SHC

I don't know why it didn't work for you, the GLFWTest should re-paint while moving and resizing the window. Here's a crappy GIF showing that it's working.



Other tests do not use this behaviour, it is disabled by default in the engine. You can enable it manually by setting the callbacks to the display window manually. Thanks for your compliment BTW.

Kai

@JackDawson, you are right. GLFW does not allow you to render when you are moving (or just keeping a hold of the window's title bar when holding the left mouse button on it).
If you have an animated scene (which a static triangle is not) you recognize this.
@SHC: With a static triangle it just "seems" that it is rendering when you move the window, when in fact all you see there is the back-buffered image, which was rendered before you moved the window. Use an animated render to see what JackDawson and I mean.

JackDawson

Quote from: Kai on June 13, 2015, 09:54:40
@JackDawson, you are right. GLFW does not allow you to render when you are moving (or just keeping a hold of the window's title bar when holding the left mouse button on it).
If you have an animated scene (which a static triangle is not) you recognize this.
@SHC: With a static triangle it just "seems" that it is rendering when you move the window, when in fact all you see there is the back-buffered image, which was rendered before you moved the window. Use an animated render to see what JackDawson and I mean.

@SHC
I can render a non animated scene all day long. But animated with move or resize of the screen and the screen freezes the animation. And then you let go of the mouse, the animation speeds up really fast to catch up. Try it with your movable blocks and then try to move and you will see the behavior I am speaking about.

@Kai
Exactly what I mean. Thank you for understanding. I been wracking my brain for weeks over this. A lot of posts I have read, JOGL can do it, but as you and many others have said, GLFW / LWJGL can not. I really hope this function gets added.

This guy shows it working but he obviously is not using LWJGL or JOGL. Just pure C++ and OpenGL.

http://www.songho.ca/opengl/gl_mvc.html

Scroll down to the planet scene. He has full source code and the bin files to show it works. The earth keeps spinning even while you drag the screen around. I am hoping that by showing this one of you might figure out how its done and add the functionality to LWJGL. I am a newbie when it comes to C++. So I am unable to figure this out.

On another note : Pure straight Java can do this. I have written a pure java code that animated and it would continue to do so while you drag it around. So I know Java can do it.

Kai

Turns out GLFW DOES allow you to do this! All GLFW wants is that the window proc runs in the main thread. But this restriction does not apply to the OpenGL render context.
So I just did a small example which handles window proc in the main thread that also creates the GLFW window, and then makes the OpenGL context current and does the rendering in another spawned thread!
This works (at least under Windows 7).

I modified this joml-lwjgl3-demo to make use of this.
Use this simpler demo instead.

JackDawson

Quote from: Kai on June 13, 2015, 10:29:04
Turns out GLFW DOES allow you to do this! All GLFW wants is that the window proc runs in the main thread. But this restriction does not apply to the OpenGL render context.
So I just did a small example which handles window proc in the main thread that also creates the GLFW window, and then makes the OpenGL context current and does the rendering in another spawned thread!
This works (at least under Windows 7).

I modified this joml-lwjgl3-demo to make use of this.

Awesome. I will look at your code and check it out. Thank you !!

Kai

I did a dead simple demo not requiring shaders and/or JOML: Here it is

EDIT: Now that we use separate threads, we can better use glfwWaitEvents() instead of glfwPollEvents(). The former blocks until an event can be processed and therefore does not keep that loop so busy anymore. :)

JackDawson

BOTH Demos worked Perfectly !!!!!!!!    ;D

THANK YOU THANK YOU THANK YOU !!!!!!

My day just got soooo much brighter. Now its been proven that it can work and with LWJGL3. OMG I am doing the happy dance !!  hahaha..

You guys rock !! I appreciate all this help. Finally this thread can be marked as SOLVED.