Handmade Hero»Forums»Code
Tucker
4 posts
Can't get opengl to draw anything in a simple window
I watched day 235 where Casey initializes opengl and looked at few other online tutorials but I can't get my window to draw anything. In Win32DisplayBufferInWindow I continually get the GL_INVALID_OPERATION glError which is supposed to mean I am passing illegal parameters however I don't think this is the case? Also wglMakeCurrent succeeds so opengl should be initialized properly?

Must be something obvious I'm missing. Any help would be awesome!

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
#include "toast_platform.h"

#include <windows.h>
#include <gl/gl.h>

#include "win32_toast.h"

global_variable bool32 GlobalRunning;

internal win32_window_dimension
Win32GetWindowSize(HWND Window)
{
    RECT WindowRect;
    GetClientRect(Window, &WindowRect);

    win32_window_dimension Result;
    Result.Width = WindowRect.right - WindowRect.left;
    Result.Height = WindowRect.bottom - WindowRect.top;

    return(Result);
}

internal void
Win32DisplayBufferInWindow(HDC DeviceContext, int32 Width, int32 Height)
{
    glViewport(0, 0, Width, Height);
    glClearColor(1.0f, 0.0f, 1.0f, 0.0f);
    glClear(GL_COLOR_BUFFER_BIT);
    SwapBuffers(DeviceContext);
}

internal void
Win32InitOpenGL(HWND Window)
{
    HDC DeviceContext = GetDC(Window);
    HGLRC OpenGLRC = wglCreateContext(DeviceContext);

    PIXELFORMATDESCRIPTOR DesiredPixelFormat = {};
    DesiredPixelFormat.nSize = sizeof(DesiredPixelFormat);
    DesiredPixelFormat.nVersion = 1;
    DesiredPixelFormat.dwFlags = PFD_SUPPORT_OPENGL|PFD_DRAW_TO_WINDOW|PFD_DOUBLEBUFFER;
    DesiredPixelFormat.cColorBits = 32;
    DesiredPixelFormat.cAlphaBits = 8;
    DesiredPixelFormat.iLayerType = PFD_MAIN_PLANE;

    int32 SuggestedPixelFormatIndex = ChoosePixelFormat(DeviceContext, &DesiredPixelFormat);
    PIXELFORMATDESCRIPTOR SuggestedPixelFormat = {};
    DescribePixelFormat(DeviceContext, SuggestedPixelFormatIndex,
                        sizeof(SuggestedPixelFormat),
                        &SuggestedPixelFormat);
    SetPixelFormat(DeviceContext, SuggestedPixelFormatIndex, &SuggestedPixelFormat);
    
    if(wglMakeCurrent(DeviceContext, OpenGLRC))
    {
        int32 Y = 6;
    }
    else
    {
        int32 Y = 6;
    }

    ReleaseDC(Window, DeviceContext);
}

internal LRESULT CALLBACK
Win32MainWindowCallback(HWND Window,
                        UINT Message,
                        WPARAM WParam,
                        LPARAM LParam)
{
    LRESULT Result = 0;
    
    switch(Message)
    {
        case WM_CLOSE:
        {
            GlobalRunning = false;
        } break;

        case WM_PAINT:
        {
            PAINTSTRUCT Paint;

            HDC DeviceContext = BeginPaint(Window, &Paint);
            win32_window_dimension WindowSize = Win32GetWindowSize(Window);
            Win32DisplayBufferInWindow(DeviceContext, WindowSize.Width, WindowSize.Height);

            EndPaint(Window, &Paint);
        }
        
        default:
        {
            Result = DefWindowProc(Window, Message, WParam, LParam);
        } break;
    }

    return(Result);
}

int CALLBACK
WinMain(HINSTANCE Instance,
        HINSTANCE PrevInstance,
        LPSTR CommandLine,
        int ShowCode)
{
    WNDCLASS WindowClass = {};
    WindowClass.style = CS_HREDRAW|CS_VREDRAW|CS_OWNDC;
    WindowClass.lpfnWndProc = Win32MainWindowCallback;
    WindowClass.hInstance = Instance;
    WindowClass.hCursor = LoadCursor(0, IDC_ARROW);
    WindowClass.lpszClassName = "ToastWindowClass";

    if(RegisterClass(&WindowClass))
    {
        HWND Window = CreateWindowEx(0,
                                     WindowClass.lpszClassName,
                                     "Toast Game",
                                     WS_OVERLAPPEDWINDOW,
                                     CW_USEDEFAULT,
                                     CW_USEDEFAULT,
                                     CW_USEDEFAULT,
                                     CW_USEDEFAULT,
                                     0,
                                     0,
                                     Instance,
                                     0);

        if(Window)
        {
            GlobalRunning = true;

            Win32InitOpenGL(Window);
            ShowWindow(Window, ShowCode);
            
            HDC DeviceContext = GetDC(Window);
            MSG Message = {};
            while(GlobalRunning)
            {
                while(PeekMessage(&Message, 0, 0, 0, PM_REMOVE))
                {
                    TranslateMessage(&Message);
                    DispatchMessage(&Message);
                }

                win32_window_dimension WindowSize = Win32GetWindowSize(Window);
                Win32DisplayBufferInWindow(DeviceContext, WindowSize.Width, WindowSize.Height);
            }
        }
    }
    
    return(0);
}
Casey Muratori
801 posts / 1 project
Casey Muratori is a programmer at Molly Rocket on the game 1935 and is the host of the educational programming series Handmade Hero.
Can't get opengl to draw anything in a simple window
Did you check to see that you actually got an OpenGL context? My guess is that your wglMakeCurrent succeeds because the HGLRC is actually 0, meaning you didn't get one, and so all it's doing is saying "make no context current". I would check the return value of wglCreateContext.

If I had to guess from just grazing the code, I'd say the problem is that you're trying to create the context _before_ setting the pixel format. But you have to set the pixel format _first_, _then_ create the context.

- Casey
Tucker
4 posts
Can't get opengl to draw anything in a simple window
That was absolutely the problem. Thank you so much Casey! That was driving me nuts! Wasn't expecting anyone to actually answer because random code dumps that just say hey fix this for me are kinda the worst. Thanks again and thank you for everything you have done, I have learned more from you than I have from my 3 years in collage so far!
Andrew Smith
13 posts
Programmer at Sucker Punch Productions
Can't get opengl to draw anything in a simple window
Glad you got the issue fixed. I'm only on day 70, so I don't know what all Casey covers as far as OpenGL goes, but if you want some fantastic tutorials on OpenGL that start completely introductory and move on to much more advanced things, I highly highly recommend http://learnopengl.com/

i just started learning OpenGL about a month ago and those tutorials have been invaluable.
Timothy Wright
76 posts / 1 project
Can't get opengl to draw anything in a simple window
Here are some other resources I've found useful for OpenGL stuff.

https://www.youtube.com/user/jeffchastine/videos
http://ogldev.atspace.co.uk/index.html