What does GL.createCapabilities() exactly do?

Started by Nox, December 11, 2018, 19:52:49

Previous topic - Next topic

Nox

Hello everyone, I'm completly new here and got stuck on a problem.

So I'm trying to create a window using GLFW and came across this function called createCapabilities(). To my understanding this function creates the OpenGl context, for the given window in the parameters. But then I read in the documention that glfwCreateWindow() already creates a context. Why are there two contexts? Do you need both of them? Or did I get something wrong?

Nox 

KaiHH

The native OpenGL context itself is created by GLFW's native code when calling glfwCreateWindow and made current in the calling thread when calling glfwMakeContextCurrent. LWJGL's GL.createCapabilities() is more like GLEW's glewInit() if you know that from the native/C/C++ world. In order to actually call OpenGL functions, the OpenGL client application has to use platform-specific APIs to query the function pointers for all OpenGL functions by string. That is because the function addresses need not be constant for all OpenGL contexts but can differ by context, so an OpenGL client application actually needs to resolve the function addresses of OpenGL functions such as glCreateShader or glBindBuffer etc. dynamically at runtime via a platform API.
So, what LWJGL's GL.createCapabilities() - or more precisely the GLCapabilities class - does is to query the underlying function pointer addresses for all known OpenGL functions that are declared in any LWJGL OpenGL class, such as GL11..GL46.
In addition, GL.createCapabilities() also loads the names of all available OpenGL extensions and parses the effective OpenGL version.

Nox

Ok, thanks for your answer. I think I got it now ... but why does this need to be a seperate step? Why not just do it with createWindow() as well? It seems like something you would always do together.

Nox

KaiHH

Quote from: Nox on December 11, 2018, 20:24:55
but why does this need to be a seperate step? Why not just do it with createWindow() as well? It seems like something you would always do together.
Not necessarily. If you use Vulkan, then GLFW won't create any OpenGL context. Likewise, if you use OpenGL ES then GL.createCapabilities() would also be wrong. It depends on the graphics API you use on top of GLFW windowing.
LWJGL could _in theory_ also intercept other GLFW calls that tell GLFW whether or not to create a context for any graphics API, but that would interfere with LWJGL wanting to be as lightweight as possible and that would also drag library-dependent decisions/code into LWJGL code and make LWJGL depend on the behaviour of such libraries instead of just the (syntactic) API.

Nox

Ok, and does
Quote from: KaiHH on December 11, 2018, 20:06:54
That is because the function addresses need not be constant for all OpenGL contexts but can differ by context, so an OpenGL client application actually needs to resolve the function addresses of OpenGL functions such as glCreateShader or glBindBuffer etc. dynamically at runtime via a platform API.
mean, that if I have two contexts and in both i use glCreateShader() that the adress for glCreateShader() in one context is different from the one in the other?

KaiHH


Nox

Thanks. It's a lot harder then I thought I would be, but I'm getting there ... very slowly ... :D Oh and one last question (I promise): I still dont get why I have to tell OpenGL to get the adresses of  the functions. For instance why don't I have to do that for java if I want to call System.out.println() or any other method provided by java? And if java does that automatically, why doesn't openGL?

Nox

Cornix

Because OpenGL is NOT a library. It is not software. It is a standard; an idea.

The world has decided to use this standard. It is implemented through software and hardware. All the implementations are possibly very different from each other but they are all supposed to do the same thing.

Java on the other hand is a programming language coupled with a runtime enviroment. It is software through and through.

KaiHH

Quote from: Nox on December 11, 2018, 21:01:37I still dont get why I have to tell OpenGL to get the adresses of  the functions. For instance why don't I have to do that for java if I want to call System.out.println() or any other method provided by java? And if java does that automatically, why doesn't openGL?
The API provided by the JVM to Java programs and the calling conventions of those methods is obviously something completely different compared to a native library such as OpenGL. First of all, when code such as `System.out.println()` is executed, that Java code is first translated to JVM bytecode which is then either interpreted or JIT-compiled to native code and linked to the called target method at runtime when the class is first loaded. Explaining everything that happens there would definitely completely blow the scope of a single forum post. I highly recommend reading the Java Virtual Machine Specification if you want to know all of that in-depth. What this distilles to is that the JVM actually is a platform with its own Instruction Set Architecture (ISA), its own application binary interface (ABI) if you will - which would be the JVM bytecode - and its own linking procedure for resolving classes, methods etc.
Calling an external native library such as OpenGL is something completely different, which also would completely blow the scope of a single forum post.
You have to know about C function linking, shared object file formats, the dynamic linker of the operating system, etc. etc. etc. to get all of this into one picture.
Just take away that LWJGL effectively calls JNI (Java Native Interface) methods - which is the JVM's way to interact with non-JVM external native functions - to call OpenGL functions. And all of such functions are accessible via a function address inside of the processe's address space. And in order to obtain such an address, there are multiple ways: either dynamic linking, in which case the dynamic loader of the OS will resolve the function addresses at load time or call time of the function or via copying the function into the own executable when statically linking the code, or via providing an actual API to obtain such function addresses, which is OpenGL's way.

Nox

Thank you for sticking with me, I really appreciate your help. :)

KaiHH

Sure. :) If you want you could probably start working with OpenGL in a native language instead of Java/LWJGL, to get to know that world as well. Some things are easier while others are much harder than with Java. But working with native code (especially C) will probably help in understanding all that function pointer stuff.