windows - wglCreateContext mislykkes med fejlkode 6 (ugyldig håndtering)

Indlæg af Hanne Mølgaard Plasc

Problem



Jeg forsøger at skabe en wgl-kontekst i henhold til vejledningen på https://www.khronos.org/opengl/wiki/Creating\_an\_OpenGL\_Context\_(WGL). Af en eller anden grund returnerer wglCreateContext null og GetLastError returnerer 6 eller Invalid Handle. Jeg har brugt tutorialen før, og det fungerede fint. [18]


Jeg forsøger at skabe en dummy-kontekst til et skjult vindue, så jeg kan oprette en anden kontekst til brugervinduet. Hvad sker der?


Windows API henvises via winAPI identifikatoren, og wgl er en global struktur, der indeholder funktionspegerne til 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");
        wgl.bind(cast(void**)&wgl.deleteContext, "wglDeleteContext");
        wgl.bind(cast(void**)&wgl.getProcAddress, "wglGetProcAddress");
        wgl.bind(cast(void**)&wgl.makeCurrent, "wglMakeCurrent");
    }

    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
}

Bedste reference


Jeg kender intet til det winAPI du bruger. Under alle omstændigheder er jeg sikker på:
 Du må:



  1. Opret et vindue og få dets HWND håndtag (Windows definition af
    HWND, se nedenfor). Vinduet bruger typisk WS\_CLIPCHILDREN | WS\_CLIPSIBLINGS
    stil; men prøv også WS\_OVERLAPPEDWINDOW som i linket du
    bogført.

  2. Bekræft, at du får en gyldig HWND og en gyldig HDC fra den.



HWND og HDC er defineret som *void. Jeg ville ikke stole på auto.