Difference between revisions of "Platform specifics: Windows"

From OpenGL Wiki
Jump to: navigation, search
m (When do I render my scene?)
m
 
(25 intermediate revisions by 7 users not shown)
Line 1: Line 1:
====Compiler errors and gl.h====
+
This article describes Windows-specific behavior of OpenGL programs.
 +
 
 +
=== Compiler errors and gl.h ===
 
If you get compiler errors pointing to gl.h, this is because there are some things like WINGDI which are used in gl.h but are only defined in some other header files. Include windows.h before including gl.h<br>
 
If you get compiler errors pointing to gl.h, this is because there are some things like WINGDI which are used in gl.h but are only defined in some other header files. Include windows.h before including gl.h<br>
 
If you have link errors, then you need to figure out how to link with your specific compiler/IDE.<br>
 
If you have link errors, then you need to figure out how to link with your specific compiler/IDE.<br>
Line 7: Line 9:
 
Other compiler/IDE mind need to link with opengl32.a<br>
 
Other compiler/IDE mind need to link with opengl32.a<br>
  
====What should I do before the window is created?====
+
=== What should I do before the window is created? ===
 
Be sure to use the CS_OWNDC flag.<br>
 
Be sure to use the CS_OWNDC flag.<br>
 
If you are doing plain old WinMain coding, RegisterClassEx() takes the WNDCLASSEX structure.<br>
 
If you are doing plain old WinMain coding, RegisterClassEx() takes the WNDCLASSEX structure.<br>
Line 20: Line 22:
  
  
====When is a good time to create the GL context?====
+
=== When is a good time to create the GL context? ===
 
When the WM_CREATE message is sent.<br>
 
When the WM_CREATE message is sent.<br>
 
This is when the window is created (has a valid HWND and DC).<br>
 
This is when the window is created (has a valid HWND and DC).<br>
Line 28: Line 30:
 
<br>
 
<br>
  
====It's flickering! Why?====
+
=== It's flickering! Why? ===
 
Windows sends a WM_ERASEBKGND message when the background needs to be erased.<br>
 
Windows sends a WM_ERASEBKGND message when the background needs to be erased.<br>
 
Tell Windows that you handled the message by returning a non-zero number (TRUE).<br>
 
Tell Windows that you handled the message by returning a non-zero number (TRUE).<br>
Line 34: Line 36:
 
<br>
 
<br>
  
====When do I render my scene?====
+
=== When do I render my scene? ===
 
Answer to this question depends on the situation:
 
Answer to this question depends on the situation:
 
* For application like CAD, 3D model viewer or anything that doesn't require constant updating, render when you receive the [http://msdn.microsoft.com/en-us/library/dd145213%28VS.85%29.aspx WM_PAINT] message
 
* For application like CAD, 3D model viewer or anything that doesn't require constant updating, render when you receive the [http://msdn.microsoft.com/en-us/library/dd145213%28VS.85%29.aspx WM_PAINT] message
Line 43: Line 45:
 
* If you are developing game or dynamic visualisation in window (not fullscreen), consider setting up a timer and render only when receiving [http://msdn.microsoft.com/en-us/library/ms644902%28VS.85%29.aspx WM_TIMER] message. You will be still able to get high framerate, but your program will not eat so much CPU resources
 
* If you are developing game or dynamic visualisation in window (not fullscreen), consider setting up a timer and render only when receiving [http://msdn.microsoft.com/en-us/library/ms644902%28VS.85%29.aspx WM_TIMER] message. You will be still able to get high framerate, but your program will not eat so much CPU resources
  
* If you develop fullscreen application, do not render when user ALT-TABs from your program. You can detect this by handling [http://msdn.microsoft.com/en-us/library/ms632614%28VS.85%29.aspx WM_ACTIVATEAPP]. This will again prevent CPU "hogging" when it is not necessary
+
* If you are developing fullscreen application, do not render when user ALT-TABs from your program. You can detect this by handling [http://msdn.microsoft.com/en-us/library/ms632614%28VS.85%29.aspx WM_ACTIVATEAPP]. This will again prevent CPU "hogging" when it is not necessary
  
  
Line 56: Line 58:
 
For MFC, override OnPaint or OnDraw (depending on the parent class)
 
For MFC, override OnPaint or OnDraw (depending on the parent class)
  
====When do I destroy the GL context?====
+
=== When do I destroy the GL context? ===
 
Some people do it when the WM_DESTROY message is received. In my experience, this is not correct because at this point, the window resources and DC are destroyed already. Functions like wglMakeCurrent may fail.<br>
 
Some people do it when the WM_DESTROY message is received. In my experience, this is not correct because at this point, the window resources and DC are destroyed already. Functions like wglMakeCurrent may fail.<br>
 
Try the following: call wglMakeCurrent(NULL, NULL) followed by wglMakeCurrent(hdc, hglrc).<br>
 
Try the following: call wglMakeCurrent(NULL, NULL) followed by wglMakeCurrent(hdc, hglrc).<br>
Line 68: Line 70:
  
  
====How many times can I call SetPixelFormat?====
+
=== How many times can I call SetPixelFormat? ===
 
For each window, once. According to MSDN, it would lead to significant complications if they allowed for more flexibility.<br>
 
For each window, once. According to MSDN, it would lead to significant complications if they allowed for more flexibility.<br>
 
Never call GetDC(NULL) and then call SetPixelFormat. This gives the DC for the entire desktop. Instead, create a fullscreen window.<br>
 
Never call GetDC(NULL) and then call SetPixelFormat. This gives the DC for the entire desktop. Instead, create a fullscreen window.<br>
  
====Multiple Windows====
+
=== PFD_DRAW_TO_BITMAP ===
 +
This flag is for making an offscreen render buffer onto with you render with your GL commands. Typically, people do this so that they can BitBlt the result to a window or a BitBlt to a printer device context or so that they can use some Win32 commands on that same surface.
 +
 
 +
A few source code examples from 1995 show how to use PFD_DRAW_TO_BITMAP.
 +
 
 +
You should avoid using this flag during context creation, as it may cause you to not get a hardware-accelerated rendering context. It will give you the Microsoft OpenGL version 1.1 software renderer.
 +
 
 +
=== Partial Screen Update ===
 +
Certain types of software maintain multiple viewports on a single window. They render a "right view", "left view", "top view" and "preview" of the same model. The programmer might decide that "preview" needs updating but the other views do not.
 +
 
 +
In this case, you would need to select a pixelformat that supports PFD_SWAP_COPY. PFD_SWAP_COPY means that the backbuffer will be copied to the front buffer when you call SwapBuffers. Without that flag, it would be just swap pointers between front and back buffer. Switching pointers is much faster than a buffer copy. You need setup a scissor area with glScissor and enable scissoring. Then call glClear to clear only the scissor area. Now you can render and call SwapBuffers.
 +
 
 +
There might be some performance loss because these days graphics cards expect that you clear the entire screen. You should benchmark and see if there are any benefits. If there aren't, select another render path in your engine where you update the entire window.
 +
 
 +
=== Multiple Windows ===
 
If your project opens other windows and you want GL on the other window as well, in each function that you have, call wglMakeCurrent(hdc, glrc) and when
 
If your project opens other windows and you want GL on the other window as well, in each function that you have, call wglMakeCurrent(hdc, glrc) and when
 
you are done call wglMakeCurrent(NULL, NULL)<br>
 
you are done call wglMakeCurrent(NULL, NULL)<br>
Line 86: Line 102:
  
 
=== wglShareLists ===
 
=== wglShareLists ===
According to MSDN, wglShareLists shares display list space between 2 GL contexts. MSDN is outdated and full of errors.<br>
+
According to MSDN, wglShareLists shares display list space between 2 GL contexts. The MSDN documentation is incomplete. This function allows the sharing of other objects. In addition to display lists, this function allows sharing of [[Texture|textures]], [[Renderbuffer Object|renderbuffers]], and [[Buffer Object|buffer objects]]. Only these object types are shared among GL contexts.
This function allows you to share textures, VBOs, shaders, etc. Be careful because some GL object might not be shareable (NV_fence). Read each extension's specification carefully.<br>
+
 
The best time to call wglShareLists is when you create the 2 GL contexts (yes, you can create many more and share between all of them), and just after call wglShareLists. So the best time to call it is as soon as possible, even before you create any textures or VBOs, otherwise there is a risk that wglShareLists will fail.<br>
+
The best time to call wglShareLists is after creating the GL contexts you want to share, but ''before'' you create any objects in either of the contexts. If you create objects, then there is a chance that wglShareLists will fail.
Note that under *nix systems, there is no wglShareLists. Sharing is enabled at context creation time. This is a better design as it makes drivers simpler. Perhaps one day the ARB will have a better solution in the form of an extension.
+
 
 +
Sharing can also be done as part of context creation, using wglCreateContextAttribsARB. This is analogous to how *nix systems do it, and you don't have to worry about not creating objects in the new context, since creation and sharing are done simultaneously.
 +
  HGLRC wglCreateContextAttribsARB(HDC hDC, HGLRC hShareContext, const int *attribList)
 +
 
 +
The 2nd parameter to wglCreateContextAttribsARB is a previously created GL context. wglCreateContextAttribsARB is part of the WGL_ARB_create_context extension which was introduced in parallel to when GL 3.0 was introduced. WGL_ARB_create_context can be found in the string returned by wglGetExtensionsStringARB(hdc)
 +
 
 +
http://www.opengl.org/registry/specs/ARB/wgl_create_context.txt
 +
 
 +
Programs written for GL 3.0 and above should make use of WGL_ARB_create_context. Even programs that try to create for example an old context such as 2.1 with wglCreateContextAttribsARB can also use it to share resources.
  
 
=== SwapInterval aka vsync ===
 
=== SwapInterval aka vsync ===
 
If you need information on WGL_EXT_swap_control which gives wglSwapIntervalEXT, read<br>
 
If you need information on WGL_EXT_swap_control which gives wglSwapIntervalEXT, read<br>
http://www.opengl.org/wiki/index.php/SwapInterval_aka_vsync
+
[[SwapInterval aka vsync]]
 +
 
 +
=== wglGetProcAddress ===
 +
This function is for getting a pointer to OpenGL functions. More details can be found in the article on [[Load OpenGL Functions |loading OpenGL function pointers]].
 +
 
 +
wglGetProcAddress requires a GL context to be created and to be made current (wglMakeCurrent) for it to work, otherwise, it will return NULL for every call.
 +
 
 +
=== The Default Renderer ===
 +
In this section, we'll talk about the default GL implementation of Microsoft.
 +
 
 +
The original Windows 95 did not have OpenGL. You had to download an installer from Microsoft called opengl95a.exe and run it.
  
=== wglGetProcAddress===
+
Windows 95b came with GL. It included a GL 1.1 software renderer. Windows NT 4 also came with a GL 1.1 software renderer. There were a few screensavers that utilized GL : for example the screensaver with the maze.
This function is for getting a pointer to a function. Since on Windows, opengl32.dll will never get updated, opengl32.dll only provides the GL 1.1 functionality subset. To get the higher ones, you need wglGetProcAddress. Note that wglGetProcAddress gives a direct pointer to the real opengl driver implemented by your IHV, so you get to bypass opengl32.dll. This doesn't mean your GL code will run faster. In the case of modern games, they are often fill rate limited due to the enormous about of pixels they need to render.
 
  
=== What about the WGL functions? ===
+
The case for Windows 98, 98SE, Me, 2000 was the same : they came with the same GL 1.1 software renderer and the same GL screensavers.
 +
 
 +
Windows XP changed things a bit. opengl32.dll now utilized Direct3D and since Windows comes with drivers for your hardware, the renderer was fast. The GL screensavers were rewritten to use Direct3D, probably version 8 since Windows XP came with DirectX 8.
 +
 
 +
For Windows Vista, Microsoft had announced that they will update their renderer to GL 1.4. My own experience shows that it is actually a GL 1.1 software renderer. For some reason, Microsoft decided to remove the Direct3D wrapper from opengl32.dll.
 +
 
 +
=== The WGL functions ===
 
We call them the "wiggle" functions.<br>
 
We call them the "wiggle" functions.<br>
 
There are many wgl functions and some aren't even documented in MSDN.<br>
 
There are many wgl functions and some aren't even documented in MSDN.<br>
Mostly, you will only need :<br>
+
Mostly, you will only need :
*wglCreateContext<br>
+
*wglCreateContext
*wglDeleteContext<br>
+
*wglDeleteContext
*wglMakeCurrent<br>
+
*wglMakeCurrent
*wglShareLists<br>
+
*wglShareLists
<br>
+
 
  
If you are writing an GL extension loader, you will make plenty use of wglGetProcAddress.<br>
+
If you are writing an GL extension loader, you will make plenty use of wglGetProcAddress.
<br>
 
  
I don't recommend that you use some of these wgl functions :<br>
+
I don't recommend that you use some of these wgl functions :
*ChoosePixelFormat instead of wglChoosePixelFormat<br>
+
*Use ChoosePixelFormat instead of wglChoosePixelFormat
*DescribePixelFormat instead of wglDescribePixelFormat<br>
+
*Use DescribePixelFormat instead of wglDescribePixelFormat
*SetPixelFormat instead of wglSetPixelFormat<br>
+
*Use SetPixelFormat instead of wglSetPixelFormat
*GetPixelFormat instead of wglGetPixelFormat<br>
+
*Use GetPixelFormat instead of wglGetPixelFormat
*SwapBuffers instead of wglSwapBuffers<br>
+
*Use SwapBuffers instead of wglSwapBuffers
<br>
 
  
 
==== glX vs wgl ====
 
==== glX vs wgl ====
This is a list of glX functions and there equivalent wgl functions. There migth be some missing entries.<br>
+
This is a list of glX functions and their equivalent wgl functions. There might be some missing entries.
<br>
+
 
glXChooseVisual --- ChoosePixelFormat<br>
+
*glXChooseVisual --- ChoosePixelFormat
glXCopyContext  —-- NULL<br>
+
*glXCopyContext  —-- NULL
glXCreateContext --- wglCreateContext<br>
+
*glXCreateContext --- wglCreateContext
glXCreateGLXPixmap --- CreateDIBitmap and CreateDIBSection<br>
+
*glXCreateGLXPixmap --- CreateDIBitmap and CreateDIBSection
glXDestroyContext --- wglDeleteContext<br>
+
*glXDestroyContext --- wglDeleteContext
glXDestroyGLXPixmap --- DeleteObject<br>
+
*glXDestroyGLXPixmap --- DeleteObject
glXGetConfig --- DescribePixelFormat<br>
+
*glXGetConfig --- DescribePixelFormat
glXGetCurrentContext --- wglGetCurrentContext<br>
+
*glXGetCurrentContext --- wglGetCurrentContext
glXGetCurrentDrawable --- wglGetCurrentDC <br>
+
*glXGetCurrentDrawable --- wglGetCurrentDC
glXIsDirect —-- NULL<br>
+
*glXIsDirect —-- NULL
glXMakeCurrent --- wglMakeCurrent <br>
+
*glXMakeCurrent --- wglMakeCurrent
glXQueryExtension ---- GetVersion <br>
+
*glXQueryExtension ---- GetVersion
glXQueryVersion --- GetVersion <br>
+
*glXQueryVersion --- GetVersion
glXSwapBuffers --- SwapBuffers <br>
+
*glXSwapBuffers --- SwapBuffers
glXUseXFont wglUseFontBitmaps and wglUseFontOutlines <br>
+
*glXUseXFont wglUseFontBitmaps and wglUseFontOutlines
glXWaitGL —-- NULL<br>
+
*glXWaitGL —-- NULL
glXWaitX --— NULL<br>
+
*glXWaitX --— NULL
XGetVisualInfo --- GetPixelFormat <br>
+
*XGetVisualInfo --- GetPixelFormat
XCreateWindow --- CreateWindow/CreateWindowEx and GetDC/BeginPaint <br>
+
*XCreateWindow --- CreateWindow/CreateWindowEx and GetDC/BeginPaint
XSync GdiFlush <br>
+
*XSync GdiFlush
NULL —-- SetPixelFormat <br>
+
*NULL —-- SetPixelFormat
glXGetProcAddress --— wglGetProcAddress <br>
+
*glXGetProcAddress --— wglGetProcAddress
NULL —-- wglShareLists <br>
+
*NULL —-- wglShareLists
<br>
+
 
 +
=== Installing Mesa3D on Windows ===
 +
 
 +
If your system does not contain a GPU, or the GPU vendor delivers graphics drivers providing OpenGL support that's so old as to be useless to you, you might want to consider installing the [https://mesa3d.org/ Mesa3D] OpenGL library on your system to provide OpenGL support.
 +
 
 +
[https://mesa3d.org/ Mesa3D] is a graphics library that provides an OpenGL implementation for multiple platforms.  GPU hardware acceleration is supported on some GPUs, with a software (CPU) rendering pipeline generally available as a fallback or alternative rendering method (see [https://mesamatrix.net/ Mesa3D Support Matrix]).
 +
 
 +
For experienced developers that choose to build Mesa3D libraries from source, here are a few guides on how to download, build, and install Mesa3D:
 +
 
 +
* [https://www.mesa3d.org/download.html Downloading, Compiling, and Installing Mesa3d] (Mesa3D)
 +
* [https://fdossena.com/?p=mesa/build.frag Building Mesa3D on Windows] (Dossena)
 +
* [https://wiki.qt.io/MesaLlvmpipe How to build Mesa for software rendering with llvmpipe on Windows with Visual Studio 2017 (llvmpipe)] (Qt)
 +
 
 +
For beginning developers and others which don't have the time or desire to build Mesa3D libraries from source, here are some pre-built Windows installer (EXE) images.  Options are provided to install the Mesa3D OpenGL libraries either system-wide or per-application:
 +
 
 +
* [https://github.com/pal1000/mesa-dist-win/releases mesa-dist-win - Mesa3D Windows Installers] (pal1000)
 +
* [https://github.com/pal1000/mesa-dist-win/ mesa-dist-win - Installation and Usage Instructions] (pal1000)

Latest revision as of 19:35, 8 September 2018

This article describes Windows-specific behavior of OpenGL programs.

Compiler errors and gl.h

If you get compiler errors pointing to gl.h, this is because there are some things like WINGDI which are used in gl.h but are only defined in some other header files. Include windows.h before including gl.h
If you have link errors, then you need to figure out how to link with your specific compiler/IDE.
Example : with VC++6 (which is very old by now), you go to Project->Settings and click on the links tab.
Add opengl32.lib to the Object/library modules list.
If you use other libs like GLU, add glu32.lib.
Other compiler/IDE mind need to link with opengl32.a

What should I do before the window is created?

Be sure to use the CS_OWNDC flag.
If you are doing plain old WinMain coding, RegisterClassEx() takes the WNDCLASSEX structure.
WNDCLASSEX.style should have the CS_OWNDC
If you are using MFC (SDI or MDI project), override PreCreateWindow and add the CS_OWNDC to cs.
For CDialog based project, PreCreateWindow doesn't get called.
This flag is really needed for Win9x systems.
Since DCs (device contexts) consume resources, the OS does not assign a DC but might share it between multiple windows and GUI elements.
On WinNT and its derivatives, it is said that resources are not a problem and it assigns a unique DC per window.
For good practice, I recommend using CS_OWNDC.


When is a good time to create the GL context?

When the WM_CREATE message is sent.
This is when the window is created (has a valid HWND and DC).
Normally, the window is visible at this point. Even if you create a invisible window, this is the place to create the GL context.
This is also a good place to make the context current, setup some GL states and setup some things for your program.
For MFC, you override the OnCreate function for your "View" class.

It's flickering! Why?

Windows sends a WM_ERASEBKGND message when the background needs to be erased.
Tell Windows that you handled the message by returning a non-zero number (TRUE).
On MFC, override OnEraseBkgnd and just return TRUE.

When do I render my scene?

Answer to this question depends on the situation:

  • For application like CAD, 3D model viewer or anything that doesn't require constant updating, render when you receive the WM_PAINT message
  • For high performance game do not use WM_PAINT and render directly from your "infinite loop"


Besides this simple division, please consider following advices:

  • If you are developing game or dynamic visualisation in window (not fullscreen), consider setting up a timer and render only when receiving WM_TIMER message. You will be still able to get high framerate, but your program will not eat so much CPU resources
  • If you are developing fullscreen application, do not render when user ALT-TABs from your program. You can detect this by handling WM_ACTIVATEAPP. This will again prevent CPU "hogging" when it is not necessary


To render image on the screen, you can follow this simple scheme:

 glClear( ... )      // Clear the color/depth/stencil buffer  
 //
 //  Draw your geometry using OpenGL commands here 
 //
 SwapBuffers( ... )  // Swap buffers to make geometry visible on screen


To swap buffers, use SwapBuffers instead of wglSwapBuffers.
For MFC, override OnPaint or OnDraw (depending on the parent class)

When do I destroy the GL context?

Some people do it when the WM_DESTROY message is received. In my experience, this is not correct because at this point, the window resources and DC are destroyed already. Functions like wglMakeCurrent may fail.
Try the following: call wglMakeCurrent(NULL, NULL) followed by wglMakeCurrent(hdc, hglrc).
The second call will(might) fail.
Instead, destroy the GL context when the WM_CLOSE message is received. With MFC, override OnClose.
Don't forget to deallocate your textures, display lists, VBOs, PBOs, FBOs, shaders, etc before destroying the GL context.
It is good programming practice to release resources!
Call wglMakeCurrent(NULL, NULL) to make the GL context non-current.
Call wglDeleteContext(glrc) to destroy the GL context.
If you have allocated a DC for your window, release it and/or destroy it (ReleaseDC and/or DeleteDC)


How many times can I call SetPixelFormat?

For each window, once. According to MSDN, it would lead to significant complications if they allowed for more flexibility.
Never call GetDC(NULL) and then call SetPixelFormat. This gives the DC for the entire desktop. Instead, create a fullscreen window.

PFD_DRAW_TO_BITMAP

This flag is for making an offscreen render buffer onto with you render with your GL commands. Typically, people do this so that they can BitBlt the result to a window or a BitBlt to a printer device context or so that they can use some Win32 commands on that same surface.

A few source code examples from 1995 show how to use PFD_DRAW_TO_BITMAP.

You should avoid using this flag during context creation, as it may cause you to not get a hardware-accelerated rendering context. It will give you the Microsoft OpenGL version 1.1 software renderer.

Partial Screen Update

Certain types of software maintain multiple viewports on a single window. They render a "right view", "left view", "top view" and "preview" of the same model. The programmer might decide that "preview" needs updating but the other views do not.

In this case, you would need to select a pixelformat that supports PFD_SWAP_COPY. PFD_SWAP_COPY means that the backbuffer will be copied to the front buffer when you call SwapBuffers. Without that flag, it would be just swap pointers between front and back buffer. Switching pointers is much faster than a buffer copy. You need setup a scissor area with glScissor and enable scissoring. Then call glClear to clear only the scissor area. Now you can render and call SwapBuffers.

There might be some performance loss because these days graphics cards expect that you clear the entire screen. You should benchmark and see if there are any benefits. If there aren't, select another render path in your engine where you update the entire window.

Multiple Windows

If your project opens other windows and you want GL on the other window as well, in each function that you have, call wglMakeCurrent(hdc, glrc) and when you are done call wglMakeCurrent(NULL, NULL)
Example:

 wglMakeCurrent(hdc, glrc);
 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
 RenderThis();
 RenderThat();
 SwapBuffers(hdc);
 wglMakeCurrent(NULL, NULL);

This is because a GL context can be current to 1 thread. Since window 1 has a GL context and window 2 has a GL context, both can't be current at the same time. You can either create a window in another thread, this way each context is in its own thread, or if both windows use the same pixelformat, use 1 GL context for both windows. In the 2 window 1 context case, you still have to call wglMakeCurrent(hdc, glrc) wglMakeCurrent(NULL, NULL) because the hdc would be different for each window.

wglShareLists

According to MSDN, wglShareLists shares display list space between 2 GL contexts. The MSDN documentation is incomplete. This function allows the sharing of other objects. In addition to display lists, this function allows sharing of textures, renderbuffers, and buffer objects. Only these object types are shared among GL contexts.

The best time to call wglShareLists is after creating the GL contexts you want to share, but before you create any objects in either of the contexts. If you create objects, then there is a chance that wglShareLists will fail.

Sharing can also be done as part of context creation, using wglCreateContextAttribsARB. This is analogous to how *nix systems do it, and you don't have to worry about not creating objects in the new context, since creation and sharing are done simultaneously.

 HGLRC wglCreateContextAttribsARB(HDC hDC, HGLRC hShareContext, const int *attribList)

The 2nd parameter to wglCreateContextAttribsARB is a previously created GL context. wglCreateContextAttribsARB is part of the WGL_ARB_create_context extension which was introduced in parallel to when GL 3.0 was introduced. WGL_ARB_create_context can be found in the string returned by wglGetExtensionsStringARB(hdc)

http://www.opengl.org/registry/specs/ARB/wgl_create_context.txt

Programs written for GL 3.0 and above should make use of WGL_ARB_create_context. Even programs that try to create for example an old context such as 2.1 with wglCreateContextAttribsARB can also use it to share resources.

SwapInterval aka vsync

If you need information on WGL_EXT_swap_control which gives wglSwapIntervalEXT, read
SwapInterval aka vsync

wglGetProcAddress

This function is for getting a pointer to OpenGL functions. More details can be found in the article on loading OpenGL function pointers.

wglGetProcAddress requires a GL context to be created and to be made current (wglMakeCurrent) for it to work, otherwise, it will return NULL for every call.

The Default Renderer

In this section, we'll talk about the default GL implementation of Microsoft.

The original Windows 95 did not have OpenGL. You had to download an installer from Microsoft called opengl95a.exe and run it.

Windows 95b came with GL. It included a GL 1.1 software renderer. Windows NT 4 also came with a GL 1.1 software renderer. There were a few screensavers that utilized GL : for example the screensaver with the maze.

The case for Windows 98, 98SE, Me, 2000 was the same : they came with the same GL 1.1 software renderer and the same GL screensavers.

Windows XP changed things a bit. opengl32.dll now utilized Direct3D and since Windows comes with drivers for your hardware, the renderer was fast. The GL screensavers were rewritten to use Direct3D, probably version 8 since Windows XP came with DirectX 8.

For Windows Vista, Microsoft had announced that they will update their renderer to GL 1.4. My own experience shows that it is actually a GL 1.1 software renderer. For some reason, Microsoft decided to remove the Direct3D wrapper from opengl32.dll.

The WGL functions

We call them the "wiggle" functions.
There are many wgl functions and some aren't even documented in MSDN.
Mostly, you will only need :

  • wglCreateContext
  • wglDeleteContext
  • wglMakeCurrent
  • wglShareLists


If you are writing an GL extension loader, you will make plenty use of wglGetProcAddress.

I don't recommend that you use some of these wgl functions :

  • Use ChoosePixelFormat instead of wglChoosePixelFormat
  • Use DescribePixelFormat instead of wglDescribePixelFormat
  • Use SetPixelFormat instead of wglSetPixelFormat
  • Use GetPixelFormat instead of wglGetPixelFormat
  • Use SwapBuffers instead of wglSwapBuffers

glX vs wgl

This is a list of glX functions and their equivalent wgl functions. There might be some missing entries.

  • glXChooseVisual --- ChoosePixelFormat
  • glXCopyContext —-- NULL
  • glXCreateContext --- wglCreateContext
  • glXCreateGLXPixmap --- CreateDIBitmap and CreateDIBSection
  • glXDestroyContext --- wglDeleteContext
  • glXDestroyGLXPixmap --- DeleteObject
  • glXGetConfig --- DescribePixelFormat
  • glXGetCurrentContext --- wglGetCurrentContext
  • glXGetCurrentDrawable --- wglGetCurrentDC
  • glXIsDirect —-- NULL
  • glXMakeCurrent --- wglMakeCurrent
  • glXQueryExtension ---- GetVersion
  • glXQueryVersion --- GetVersion
  • glXSwapBuffers --- SwapBuffers
  • glXUseXFont wglUseFontBitmaps and wglUseFontOutlines
  • glXWaitGL —-- NULL
  • glXWaitX --— NULL
  • XGetVisualInfo --- GetPixelFormat
  • XCreateWindow --- CreateWindow/CreateWindowEx and GetDC/BeginPaint
  • XSync GdiFlush
  • NULL —-- SetPixelFormat
  • glXGetProcAddress --— wglGetProcAddress
  • NULL —-- wglShareLists

Installing Mesa3D on Windows

If your system does not contain a GPU, or the GPU vendor delivers graphics drivers providing OpenGL support that's so old as to be useless to you, you might want to consider installing the Mesa3D OpenGL library on your system to provide OpenGL support.

Mesa3D is a graphics library that provides an OpenGL implementation for multiple platforms. GPU hardware acceleration is supported on some GPUs, with a software (CPU) rendering pipeline generally available as a fallback or alternative rendering method (see Mesa3D Support Matrix).

For experienced developers that choose to build Mesa3D libraries from source, here are a few guides on how to download, build, and install Mesa3D:

For beginning developers and others which don't have the time or desire to build Mesa3D libraries from source, here are some pre-built Windows installer (EXE) images. Options are provided to install the Mesa3D OpenGL libraries either system-wide or per-application: