FamSlam
FamSlam

Reputation: 1

GetLastError() returns ERROR_INVALID_HANDLE / 6 after calling SwapBuffers(HDC)

Whenever I attempt to call SwapBuffers(), GetLastError() returns 6 / ERROR_INVALID_HANDLE. For a while I have attempted to fix this by rewriting this code in different ways, attempting to find different origins of errors and generally looking at what I could be doing wrong. But, I haven't come to a single conclusion on what is inducing this or what I can do to resolve this.

I have also recognized when I call OpenGL functions such as glUseProgram() and glVertexAttribPointer(), glGetError() returns 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);
        }

Code to the game state(where I call gl functions):

    #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();
}

Upvotes: 0

Views: 1328

Answers (1)

David Heffernan
David Heffernan

Reputation: 612814

You are calling GetLastError irrespective of whether or not the previous API call failed. You should only call GetLastError when the documentation indicates that you should. Typically that is when the return value of the function that you called indicates a failure.

It is perfectly possible for an API call to succeed, and GetLastError to return a non-zero value. It seems likely that is what is happening here.

Upvotes: 2

Related Questions