[BUG] GLFW window contexts and GLContexts

Started by EnergyRay, July 05, 2014, 00:31:05

Previous topic - Next topic

EnergyRay

First, a short one:
The javadoc for GLFW.glfwMakeContextCurrent(long window) explicitly states that passing a null value will detach the current context. The GLFW documentation explicitly states that as well. However, the method performs a null pointer check causing a NullPointerException to be thrown, if the LWJGL checks are enabled, before passing the window handle to the JNI method.


Secondly, a question about some behavior:

To start rendering, there must be a current GLContext.
To make a GLContext, a window context must be current.
This is then solved with glfwMakeContextCurrent and a valid window.

But then...

Detaching the window context (leaving the GLContext current) and attempting to perform any OpenGL operations do not cause exceptions. (Window contains junk)
Destroying the GLContext... same thing, only now the window context does not exist at all. (More junk on the window)
Destroying the window itself... again, no exceptions! GLContext is still current though. (No window)

Is this intended behavior?

EDIT: Found out that you can set the current GLContext to null with GL.setCurrent(null), which I guess should be called whenever glfwMakeContextCurrent(0) is called. I still think there should be some sort of feedback on an attempt to perform GL operations in one of the above situations. It would also be useful if it was possible to poll what thread a given GLContext is current on.

EDIT 2: Changed threads to just thread (plural to singular).

spasi

Quote from: EnergyRay on July 05, 2014, 00:31:05The javadoc for GLFW.glfwMakeContextCurrent(long window) explicitly states that passing a null value will detach the current context. The GLFW documentation explicitly states that as well. However, the method performs a null pointer check causing a NullPointerException to be thrown, if the LWJGL checks are enabled, before passing the window handle to the JNI method.

Thanks, this has been fixed.

Quote from: EnergyRay on July 05, 2014, 00:31:05To start rendering, there must be a current GLContext.
To make a GLContext, a window context must be current.
This is then solved with glfwMakeContextCurrent and a valid window.

But then...

Detaching the window context (leaving the GLContext current) and attempting to perform any OpenGL operations do not cause exceptions. (Window contains junk)
Destroying the GLContext... same thing, only now the window context does not exist at all. (More junk on the window)
Destroying the window itself... again, no exceptions! GLContext is still current though. (No window)

Is this intended behavior?

GLFW contexts are externally managed contexts as far as LWJGL is concerned (and also coupled with GLFW windows). Their lifecycle is handled by GLFW, so the only LWJGL method that makes sense is GLContext.createFromCurrent(). This returns a GLContext, which basically wraps the external GLFW context. The user is then responsible for making sure that context remains valid while used.

Please note that, even though no exceptions are raised, any OpenGL functions called after clearing the current context will result in a GL_INVALID_OPERATION error.

Quote from: EnergyRay on July 05, 2014, 00:31:05EDIT: Found out that you can set the current GLContext to null with GL.setCurrent(null), which I guess should be called whenever glfwMakeContextCurrent(0) is called. I still think there should be some sort of feedback on an attempt to perform GL operations in one of the above situations. It would also be useful if it was possible to poll what threads a given GLContext is current on.

GL.getCurrent()'s behavior will be improved, I haven't yet tried to make it clever. But with externally managed contexts, you can never be 100% certain of the current state (without doing expensive queries per OpenGL call, etc). Also, OpenGL contexts can only be current in a single thread. You can use GLContext.isCurrent or platform-specific APIs (like wglGetCurrentContext) to query the current context. A properly written application should never need to do that though.

EnergyRay

I have been trying to post a reply for over a week now (session verification failed)...


QuotePlease note that, even though no exceptions are raised, any OpenGL functions called after clearing the current context will result in a GL_INVALID_OPERATION error.

Thank you for pointing that out. I had completely forgotten to enable debug output, or even performing basic GL error checking. ::)

QuoteGLFW contexts are externally managed contexts as far as LWJGL is concerned (and also coupled with GLFW windows). Their lifecycle is handled by GLFW, so the only LWJGL method that makes sense is GLContext.createFromCurrent(). This returns a GLContext, which basically wraps the external GLFW context. The user is then responsible for making sure that context remains valid while used.

How is GLContext.createFromCurrent() the only method that makes sense? What exactly is the message that is trying to be conveyed in this statement?
It looks like there are method pairs (GLFW + GL/GLContext), that should be used together:


  • GLFW.createWindow() and GLContext.createFromCurrent() (with a current GLFW context)
  • GLFW.makeContextCurrent() and GL.setCurrent()
  • GLFW.getCurrentContext() and GL.getCurrent()
  • GLFW.destroyWindow() and someGLContextInstance.destroy()

Or have I completely missed the point of these methods?

QuoteGL.getCurrent()'s behavior will be improved, I haven't yet tried to make it clever. But with externally managed contexts, you can never be 100% certain of the current state (without doing expensive queries per OpenGL call, etc).

Hopefully the ability to query the thread a context is attached to is planned. The ability to get the thread instances would help setting up, for example, a messaging system for dealing with contexts. Especially in the pesky situation where you need to, say, transfer a context (for one reason or another). This requires you to first detach the context on the owner thread, and then attach it on the new thread. At least I'm pretty certain attaching won't detach it from a different thread.

QuoteAlso, OpenGL contexts can only be current in a single thread.

I accidentally wrote it in plural where it should have been singular. I'll correct it once the forums start working for me again.

EDIT: Grammar and other corrections.

spasi

Quote from: EnergyRay on July 16, 2014, 23:37:32How is GLContext.createFromCurrent() the only method that makes sense? What exactly is the message that is trying to be conveyed in this statement?
It looks like there are method pairs (GLFW + GL/GLContext), that should be used together:


  • GLFW.createWindow() and GLContext.createFromCurrent() (with a current GLFW context)
  • GLFW.makeContextCurrent() and GL.setCurrent()
  • GLFW.getCurrentContext() and GL.getCurrent()
  • GLFW.destroyWindow() and someGLContextInstance.destroy()

Or have I completely missed the point of these methods?

When using GLFW, you should only call the GLFW APIs. The OpenGL context is created and managed internally by GLFW. For example, calling glfwDestroyWindow destroys both the GLFW window and the OpenGL context associated with it; there's no need to call the GLContext destroy method (simply throw away the reference, the native context has already been destroyed). With that in mind, GLContext.createFromCurrent is most likely the only method you need.

Other context management methods can still be called, if you're doing something fancy, but you should be very careful to avoid conflicts with externally managed contexts.

Quote from: EnergyRay on July 16, 2014, 23:37:32Hopefully the ability to query the thread a context is attached to is planned. The ability to get the thread instances would help setting up, for example, a messaging system for dealing with contexts. Especially in the pesky situation where you need to, say, transfer a context (for one reason or another). This requires you to first detach the context on the owner thread, and then attach it on the new thread. At least I'm pretty certain attaching won't detach it from a different thread.

That's true, but I'm having trouble understanding why you'd need to do query the current thread. Your application should be able to store the necessary state when doing the makeCurrent calls and have all the information it needs when it's time to transfer.

EnergyRay

I seem to need to completely nuke all cookies and temp files before I can post anything on the forums... Darn, "Session verification failed" error!


QuoteWhen using GLFW, you should only call the GLFW APIs. The OpenGL context is created and managed internally by GLFW. For example, calling glfwDestroyWindow destroys both the GLFW window and the OpenGL context associated with it; there's no need to call the GLContext destroy method (simply throw away the reference, the native context has already been destroyed). With that in mind, GLContext.createFromCurrent is most likely the only method you need.

Other context management methods can still be called, if you're doing something fancy, but you should be very careful to avoid conflicts with externally managed contexts.

It seems that I have misunderstood the usage of the GLContext related functions... For clarification: Is the GL.setCurrent() needed when attaching / detaching a context, or just glfwMakeContextCurrent? And may I ask why exactly this functionality exists if most of it does not need to be / should not be used? For wrapping a native context created with, say, Win32?

QuoteThat's true, but I'm having trouble understanding why you'd need to do query the current thread. Your application should be able to store the necessary state when doing the makeCurrent calls and have all the information it needs when it's time to transfer.

My application does indeed store the thread a context is attached to. In order to simplify (in terms of an interface) the context transfer, or even window destroying, I am currently mapping threads to what are basically queues of runnables. This allows me to send, for example, a command to detach a context from another thread and then wait for the action to be performed on the other thread. Before-hand knowledge of the context's thread is required to pick the correct thread. This is currently one of the cleanest ways of performing these operations that I've thought of. There's probably even better ways, but for now this is what I have. Anyways, getting slightly off-topic.

Reason why I think the thread querying should be added is, if someone desires that information it needs to be added in by the user. While it is quite easy to add this functionality, it would still mean less what is almost entirely boilerplate code.

spasi

Quote from: EnergyRay on July 17, 2014, 23:37:37It seems that I have misunderstood the usage of the GLContext related functions... For clarification: Is the GL.setCurrent() needed when attaching / detaching a context, or just glfwMakeContextCurrent? And may I ask why exactly this functionality exists if most of it does not need to be / should not be used? For wrapping a native context created with, say, Win32?

I was talking about GLContext methods, not the ones in GL. GL.setCurrent is required when you already have a GLContext instance and the associated native context has been made current in the current thread via an external mechanism (e.g. glfwMakeContextCurrent). The GLContext methods (makeCurrent and destroy) should be used when the underlying native context has been created with LWJGL (e.g. using the WGL or GLX bindings).