GetLastError()在调用SwapBuffers(HDC)后返回ERROR_INVALID_HANDLE / 6

时间:2015-05-30 22:42:16

标签: winapi opengl c++11 opengl-3 getlasterror

每当我尝试调用SwapBuffers()时,GetLastError()都会返回6 / ERROR_INVALID_HANDLE。有一段时间我试图通过以不同的方式重写这段代码来解决这个问题,试图找到不同的错误来源,并且通常会看到我可能做错了什么。但是,我还没有得出一个关于诱导这个或者我能做些什么来解决这个问题的结论。

当我调用诸如glUseProgram()和。之类的OpenGL函数时,我也认识到了 glVertexAttribPointer(),glGetError()返回1282 / GL_INVALID_OPERATION。

Window::Window(string title, int xPos, int yPos, int width, int height, string icon_path)
        {
            this->title = title;
            this->width = width;
            this->height = height;

            if (this->height == 0)
                this->height = 1;

            if (!Create(xPos, yPos))
            {
                cout << "Window Creation Failure!" << endl;
                exit(EXIT_FAILURE);
            }

            HANDLE hIcon = LoadImage(0, icon_path.c_str(), IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_LOADFROMFILE);

            SendMessage(hWnd, WM_SETICON, ICON_BIG, (LPARAM) hIcon);

            glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
        }

        Window::~Window()
        {
            wglMakeCurrent(hDC, 0);
            wglDeleteContext(hRC);

            ReleaseDC(hWnd, hDC);
        }

        bool Window::Create(int xPos, int yPos)
        {
            WNDCLASS WndClass;
            DWORD dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
            DWORD dwStyle = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX;

            this->hInstance = GetModuleHandle(nullptr);

            if (!this->hInstance)
                return false;

            WndClass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
            WndClass.lpfnWndProc = (WNDPROC) WndProc;
            WndClass.cbClsExtra = 0;
            WndClass.cbWndExtra = 0;
            WndClass.hInstance = this->hInstance;
            WndClass.hIcon = LoadIcon(nullptr, IDI_WINLOGO);
            WndClass.hCursor = LoadCursor(nullptr, IDC_ARROW);
            WndClass.hbrBackground = nullptr;
            WndClass.lpszMenuName = nullptr;
            WndClass.lpszClassName = this->title.c_str();

            if (!RegisterClass(&WndClass))
                return false;

            this->hWnd = CreateWindowEx(dwExStyle, this->title.c_str(), this->title.c_str(), dwStyle,
                xPos, yPos, this->width, this->height, nullptr, nullptr, this->hInstance, nullptr);

            if (!this->hWnd)
                return false;

            if (!this->CreateContext())
                return false;

            ShowWindow(this->hWnd, SW_SHOW);
            UpdateWindow(this->hWnd);

            return true;
        }

        bool Window::CreateContext()
        {
            this->hDC = GetDC(hWnd);

            if (!this->hDC)
                return false;

            PIXELFORMATDESCRIPTOR pfd;
            memset(&pfd, 0, sizeof(PIXELFORMATDESCRIPTOR));
            pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
            pfd.dwFlags = PFD_DOUBLEBUFFER | PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW;
            pfd.iPixelType = PFD_TYPE_RGBA; 
            pfd.cColorBits = 32;
            pfd.cDepthBits = 32;
            pfd.iLayerType = PFD_MAIN_PLANE;

            int nPixelFormat = ChoosePixelFormat(this->hDC, &pfd);

            if (!nPixelFormat) 
                return false;

            bool bResult = SetPixelFormat(this->hDC, nPixelFormat, &pfd);

            if (!bResult)
                return false;

            HGLRC tempOpenGLContext = wglCreateContext(this->hDC);
            wglMakeCurrent(this->hDC, tempOpenGLContext);

            GLenum err = glewInit();

            if (GLEW_OK != err)
                return false;

            int attributes[] = 
            {
                WGL_CONTEXT_MAJOR_VERSION_ARB, 3,
                WGL_CONTEXT_MINOR_VERSION_ARB, 2,
                WGL_CONTEXT_FLAGS_ARB,                          WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,
                0
            };

            if (wglewIsSupported("WGL_ARB_create_context") == true)
            {
                this->hRC = wglCreateContextAttribsARB(this->hDC, NULL, attributes);
                wglMakeCurrent(nullptr, nullptr);
                wglDeleteContext(tempOpenGLContext);
                wglMakeCurrent(this->hDC, this->hRC);

                if (!this->hRC)
                    return false;
            }
            else 
            {
                this->hRC = tempOpenGLContext;
            }

            int glVersion[2] = {-1, -1};
            glGetIntegerv(GL_MAJOR_VERSION, &glVersion[0]);
            glGetIntegerv(GL_MINOR_VERSION, &glVersion[1]);

            cout << "Opengl is running on context version : " << glVersion[0] << ", " << glVersion[1]  << endl;

            return true;
        }

        int Window::GameLoop(Core *core)
        {
            MSG msg;

            while (core->IsRunning())
            {
                if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
                {
                    if (msg.message == WM_QUIT)
                    {
                        core->SetRunning(false);
                    }
                    else
                    {
                        TranslateMessage(&msg);
                        DispatchMessage(&msg);
                    }
                }
                else
                {
                    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

                    core->Run();

                    SwapBuffers(this->hDC);
                }
            }

            Core::Destroy();

            return (int)(msg.wParam);
        }

游戏状态的代码(我称之为gl函数):

    #include "State.h"

using namespace Lumen::Core_Engine;

GLfloat Data[9] =
{
    -0.5f, -0.5f, 0.0f,
     0.5f, -0.5f, 0.0f,
     0.0f,  0.5f, 0.0f
};

Example::Example()
{
    this->colourShader = new Shader("./Shaders/Vertex/BasicColour.vert", "./Shaders/Vertex/BasicColour.vert");

    this->colourVertexArray = new VertexArray(new VertexBuffer(Data, sizeof(Data), GL_TRIANGLES, 3, sizeof(GLfloat) * 3, this->colourShader));

    cout << "'Example' state initialized!" << endl;
}

Example::~Example()
{
}

void Example::Update()
{
    GLenum errGL = glGetError();
    if (GLEW_NO_ERROR != errGL)
        cout << errGL << endl;

    DWORD errWin = GetLastError();
    if (NO_ERROR != errWin)
        cout << errWin << endl;
}

void Example::Render()
{
    glUseProgram((colourVertexArray->GetVertexBufferObject()->GetShader())->GetProgram());
    (colourVertexArray->GetVertexBufferObject()->GetShader())->SetFloat4((colourVertexArray->GetVertexBufferObject()->GetShader())->GetUniform("Colour"), 1.0f, 0.0f, 0.0f, 1.0f);
    (colourVertexArray)->AddVertexBufferObjectTarget((colourVertexArray->GetVertexBufferObject()->GetShader())->GetAttribute("Position"));
    (colourVertexArray)->Render();
}

1 个答案:

答案 0 :(得分:2)

无论先前的API调用是否失败,您都在调用GetLastError。您应该只在文档表明您应该调用时GetLastError。通常,当您调用的函数的返回值表示失败时。

API调用完全可以成功,GetLastError返回非零值。这似乎正是这里发生的事情。