wglCreateContext失败,错误代码为6(无效句柄)

时间:2017-08-08 15:38:33

标签: windows opengl d

我试图根据https://www.khronos.org/opengl/wiki/Creating_an_OpenGL_Context_(WGL)的教程创建一个wgl上下文。无论出于何种原因,wglCreateContext都会返回nullGetLastError会返回6或无效句柄。我之前使用过该教程,但它工作得很好。

我试图为隐藏窗口创建一个虚拟上下文,以便我可以为用户窗口创建另一个上下文。发生了什么事?

Windows API通过winAPI标识符引用,wgl是一个包含OpenGL函数指针的全局结构。

struct WglContext
{
    winAPI.HDC hdc;
    winAPI.HGLRC handle;
}

__gshared Win32GL wgl;

///WGL-specific global data.
struct Win32GL
{
    import oswald : OsWindow, WindowConfig, WindowError;

    OsWindow helperWindow;
    winAPI.HINSTANCE instance;

    PFN_wglCreateContext createContext;
    PFN_wglDeleteContext deleteContext;
    PFN_wglGetProcAddress getProcAddress;
    PFN_wglMakeCurrent makeCurrent;

    PFN_wglCreateContextAttribsARB createContextAttribsARB;
    PFN_wglGetExtensionStringARB getExtensionStringARB;
    PFN_wglGetExtensionStringEXT getExtensionStringEXT;

    bool extensionsAreLoaded;

    static void initialize()
    {
        if (wgl.instance !is null)
            return; //The library has already been initialized

        WindowConfig cfg;
        cfg.title = "viewport_gl_helper";
        cfg.hidden = true;
        auto windowError = OsWindow.createNew(cfg, &wgl.helperWindow);
        if (windowError != WindowError.NoError)
        {
            import std.conv : to;

            assert(false, "Failed to create helper window: " ~ windowError.to!string);
        }

        wgl.instance = winAPI.LoadLibrary("opengl32.dll");

        if (wgl.instance is null)
            assert(false, "Viweport failed to load opengl32.dll");

        wgl.bind(cast(void**)&wgl.createContext, "wglCreateContext\0");
        wgl.bind(cast(void**)&wgl.deleteContext, "wglDeleteContext\0");
        wgl.bind(cast(void**)&wgl.getProcAddress, "wglGetProcAddress\0");
        wgl.bind(cast(void**)&wgl.makeCurrent, "wglMakeCurrent\0");
    }

    static void terminate()
    {
        if (!wgl.instance)
            return;

        winAPI.FreeLibrary(wgl.instance);
        wgl.helperWindow.destroy();
    }

    void bind(void** func, in string name)
    {
        *func = winAPI.GetProcAddress(this.instance, name.ptr);
    }
}

struct WglContext
{
    winAPI.HDC hdc;
    winAPI.HGLRC handle;
}

WglContext wglCreateTmpContext()
{
    assert(wgl.instance);

    winAPI.PIXELFORMATDESCRIPTOR pfd;
    pfd.nSize = winAPI.PIXELFORMATDESCRIPTOR.sizeof;
    pfd.nVersion = 1;
    pfd.dwFlags = winAPI.PFD_DRAW_TO_WINDOW | winAPI.PFD_SUPPORT_OPENGL | winAPI.PFD_DOUBLEBUFFER;
    pfd.iPixelType = winAPI.PFD_TYPE_RGBA;
    pfd.cColorBits = 24;

    auto hdc = winAPI.GetDC(wgl.helperWindow.platformData.handle);

    const pixelFormat = winAPI.ChoosePixelFormat(hdc, &pfd);
    if (winAPI.SetPixelFormat(hdc, pixelFormat, &pfd) == winAPI.FALSE)
        assert(false, "Failed to set pixel format for temp context");

    writeln(hdc);
    writeln(pixelFormat);

    winAPI.HGLRC context = wgl.createContext(hdc);
    if (context is null)
    {
        import std.conv: to;
        assert(false, "Failed to create temp context: Error Code " ~ winAPI.GetLastError().to!string);
    }

    if (wgl.makeCurrent(hdc, context) == winAPI.FALSE)
    {
        wgl.deleteContext(context);
        assert(false, "Failed to make temp context current");
    }

    return WglContext(hdc, context);
}

void main()
{
    wgl.initialize(); //Fetches function pointers, and loads opengl32.dll
    auto context = wglCreateTmpContext();
    wglDeleteContext(context); //Delegates to wgl.deleteContext
    wgl.terminate(); //Unloads opengl32.dll and nulls function pointers
}

1 个答案:

答案 0 :(得分:0)

我对你使用的winAPI一无所知。无论如何,我确信:

你必须:

  1. 创建一个窗口并获取其HWND句柄(Windows的定义) HWND,见下文)。该窗口使用WS_CLIPCHILDREN | WS_CLIPSIBLINGS 样式;但请尝试使用链接中的WS_OVERLAPPEDWINDOW 帐。
  2. 确认您从中获得有效的HWND和有效的HDC
  3. HWNDHDC定义为*void。我不相信auto