To ensure correct operation of OpenGL use ChoosePixelformat,DescribePixelformat, GetPixelformat, SetPixelformat, and SwapBuffers,instead of the wgl equivalents, wglChoosePixelformat,wglDescribePixelformat, wglGetPixelformat, wglSetPixelformat, andwglSwapBuffers. In all other cases use the wgl function whereavailable. Using the five wgl functions is only of interest todevelopers run-time linking to an OpenGL driver.
My own testing indicates that "error: 2000" occurs on some systems (Nvidia, but not Intel or a Parallels VM) if the WGL version of these functions is called. Changing to the GDI version clears this issue, but using LoadLibrary("opengl32.dll" does not appear to change anything.
Has anyone ever investigated the difference between these WGL and GDI functions? It is clear that there is some form of difference, and I am trying to understand which version should be used under which circumstances and what are the potential pitfalls if the wrong version is used.
Edit: Wayback Machine brings up a webpage that describes how direct loading of an ICD works. This was apparently required back in the Voodoo 1/2 days when the 2D and 3D accelerators were two different pieces of hardware with separate ICDs (which the normal, single-ICD mechanism in opengl32.dll couldn't handle). Quake 1 and 2 would apparently load ICDs directly because of this.
This makes sense, since Mesa3D is not supposed to be used as an ICD. This fits with the pattern in the Mesa3D thread linked above: their calls are not being routed through Microsoft's opengl32.dll, so GDI functions fail, but Mesa3D is exporting wgl* functions so these still work. However, that's specific to Mesa3D - that method would fail if you tried to use AMD's ICD directly.
There is a huge difference, namely that the prototypes for the WGL functions are not defined in any system headers. opengl32.dll exports the symbols, but unless you manually import the functions you would never know this.
opengl32.dllis basically Microsoft's GDI implementation of OpenGL and a wrapper for ICDs. You can even see what an implementation of an ICD looks like if you look at Mesa; notice how none of the functions are prefixed with wgl? ICDs do not export any wgl-prefixed symbols, the WGL functions they do implement are all extensions (e.g. wglSwapIntervalEXT (...), wglChoosePixelFormatARB (...), etc.) and can only be loaded using wglGetProcAddress (...) or DrvGetProcAddress (...).
Now, ICDs do not actually implement ChoosePixelFormat (...), as it is functionally identical across all implementations. It is a simple pattern matching function. If you want to see how opengl32.dll dispatches one of its wgl... functions to an ICD at run-time, take a look at the control flow for wglSwapBuffers:
The red left-hand branch is what occurs when an ICD is installed and the green right-hand branch is the default GDI implementation of wglSwapBuffers. Interestingly, you can see that the GDI implementation requires a full glFinish (...). Most hardware drivers will tend to flush the command queue instead of finishing when you swap buffers, this allows better CPU/GPU parallelism.
Due to the (not relevant for this question) restrictions of OpenGL implementation in Virtualbox (only OpenGL version 1.1 available, but I need at least version 2. I decided to use software implementation in form of a DLL (named opengl32.dll) which can be downloaded from here:
Important notice: All the 32 bits applications need the file opengl32.dll from the directory /win32/ of this FTP server, while all the 64 bits applications need the file opengl32.dll (same name, but it's a different file!) from the directory /win64/. Thus if I have one 32 bit and one 64 bit application in a same directory on my computer, the solution of putting the DLL into the same folder doesn't work: it's not possible to have two different files with the same name in a same directory.
Note, that on Windows 10 original OpenGL32.dll files are only accessible by TrustedInstalle