Easy OpenGL context creation

I thought this might be helpful to some people.

HGLRC glInitialize(hwnd)
This function creates a basic OpenGL context. You must use this before creating an advanced context.

HGLRC glCreateContext(HWND hwnd, HGLRC sharedcontext, const int& majorversion, const int& minorversion, const int& multisamplemode)
This function creates an advanced OpenGL context. You must create a basic OpenGL context before using this. You can specify an OpenGL version and multisampling mode. If OpenGL 3.3+ is used, a forward-compatible context will be created.

Win32.OpenGL.h:

#pragma once

#include <windows.h>
#include <glew.h>
#include <wglew.h>

namespace le3
{
	HGLRC glInitialize(HWND hwnd);
	HGLRC glCreateContext(HWND hwnd, HGLRC sharedcontext, const int& majorversion, const int& minorversion, const int& multisamplemode=0);
}

Win32.OpenGL.cpp:

#include "Win32.OpenGL.h"

namespace le3
{
	//This function creates minimal OpenGL context.
	//This is required to get the wgl functions to create any more advanced styles of contexts
	HGLRC glInitialize(HWND hwnd)
	{
		int ipixelformat;
		HDC hdc = GetDC(hwnd);
		PIXELFORMATDESCRIPTOR pfd;
		GLenum err;
		
		//Create pixel format descriptor
		memset(&pfd,0,sizeof(PIXELFORMATDESCRIPTOR));
		pfd.nSize  = sizeof(PIXELFORMATDESCRIPTOR);
		pfd.nVersion   = 1;
		pfd.dwFlags    = PFD_DOUBLEBUFFER | PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW;
		pfd.iPixelType = PFD_TYPE_RGBA;
		pfd.cColorBits = 32;
		pfd.cDepthBits = 32;
		pfd.iLayerType = PFD_MAIN_PLANE;
		
		//Choose pixel format and attempt to set it
		ipixelformat = ChoosePixelFormat(hdc,&pfd);
		SetPixelFormat(hdc,ipixelformat,&pfd);
		
		//Create the OpenGL context
		HGLRC hrc = wglCreateContext(hdc);
		if (hrc==NULL)
		{
			//ReleaseDC(hdc);//Not sure if this is needed?	
			return NULL;
		}
		wglMakeCurrent(hdc,hrc);
		
		//Initialize GLEW
		err = glewInit();
		if (err!=GLEW_OK)
		{
			wglDeleteContext(hrc);
			//ReleaseDC(hdc);//Not sure if this is needed?	
			return NULL;
		}
		
		return hrc;
	}
	
	//This function will create a more advanced OpenGL context with more options.
	//It requires an active OpenGL context to already be created.
	HGLRC glCreateContext(HWND hwnd, HGLRC sharedcontext, const int& majorversion, const int& minorversion, const int& multisamplemode)
	{		
		int ipixelformat;
		int contextflags = 0;
		PIXELFORMATDESCRIPTOR pfd;
		float fAttributes[] = {0,0};
		unsigned int countformats = 0;
		HDC hdc = GetDC(hwnd);
		HGLRC hrc = NULL;

		//Create pixel format descriptor
		memset(&pfd,0,sizeof(PIXELFORMATDESCRIPTOR));
		pfd.nSize  = sizeof(PIXELFORMATDESCRIPTOR);
		pfd.nVersion   = 1;
		pfd.dwFlags    = PFD_DOUBLEBUFFER | PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW;
		pfd.iPixelType = PFD_TYPE_RGBA;
		pfd.cColorBits = 32;
		pfd.cDepthBits = 32;
		pfd.iLayerType = PFD_MAIN_PLANE;
		
		//Use forward-compatible context for version 3.3+
		if ((majorversion>2 && minorversion>2) || majorversion>3)
		{
			contextflags = WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
		}
		
		//Choose pixel format and attempt to set it
		if (multisamplemode>1)
		{
			int iAttributes[] = 
			{
					WGL_DRAW_TO_WINDOW_ARB,GL_TRUE,
					WGL_SUPPORT_OPENGL_ARB,GL_TRUE,
					WGL_ACCELERATION_ARB,WGL_FULL_ACCELERATION_ARB,
					WGL_COLOR_BITS_ARB,24,
					WGL_ALPHA_BITS_ARB,8,
					WGL_DEPTH_BITS_ARB,24,
					WGL_STENCIL_BITS_ARB,0,
					WGL_DOUBLE_BUFFER_ARB,GL_TRUE,
					WGL_SAMPLE_BUFFERS_ARB,GL_TRUE,
					WGL_SAMPLES_ARB,multisamplemode,
					0,0
			};
			wglChoosePixelFormatARB(hdc,iAttributes,fAttributes,1,&ipixelformat,&countformats);
		}
		else
		{
			int iAttributes[] = 
			{
					WGL_DRAW_TO_WINDOW_ARB,GL_TRUE,
					WGL_SUPPORT_OPENGL_ARB,GL_TRUE,
					WGL_ACCELERATION_ARB,WGL_FULL_ACCELERATION_ARB,
					WGL_COLOR_BITS_ARB,24,
					WGL_ALPHA_BITS_ARB,8,
					WGL_DEPTH_BITS_ARB,24,
					WGL_STENCIL_BITS_ARB,0,
					WGL_DOUBLE_BUFFER_ARB,GL_TRUE,
					WGL_SAMPLE_BUFFERS_ARB,GL_FALSE,
					0,0

			};
			wglChoosePixelFormatARB(hdc,iAttributes,fAttributes,1,&ipixelformat,&countformats);
		}
		
		if (countformats==0)
		{
			//ReleaseDC(hdc);
			return NULL;
		}
		
		if (!SetPixelFormat(hdc,ipixelformat,&pfd))
		{
			//ReleaseDC(hdc);
			return NULL;
		}
		
		//Attributes for the real OpenGL context
		int attribs[] = 
		{
			WGL_CONTEXT_MAJOR_VERSION_ARB, majorversion,
			WGL_CONTEXT_MINOR_VERSION_ARB, minorversion,
			WGL_CONTEXT_FLAGS_ARB, contextflags,
			0,0
		};
		
		//Create context
		hrc = wglCreateContextAttribsARB(hdc,sharedcontext,attribs);
		
		if (hrc==NULL)
		{
			//ReleaseDC(hdc);
			return NULL;
		}
		
		return hrc;
	}
}

I’m not sure if I need to call ReleaseDC() here. I’ve seen the docs, and they are clear as mud. Any ideas?

I’m not sure if I need to call ReleaseDC() here.

Anytime you get a Windows handle object of any kind, you must release it. So your call to GetDC ultimately requires a corresponding call to ReleaseDC.

Two things about your code:

1: You didn’t mention that it relies on GLEW.

2: Why are there no options for other things, like various bitdepths for buffers or sRGB framebuffers for gamma-correct computations?

Thank for the info.

This is my code for the features I need. I wasn’t trying to include every possible feature, just the ones I use.

Not very helpful to others then, is it? :stuck_out_tongue:

Joke - seeing the actual code used should be of assistance to anyone who’s wondering what’s involved. Just so long as they’re not expecting to be able to copy and paste.

(BTW - using C++ rather than C also limits it’s general usefulness.)

Don’t criticize everything!

Josh, it is very nice of you to post your code, very helpful! And if someone needs more (or pure C, or whatever) the few minutes to modify the code won’t kill him.

Jan.