检测3.2版之前的OpenGL上下文配置文件

7fyelxc5  于 2022-09-26  发布在  其他
关注(0)|答案(1)|浏览(168)

我正在尝试检测使用glfw创建的默认OpenGL上下文的配置文件。这就是我实现它的方式(基于wiki page)

std::string openGLProfile(){
   // Prints the profile of the current context

   GLint profile = 0;
   glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &profile);

   bool core_profile = profile & GL_CONTEXT_CORE_PROFILE_BIT;
   bool compatibility_profile = profile & GL_CONTEXT_COMPATIBILITY_PROFILE_BIT;

   std::string str = "No profile";

   if (core_profile == true)
       str = "Core profile";

   else if (compatibility_profile == true)
       str = "Compatibility";

   std::cout << str;
}

问题是这个枚举数GL_CONTEXT_PROFILE_MASK显然在一些OpenGL版本中不可用,比如2.1,这会导致错误。

我的问题是-如何对没有GL_CONTEXT_PROFILE_MASK的OpenGL版本进行配置文件检查?此外,如果有人能给我指点一下最初介绍这种个人资料面膜的文档,我会发现它非常有用。显然,doc for OpenGL 4.xx about glGetIntegerv甚至没有提到个人资料面具,这让我感到困惑。

cbjzeqam

cbjzeqam1#

如何对没有GL_CONTEXT_PROFILE_MASK的OpenGL版本进行配置文件检查?

准确地说,OpenGL直到3.2版才有配置文件的概念,因为之前的大多数版本(直到2.1)都是向后兼容的。当OpenGL 3.0引入了过时的功能,而OpenGL 3.1刚刚从规范中删除了一些功能时,这就成了一个问题。然而,不同的供应商一直通过扩展来支持向后兼容,并且同时存在不同版本的OpenGL规范。为了区分它们,引入了概要文件,但仅在3.2版中引入。

对你的问题最正确的回答是,在OpenGL 3.2之前,配置文件不存在,从技术上讲,没有配置文件。然而,如果我们将这个问题归结为如何在旧的OpenGL版本中表示配置文件二分法,那么答案将如下所示:

  • OpenGL高达2.1**-仅支持兼容性配置文件(所有上下文均向后兼容)
  • OpenGL 3.0**-尽管弃用了许多遗留功能,但它们仍然适用于3.0,因此主要是3.0是兼容性配置文件,但有一个例外-如果它有GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT,则意味着3.0模拟3.1体验,其中向后兼容性被移除,从而成为其核心配置文件。
  • OpenGL 3.1**-此版本的AS the documentation says如果扩展字符串中存在GL_ARB_compatibility,则支持所有不推荐使用的函数,因此可以将其视为兼容性(否则视为核心)
  • OpenGL 3.2及更高版本**-使用GL_CONTEXT_PROFILE_MASK提供此信息

实际代码应该如下所示(对于冗长的OpenGL版本实用程序函数,很抱歉,但它们在这里很方便)

constexpr GLint GLV(GLint major, GLint minor) {
    constexpr auto majorShift = std::numeric_limits<GLint>::digits / 2 - 1;
    return (major << majorShift) | minor;
}

GLint glVersion() {
    constexpr auto invalid_version = -1;
    const auto glVersionString{ reinterpret_cast<const char*>(glGetString(GL_VERSION)) };

    GLint major;
    const auto majorResult = std::from_chars(glVersionString, glVersionString + 1, major).ec;
    if (majorResult == std::errc::invalid_argument) {
        return invalid_version;
    }

    GLint minor;
    const auto minorResult = std::from_chars(glVersionString + 2, glVersionString + 3, minor).ec;
    if (minorResult == std::errc::invalid_argument) {
        return invalid_version;
    }

    return GLV(major, minor);
}

void reportGLProfile() {  
    const auto glV = glVersion();
    if (glV <= GLV(2, 1)) {
        std::cout << "Compatibility profile" << std::endl;
    } else if (glV == GLV(3, 0)) {
        GLint flags;
        glGetIntegerv(GL_CONTEXT_FLAGS, &flags);
        if (flags & GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT) {
            std::cout << "Core profile" << std::endl;
        } else {
            std::cout << "Compatibility profile" << std::endl;
        }
    } else if (glV == GLV(3, 1)) {
        GLint extensionsNum;
        glGetIntegerv(GL_NUM_EXTENSIONS, &extensionsNum);
        while (extensionsNum--) {
            const auto extensionName = reinterpret_cast<const char *>(glGetStringi(GL_EXTENSIONS, extensionsNum));
            if (std::strcmp(extensionName, "GL_ARB_compatibility") == 0) {
                std::cout << "Compatibility profile" << std::endl;
                return;
            }
        }
        std::cout << "Core profile" << std::endl;
    } else {
        GLint profile;
        glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &profile);

        if (const auto errorCode = glGetError()) {
            std::cout << "Pending GL error while obtaining profile: " << errorCode << std::endl;
            return;
        }

        if (profile & GL_CONTEXT_CORE_PROFILE_BIT) {
            std::cout << "Core profile" << std::endl;
        } else {
            std::cout << "Compatibility profile" << std::endl;
        }
    }
}

如果有人能给我指点一下最初引入这种轮廓面具的文档,我会发现它非常有用

这在上下文类型文档中有所涉及:

环境创建的3.0形式没有配置文件的概念。OpenGL只有一种形式:核心规范。在3.2版本中,OpenGL实际上被分成了两个概要:核心和兼容性。实现只需要定义核心,因此不能保证兼容性可用

相关问题