wglCreateContextAttribsARB function crashes

2020-03-31 03:30发布

问题:

I try to write down code from this tutorial. I have the code of InitializeOGL():

bool Ogl::InitializeOGL(bool vSync)
{
  cout<<"Init OpenGL"<<endl;
  int pixelFormat;
  PIXELFORMATDESCRIPTOR pixelFormatDescriptor;
  int result;
  char *vendorChar, *rendererChar;

  hDC = GetDC(hWnd);
  if(!hDC)
    return false;

  pixelFormat = ChoosePixelFormat(hDC,&pixelFormatDescriptor);
  if(pixelFormat==0)
    return false;

  result = SetPixelFormat(hDC,pixelFormat,&pixelFormatDescriptor);
  if(result!=1)
    return false;

  HGLRC tempDeviceContext = wglCreateContext(hDC);
  wglMakeCurrent(hDC,tempDeviceContext);

  // glewExperimental = GL_TRUE;
  if(glewInit()!=GLEW_OK)
    return false;

  int attribList[5] = 
  {
    WGL_CONTEXT_MAJOR_VERSION_ARB, 3,
    WGL_CONTEXT_MINOR_VERSION_ARB, 1, 0
  };

  hGLRC = wglCreateContextAttribsARB(hDC,0,attribList);
  if(hGLRC!=NULL)
  {
    wglMakeCurrent(NULL,NULL);
    wglDeleteContext(tempDeviceContext);
    result = wglMakeCurrent(hDC,hGLRC);
    if(result!=1)
      return false;
  }

  vendorChar = (char*)glGetString(GL_VENDOR);
  rendererChar = (char*)glGetString(GL_RENDERER);

  strcpy_s(videoCardInfo,vendorChar);
  strcat_s(videoCardInfo,"-");
  strcat_s(videoCardInfo,rendererChar);

  if(vSync)
    result = wglSwapIntervalEXT(1);
  else
    result = wglSwapIntervalEXT(0);

  if(result!=1)
    return false;

  int glVersion[2] = {-1,-1};
  glGetIntegerv(GL_MAJOR_VERSION,&glVersion[0]);
  glGetIntegerv(GL_MINOR_VERSION,&glVersion[1]);

  cout<<"Initializing OpenGL"<<endl;
  cout<<"OpenGL version"<<glVersion[0]<<"."<<glVersion[1]<<endl;
  cout<<"GPU"<<videoCardInfo<<endl;

  return 0;
}

When I try to change context version to OpenGL 3.1, here crashes wglCreateContextAttribsARB() function (Pointer for this is getting in LoadExtensions() correctly). When I try to create OpenGL 4.0 here crashes function wglSwapIntervalEXT(). My graphic card handles only OpenGL 3.1.

My question is how to succefully init OpenGL context here? What I have to do to create OpenGL context in version 3.1.

回答1:

There are a couple of things that need to be mentioned here:

1. Driver Version

If your graphics card / driver only support OpenGL 3.1, then WGL_CONTEXT_MAJOR_VERSION_ARB and friends are generally going to be undefined. Before OpenGL 3.2 introduced core / compatibility, context versions were not particularly meaningful.

  • This requires support for either WGL_ARB_create_context or WGL_ARB_create_conext_profile.

2. Incorrect usage of ChoosePixelFormat and SetPixelFormat

PIXELFORMATDESCRIPTOR pixelFormatDescriptor; // <--- Uninitialized

At minimum, the Win32 API needs you to initialize the size field of this structure. In years past, the size of structures was used to determine the version of Windows that a particular piece of code was written for. These days structures like PIXELFORMATDESCRIPTOR are generally static in size because they are used by a part of Windows that is deprecated (GDI), but if you do not set the size you can still thoroughly confuse Windows. Furthermore, you need to flag your pixel format to support OpenGL to guarantee that you can use it to create an OpenGL render context.

Also note that once you set the pixel format for a device context on Windows, it cannot be changed. Generally, this means if you want to create a dummy render context to initialize your extensions you should also create a dummy window with a dummy pixel format. After you initialize your extensions, you can use wglChoosePixelFormatARB (...) and its associated functions to select the pixel format for your main window's device context.

This is (was) particularly important back in the days before FBOs when you wanted to implement multi-sampling. You cannot get a multi-sample pixel format using ChoosePixelFormat (...), but you need to call ChoosePixelFormat (...) to setup the extension necessary to get a multi-sample pixel format. Kind of a catch 22.