为什么我没有WGL_ARB_create_context扩展名?

时间:2017-08-29 11:15:16

标签: c++ opengl

我正在执行以下代码来创建核心配置文件OpenGL上下文。

具体来说,我是:

  1. 创建虚拟窗口
  2. 使用这个虚拟窗口来请求一个OpenGL上下文(我假设它会硬件加速,但我不确定这是否重要)
  3. 使用此OpenGL上下文加载OpenGL函数指针
  4. 使用这些函数指针,然后我尝试使用wglCreateContextAttribsARB在第二个窗口中专门创建具有核心配置文件的第二个上下文。
  5. 代码:

    WNDCLASSW wcDummy = {0};
    wcDummy.lpfnWndProc     = +[](HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){return DefWindowProcW(hWnd, message, wParam, lParam);};
    wcDummy.hInstance       = GetModuleHandle(0);
    wcDummy.hbrBackground   = (HBRUSH)(COLOR_BACKGROUND);
    wcDummy.lpszClassName   = L"Dummy";
    wcDummy.style           = CS_OWNDC;
    
    if(!RegisterClassW(&wcDummy))
    {
        get_and_print_error();
        return false;
    }
    
    HWND windowDummy = CreateWindowW(wcDummy.lpszClassName, title.c_str(), WS_DISABLED, 0, 0, 640, 480, 0, 0, wcDummy.hInstance, NULL);
    if(windowDummy == NULL)
    {
        get_and_print_error();
        return false;
    }
    
    PIXELFORMATDESCRIPTOR pfdDummy =
    {
        sizeof(PIXELFORMATDESCRIPTOR),
        1,
        PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
        PFD_TYPE_RGBA,
        32,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        24,
        8,
        0, 0, 0, 0, 0, 0
    };
    
    HDC dummyDrawingContext = GetDC(windowDummy);
    
    INT pixelFormatDummy = ChoosePixelFormat(dummyDrawingContext, &pfdDummy);
    SetPixelFormat(dummyDrawingContext, pixelFormatDummy, &pfdDummy);
    
    HGLRC dummyContext = wglCreateContext(dummyDrawingContext);
    wglMakeCurrent(dummyDrawingContext, dummyContext);
    
    if(wglGetCurrentContext() != NULL)
    {
        load_gl_functions();
    }
    else
        return false;
    
    PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB = nullptr;
    
    GLint64 numExtensions;
    glGetInteger64v(GL_NUM_EXTENSIONS, &numExtensions);
    std::cout << "Available Extensions:\n";
    for(GLint64 i = 0; i < numExtensions; ++i)
    {
        const GLubyte* extensionName = glGetStringi(GL_EXTENSIONS, i);
    
        std::cout << "\n\t" << (const char*)extensionName;
    
        if(std::strcmp((const char*)extensionName, "WGL_ARB_create_context") == 0)
        {
            wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)wglGetProcAddress("wglCreateContextAttribsARB");
        }
    }
    std::cout << std::endl;
    
    wglDeleteContext(dummyContext);
    DestroyWindow(windowDummy);
    
    WNDCLASSW wc = {0};
    wc.lpfnWndProc      = Window::WndProc;
    wc.hInstance        = GetModuleHandle(0);
    wc.hbrBackground    = (HBRUSH)(COLOR_BACKGROUND);
    wc.lpszClassName    = title.c_str();
    wc.style = CS_OWNDC;
    
    if(!RegisterClassW(&wc))
    {
        get_and_print_error();
        return false;
    }
    
    HWND window = CreateWindowW(wc.lpszClassName, title.c_str(), WS_OVERLAPPED|WS_VISIBLE|WS_SYSMENU ,0,0,640,480,0,0,wc.hInstance,this);
    if(window == NULL)
    {
        get_and_print_error();
        return false;
    }
    
    PIXELFORMATDESCRIPTOR pfd =
    {
        sizeof(PIXELFORMATDESCRIPTOR),
        1,
        PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
        PFD_TYPE_RGBA,
        32,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        24,
        8,
        0, 0, 0, 0, 0, 0
    };
    
    HDC m_drawingContext = GetDC(window);
    
    INT pixelFormat = ChoosePixelFormat(m_drawingContext, &pfd);
    SetPixelFormat(m_drawingContext, pixelFormat, &pfd);
    
    const GLint attribList[] =
    {
        WGL_CONTEXT_MAJOR_VERSION_ARB, 4,
        WGL_CONTEXT_MINOR_VERSION_ARB, 4,
        WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
        0
    };
    
    m_glRenderContext = wglCreateContextAttribsARB(m_drawingContext, 0, attribList);
    
    wglMakeCurrent(m_drawingContext, m_glRenderContext);
    
    if(wglGetCurrentContext() != NULL)
    {
        load_gl_functions();
    }
    else
        return false;
    
    const GLubyte* driver = glGetString(GL_RENDERER);
    const GLubyte* version = glGetString(GL_VERSION);
    const GLubyte* glslVersion = glGetString(GL_SHADING_LANGUAGE_VERSION);
    
    std::wcout << "Device:       " << std::wstring(convert_gl_string_to_win32_string(driver)) << std::endl;
    std::wcout << "GL Version:   " << std::wstring(convert_gl_string_to_win32_string(version)) << std::endl;
    std::wcout << "GLSL Version: " << std::wstring(convert_gl_string_to_win32_string(glslVersion)) << std::endl;
    std::wcout << std::endl;
    

    问题是WGL_ARB_create_context扩展名不存在。

    但是,如果我忘记检查扩展名列表,即放弃循环,只需:

    wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)wglGetProcAddress("wglCreateContextAttribsARB");
    

    我最终得到了一个函数指针,一切正常。

    为什么我的可用扩展列表不提供WGL_ARB_create_context字符串,即使扩展名存在?

    编辑我有AMD Radeon HD 7900系列

3 个答案:

答案 0 :(得分:8)

  

为什么我的可用扩展列表不提供WGL_ARB_create_context字符串,即使扩展名存在?

因为 WGL 扩展名 不需要通过 GL 扩展字符串进行广告宣传。有WGL_ARB_extension_string扩展名控制WGL扩展的广告。引用该规范:

  

应用程序应致电wglGetProcAddress以查看是否支持wglGetExtensionsStringARB。如果它受支持,那么它可用于确定设备支持哪些WGL扩展。

因此,为了不创建任何递归问题,如果函数指针不是NULL,则保证该函数有效。

如果你想知道为什么某些WGL扩展仍然在GL扩展字符串中:这是遗留的事情。再次从该扩展规范中引用问题1:

  

请注意之前通过广告宣传的扩展程序        glGetString(例如,交换间隔扩展)应该继续        在那里做广告,所以现有的应用程序不会中断。他们        也应该通过wglGetExtensionsStringARB广告来宣传        应用程序可以进行一次调用以找出哪些WGL扩展名        支撑。

旁注:

使用glGetStringi的GL扩展查询机制仅适用于GL 3.0。 glGetInteger64vglGetStringi可能都不可用,如果在某些较旧的GPU上运行,或者在回退到Microsoft的GL 1.1渲染器时,此代码很可能会崩溃。

答案 1 :(得分:3)

扩展名WGL_ARB_create_context不在支持的扩展名列表中的原因是因为它在技术上不是OpenGL扩展而是WGL扩展。 glGetStringi仅返回OpenGL扩展,但不返回WGL 1

要查询WGL扩展程序,必须使用提供wglGetExtensionsStringARB方法的WGL_ARB_extensions_string扩展名。检查此扩展名是否可用的唯一方法是查询wglGetExtensionsStringARB的地址,并查看它是否返回0.

  

应用程序应调用wglGetProcAddress来查看是否存在       支持wglGetExtensionsStringARB。

请注意,如果您只想知道WGL_ARB_create_context是否更容易查询wglCreateContextARB的地址并检查结果。

1 由于历史原因,有一些例外情况。扩展说明指出:

  

请注意之前通过广告宣传的扩展程序        glGetString(例如,交换间隔扩展)应该继续        在那里做广告,所以现有的应用程序不会中断。他们        也应该通过wglGetExtensionsStringARB做广告这么新        应用程序可以进行一次调用以找出哪些WGL扩展名        支撑。

答案 2 :(得分:-1)

您使用glGetInteger64v来检索扩展数量。但是Windows不提供此功能,必须在OpenGL 1.1之后将其指定为任何gl-command 与glGetStringi相同的问题。两者都是OGL&gt; = 3.0函数。
因此,你的循环是没用的。我不知道代码甚至可以编译。您未显示的内容可能会指定指向这些功能的指针。

Windows中存在

wglCreateContextAttribsARB,因此您无需先检查其扩展名即可获得指针。

获取Windows中可用扩展程序的功能包括wglGetExtensionsStringARBwglGetExtensionsStringEXT。按常规wglGetProcAddress获取指针。