PDA

View Full Version : What is in the OpenGL API blackbox?



Southp
12-08-2008, 08:43 PM
Hello there,

First of all, I'm sorry because this question seems to be asked again and again. But after reading all the related thread, I still can't get a satisfied answer. So here I am.

In short, my question is:
1.) Where can I get the latest OpenGL implementation?
2.) How it works?

I know it's weird to put these two together. Let me explan my confusion a little more...

I've several years Direct3D development experience. Since Direct3D is all M$'s work. Where can I get the latest one? Go get a big-fat SDK, install it, and done. How it works? After installing the latest big-fat SDK, I include the latest headers, link to the latest .lib which contains dll stub info., and then my program will link to the latest dll if necessary. Simple enough!

However, for me it's a different story in OpenGL. After exhasuted searching, all I got is spec. No implementation(except Mesa), no big-fat SDK.

There was a thread said that:"it's your graphics card vendor's job to provide you the latest implementation." So I installed nVidia OpenGL 3.0 driver. Everything went well. nVidia OpenGL SDK 10 was compiled,and all examples were executed without a problem.

But HOW on earth it can be compiled and be executed?

I searched through the include path, and the only gl.h is the one in my VC declaring itself ver.1.1. The only opengl32.dll I found is the one in the system path, with description of "Microsoft corp., date: 2004".
Also, the date of the linked openGL32.lib is 2005.

With all these deprecated stuff, how comes a package implemented with the latest spec. can compile and run? How can I make sure I follow the latest spec. without a latest header at least?


Thanks for reading this long post.
Any help will be appreciated.

Simon Arbon
12-08-2008, 10:38 PM
1) The actual NVIDIA OpenGL 3.0 driver is in a file called nvoglnt.dll (or something similar, it depends on your OS version, and an ATI driver will be called something completely different)
2) You never access the above DLL directly, instead you get function pointers into it from opengl32.dll.
A program must first call SetPixelFormat and wglCreateContext so that OpenGL32.dll knows which window you want to use.
This is necisary because windows allows a computer to have more than one monitor screen, and each of them could have its own OpenGL driver.
OpenGL32.dll contains a function called "wglGetProcAddress" which is used to obtain pointers to the OpenGL 3.0 functions inside of the correct driver for that particular monitor.
You should find dozens of wglGetProcAddress calls somewhere in the SDK or VC libraries.
These load the pointers into "Function Variables" that have been defined for each specific OpenGL function, and which are then used to perform indirect calls into nvoglnt.dll.

gl.h only contains the most basic OpenGL commands, you will also need glext.h (http://www.opengl.org/registry/api/glext.h) and wglext.h (http://www.opengl.org/registry/api/wglext.h) which contain the definitions for the function pointers.
Just load the ones that you want to use using wglGetProcAddress.

Southp
12-09-2008, 10:46 PM
Hello Simon,

First of all, thanks for your comprehensive answer. It does solve my problem.

After reading your post, I went through gl.spec, glext.h, wglext.h and GLEW library which is used in nVidia OpenGL SDK 10.

I searched several functions defined in OpenGL 2.0,3.0 sections in gl.spec, and found them in glext.h. As you said, gl.h only contains a small subset of OpenGL core features. If I need to reveal all the features, at least gl.h and glext.h are necessary. wglext.h provides further functionalities to bind(or enable) them to M$ windows. To use these functions, I need to obtain the function pointer via wglGetProcAddress. For example:

PFNGLDRAWBUFFERSPROC foo = (PFNGLDRAWBUFFERSPROC)glewGetProcAddress((const GLubyte*)"glDrawBuffers"));
and the foo here will act as glDrawBuffers for me. Right?

I have a new question here...if one needs to access those functions through function pointers, why does glext.h ever declare a function prototype in it?

Let's take glDrawBuffers as an example again. In glext.h, it is declared as:

GLAPI void APIENTRY glDrawBuffers (GLsizei, const GLenum *);where GLAPI is simply an "extern", APIENTRY is an empty symbol.It seems that I can't name my function pointer "glDrawBuffers" anymore because of including glext.h.

GLEW takes a clever approach to solve this.
In GLEW's initialization function, it uses wglGetProcAddress as you said to obtain its actual function pointer:

r = ((glDrawBuffers = (PFNGLDRAWBUFFERSPROC)glewGetProcAddress((const GLubyte*)"glDrawBuffers")) == NULL) || r;
glDrawBuffers in GLEW is not only a function declaration, of course:

#define glDrawBuffers GLEW_GET_FUN(__glewDrawBuffers)
PFNGLDRAWBUFFERSPROC __glewDrawBuffers = NULL;
Finally, glew seems never include glext.h. It applies header exclusion mechanism to prevent not only that glext.h is included before it but makes the following inclusion of glext.h meaningless.

#if defined(__glext_h_) || defined(__GLEXT_H_)
#error glext.h included before glew.h
#endif

#define __glext_h_

I don't know if this is the most common way to solve the naming problem in OpenGL community, but it seems to be a little "too clever" for me. What if one needs to write OpenGL program without GLEW or any 3rd-party library? Does one need to do the same thing just for using "glDrawBuffers" as function name?

Sorry if I totally misunderstand.

Thanks again!

Simon Arbon
12-10-2008, 12:15 AM
if one needs to access those functions through function pointers, why does glext.h ever declare a function prototype in it?
You need the prototype to define the parameters of the function when you actually call it.
When you use wglGetProcAddress to store the function pointer you dont need this information, but when you use the function pointer to call the function the compiler needs the pointer variable to have been defined as the correct type so that it knows what parameters can be passed to the function and what calling convention to use to call it.

If glext.h uses glDrawBuffers as the name of the type, then just call the function variable something slightly different like gl_DrawBuffers or DrawBuffersGL.

Have you read the wiki yet?
http://www.opengl.org/wiki/index.php/Getting_started

I cant help with anything specific to C or GLEW as i dont use either of them myself.

Southp
12-10-2008, 12:48 AM
Hello Simon,

Thanks for your reply and your great patience.

And, Yes, I didn't ever notice there is a "getting start" page in the wiki. I'm sorry for that.

P.S: I found that the naming issues I described above is not quite a problem unless someone defines the symbol "GL_GLEXT_PROTOTYPES". In normal situation, all those prototypes will be filtered out by preprocessing.