PDA

View Full Version : Easy OpenGL context creation



JoshKlint
12-22-2010, 06:41 PM
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&amp; majorversion, const int&amp; minorversion, const int&amp; 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(&amp;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,&amp;pfd);
SetPixelFormat(hdc,ipixelformat,&amp;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&amp; majorversion, const int&amp; minorversion, const int&amp; 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(&amp;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 &amp;&amp; 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,fAttribute s,1,&amp;ipixelformat,&amp;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,fAttribute s,1,&amp;ipixelformat,&amp;countformats);
}

if (countformats==0)
{
//ReleaseDC(hdc);
return NULL;
}

if (!SetPixelFormat(hdc,ipixelformat,&amp;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,attri bs);

if (hrc==NULL)
{
//ReleaseDC(hdc);
return NULL;
}

return hrc;
}
}

JoshKlint
12-22-2010, 06:52 PM
I'm not sure if I need to call ReleaseDC() here. I've seen the docs, and they are clear as mud. Any ideas?

Alfonse Reinheart
12-22-2010, 06:57 PM
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?

JoshKlint
12-22-2010, 07:45 PM
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.

mhagain
12-23-2010, 02:30 AM
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? :P

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.)

Jan
12-24-2010, 02:57 AM
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.