【问题标题】:GLX Context Creation Error: GLXBadFBConfigGLX 上下文创建错误:GLXBadFBConfig
【发布时间】:2021-04-08 10:19:14
【问题描述】:

我使用glXCreateContext 来创建上下文,但该函数已被弃用,并且总是导致 OpenGL 版本 3.0,我需要至少 4 个版本。现在,如果我理解正确,GLXContext glXCreateContextAttribsARB(Display* dpy, GLXFBConfig config, GLXContext share_context, Bool direct, const int* attrib_list); 替换了 @987654324 @。 “新”功能允许在 attrib_list 中明确指定主要版本、次要版本、配置文件等,例如:

int context_attribs[] =
{
    GLX_CONTEXT_MAJOR_VERSION_ARB, 4,
    GLX_CONTEXT_MINOR_VERSION_ARB, 5,
    GLX_CONTEXT_FLAGS_ARB,         GLX_CONTEXT_DEBUG_BIT_ARB,
    GLX_CONTEXT_PROFILE_MASK_ARB,  GLX_CONTEXT_COMPABILITY_PROFILE_BIT_ARB,
    None
};

然后使用函数:

glXCreateContextAttribsARB(dpy, config, NULL, true, context_attribs);

这就是我在我的程序中所做的。窗口已创建,dpy 是指向 Display 的有效指针。 config我是这样定义的:

// GLXFBConfig config; created at the beginning of the program
int attrib_list[] =
{
    GLX_RENDER_TYPE,    GLX_RGBA_BIT,
    GLX_RED_SIZE,       8,
    GLX_GREEN_SIZE,     8,
    GLX_BLUE_SIZE,      8,
    GLX_DEPTH_SIZE,     24,
    GLX_DOUBLEBUFFER,   True,
    None
};
int nAttribs;

config = glXChooseFBConfig(dpy, 0, attrib_list, &nAttribs);

检查glxinfo,我有正确的视觉效果; vi 已设置为 0x120,我可以通过 glxinfo | grep 0x120 确认。它完全满足了上述要求。 到目前为止,一切都很好。但是在运行应用程序时(编译工作正常),我收到以下错误:

X Error of failed request: GLXBadFBConfig
Major opcode of failed request: 152 (GLX)
Minor opcode of failed request: 34 ()
Serial number of failed request: 31
Current serial number in output stream: 31

现在,这就是错误的原因:

如果 不支持提供请求的 API 主要和次要版本、前向兼容标志和调试上下文标志的兼容 OpenGL 上下文,则会生成 GLXBadFBConfig。

所以,问题很简单。我不知道如何解决它。它本质上的意思是找不到与我在attrib_list[] 中指定的属性和context_attribs 中的属性相对应的OpenGL 上下文。通过glxinfo | grep Max,我确认我的最高 OpenGL 版本是 4.5。我想听听您对我现在应该做什么的建议。我已经玩了一段时间context_attribs 中的属性,但没有得到任何结果。也许问题真的出在另一个地方。也许我对 GLX 函数的概念总体上是有缺陷的,如果有,请指出!

【问题讨论】:

  • “我确认我的最高 OpenGL 版本是 4.5” 确保这是针对您请求的兼容性上下文,而不仅仅是针对核心上下文。直到最近,Mesa 才在 Core 上下文中支持大于 3.0 的 GL 版本。另外,编辑minimal reproducible example

标签: c++ linux opengl glx


【解决方案1】:

GLX_ARB_create_context 的规范明确了何时可能返回GLXBadFBConfig 错误:

  * If <config> does not support compatible OpenGL contexts
    providing the requested API major and minor version,
    forward-compatible flag, and debug context flag, GLXBadFBConfig
    is generated.

这可能令人困惑(因为错误与已经创建的 GLXFBConfig 无关),但我就是我们所拥有的。因此,您遇到错误的最明显原因是您的系统实际上不支持您请求的OpenGL 4.5 Compatible Profile - 但它可能支持OpenGL 4.5 Core Profile 或更低的兼容/核心配置文件版本。这是一个非常Mesa 驱动程序的常见情况,仅支持 OpenGL 3.3+ 核心配置文件和仅支持许多 GPU 的 OpenGL 3.0 兼容配置文件(但不是全部 - 有些获得更好的兼容配置文件支持,如 Radeon)。

如果您还不熟悉OpenGL 配置文件的概念 - 您可以start here

glxinfo 显示有关 Core 和 Compatible 配置文件的信息,可以像这样过滤掉:

glxinfo | grep -e "OpenGL version" -e "Core" -e "Compatible"

这会在虚拟 Ubuntu 18.04 上返回给我:

OpenGL core profile version string: 3.3 (Core Profile) Mesa 19.2.8
OpenGL version string: 3.1 Mesa 19.2.8

如果您的应用程序确实需要 OpenGL 4.5 或更高版本,请尝试使用 GLX_CONTEXT_CORE_PROFILE_BIT_ARB 位而不是 GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 创建上下文,并确保不使用任何已弃用的功能。

请注意,请求特定版本的兼容配置文件通常没有意义 - 只需跳过版本参数即可获得最高支持的版本并从GL_VERSION/GL_MAJOR_VERSION 中过滤掉不受支持的版本已经创建的上下文,就像在介绍配置文件之前几天所做的那样。对于核心配置文件,在某些请求支持的最高版本的 OpenGL 驱动程序上可能会很棘手(例如,没有禁用高于请求的版本的功能) - 以下代码 sn-p 可能很有用:

  //! A dummy XError handler which just skips errors
  static int xErrorDummyHandler (Display* , XErrorEvent* ) { return 0; }
  ...

  Window      aWindow    = ...;
  Display*    aDisp      = ...;
  GLXFBConfig anFBConfig = ...;
  bool toDebugContext = false;

  GLXContext  aGContext  = NULL
  const char* aGlxExts   = glXQueryExtensionsString (aDisp, aVisInfo.screen);
  if (!checkGlExtension (aGlxExts, "GLX_ARB_create_context_profile"))
  {
    std::cerr << "GLX_ARB_create_context_profile is NOT supported\n";
    return;
  }

  // Replace default XError handler to ignore errors.
  // Warning - this is global for all threads!
  typedef int (*xerrorhandler_t)(Display* , XErrorEvent* );
  xerrorhandler_t anOldHandler = XSetErrorHandler(xErrorDummyHandler);

  typedef GLXContext (*glXCreateContextAttribsARB_t)(Display* dpy, GLXFBConfig config,
                                                     GLXContext share_context, Bool direct,
                                                     const int* attrib_list);
  glXCreateContextAttribsARB_t aCreateCtxProc = (glXCreateContextAttribsARB_t )glXGetProcAddress((const GLubyte* )"glXCreateContextAttribsARB");
  int aCoreCtxAttribs[] =
  {
    GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
    GLX_CONTEXT_MINOR_VERSION_ARB, 2,
    GLX_CONTEXT_PROFILE_MASK_ARB,  GLX_CONTEXT_CORE_PROFILE_BIT_ARB,
    GLX_CONTEXT_FLAGS_ARB,         toDebugContext ? GLX_CONTEXT_DEBUG_BIT_ARB : 0,
    0, 0
  };

  // try to create a Core Profile of highest OpenGL version (up to 4.6)
  for (int aLowVer4 = 6; aLowVer4 >= 0 && aGContext == NULL; --aLowVer4)
  {
    aCoreCtxAttribs[1] = 4;
    aCoreCtxAttribs[3] = aLowVer4;
    aGContext = aCreateCtxProc (aDisp, anFBConfig, NULL, True, aCoreCtxAttribs);
  }
  for (int aLowVer3 = 3; aLowVer3 >= 2 && aGContext == NULL; --aLowVer3)
  {
    aCoreCtxAttribs[1] = 3;
    aCoreCtxAttribs[3] = aLowVer3;
    aGContext = aCreateCtxProc (aDisp, anFBConfig, NULL, True, aCoreCtxAttribs);
  }
  bool isCoreProfile = aGContext != NULL;
  if (!isCoreProfile)
  {
    std::cerr << "glXCreateContextAttribsARB() failed to create Core Profile\n";
  }

  // try to create Compatible Profile
  if (aGContext == NULL)
  {
    int aCtxAttribs[] =
    {
      GLX_CONTEXT_FLAGS_ARB, toDebugContext ? GLX_CONTEXT_DEBUG_BIT_ARB : 0,
      0, 0
    };
    aGContext = aCreateCtxProc (aDisp, anFBConfig, NULL, True, aCtxAttribs);
  }
  XSetErrorHandler (anOldHandler);

  // fallback to glXCreateContext() as last resort
  if (aGContext == NULL)
  {
    aGContext = glXCreateContext (aDisp, aVis.get(), NULL, GL_TRUE);
    if (aGContext == NULL) { std::cerr << "glXCreateContext() failed\n"; }
  }

【讨论】:

    猜你喜欢
    • 2017-01-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多