前提・実現したいこと
メモリバッファを用いないOpenGL(WGL)のコードですがwglMakeCurrent
を呼ぶタイミングについての質問です.
メインスレッドでwglCreateContext
直後にwglMakeCurrent
を呼ぶと関数は成功するのですがGL_INVALID_OPERATION
となり描画されません.glBegin
~glEnd
内に不正な関数がある場合のエラーで関係ないと思いますが別スレッドのglBegin
前でwglMakeCurrent
を呼ばない成功します.wglMakeCurrent
をその位置で呼ばないとと失敗する理由とは何でしょうか?
ちなみに両方で呼ぶとスレッド内でのwglMakeCurrent
は失敗します.
発生している問題
100行目のwglMakeCurrent
(コメントアウトしてあります)と
143行目のwglMakeCurrent
該当のソースコード
C
1#pragma comment(lib, "OpenGL32.lib") 2 3#define UNICODE 4 5#include <windows.h> 6#include <process.h> 7#include <gl/GL.h> 8#include <gl/GLU.h> 9 10#define TM_CREATE WM_APP + WM_CREATE 11#define TM_PAINT WM_APP + WM_PAINT 12#define TM_DESTROY WM_APP + WM_DESTROY 13 14const wchar_t CLASS_NAME[] = L"OpenGL Line"; 15 16HDC hdc; 17HGLRC glrc; 18HANDLE hgl; 19 20HWND hWnd; 21 22unsigned thId; 23 24LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMes, WPARAM wParam, LPARAM lParam); 25DWORD WINAPI GLLoop(LPDWORD lpdata); 26 27int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) 28{ 29 UNREFERENCED_PARAMETER(hPrevInstance); 30 UNREFERENCED_PARAMETER(lpCmdLine); 31 32 33 WNDCLASSEX wcex = { 34 sizeof(WNDCLASSEX), CS_OWNDC | CS_HREDRAW | CS_VREDRAW, WindowProc, 0, 0, 35 hInstance, NULL, NULL, 36 (HBRUSH)GetStockObject(WHITE_BRUSH), NULL, CLASS_NAME, NULL 37 }; 38 39 if (!RegisterClassEx(&wcex))return 0; 40 41 RECT rc = { 0, 0, 640, 480 }; 42 if (!(hWnd = CreateWindowEx(0, CLASS_NAME, L"WGL Sample Window", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, rc.right - rc.left, rc.bottom - rc.top, NULL, NULL, hInstance, NULL)))return 0; 43 44 ShowWindow(hWnd, nCmdShow); 45 46 MSG msg = {}; 47 48 while (GetMessage(&msg, NULL, 0, 0) >= 0) { 49 TranslateMessage(&msg); 50 DispatchMessage(&msg); 51 } 52 53 return 0; 54} 55 56LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMes, WPARAM wParam, LPARAM lParam) { 57 switch (uMes) { 58 case WM_ERASEBKGND: 59 return -1; 60 61 case WM_CREATE: 62 { 63 PIXELFORMATDESCRIPTOR pfd = 64 { 65 sizeof(PIXELFORMATDESCRIPTOR), 66 1, 67 PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, 68 PFD_TYPE_RGBA, 69 32, 70 0, 0, 0, 0, 0, 0, 71 0, 72 0, 73 0, 74 0, 0, 0, 0, 75 24, 76 8, 77 0, 78 PFD_MAIN_PLANE, 79 0, 80 0, 0, 0 81 }; 82 83 hdc = GetDC(hwnd); 84 int format = ChoosePixelFormat(hdc, &pfd); 85 86 if (format == 0) { 87 MessageBox(hwnd, L"Format Error", L"Alert", MB_OK); 88 return -1; 89 } 90 91 if (!SetPixelFormat(hdc, format, &pfd)) { 92 MessageBox(hwnd, L"Set Pixel Error", L"Alert", MB_OK); 93 return -1; 94 } 95 96 glrc = wglCreateContext(hdc); 97 98 99 /* 100 101 どうやらここでwglMakeCurrentを呼ぶことがおかしい模様 102 103 if (!wglMakeCurrent(hdc, glrc)) { 104 MessageBox(hwnd, L"Make Current Error", L"Alert", MB_OK); 105 return -1; 106 } 107 108 */ 109 110 if ((hgl = (HANDLE)_beginthreadex(NULL, 0, (_beginthreadex_proc_type)GLLoop, NULL, 0, &thId)) == NULL) { 111 MessageBox(hwnd, L"Thread error", L"Caution", MB_OK); 112 return -1; 113 } 114 115 DWORD dwExCode; 116 while (GetExitCodeThread(hgl, &dwExCode) && dwExCode == STILL_ACTIVE && !PostThreadMessage(thId, WM_NULL, 0, 0))Sleep(1); 117 } 118 break; 119 120 case WM_PAINT: 121 PostThreadMessage(thId, TM_PAINT, 0, 0); 122 break; 123 124 case WM_DESTROY: 125 PostThreadMessage(thId, TM_DESTROY, 0, 0); 126 WaitForSingleObject(hgl, INFINITY); 127 PostQuitMessage(0); 128 return 0; 129 130 default: 131 return DefWindowProc(hwnd, uMes, wParam, lParam); 132 } 133} 134 135DWORD WINAPI GLLoop(LPDWORD lpdata) { 136 MSG tMsg = {}; 137 while (GetMessage(&tMsg, NULL, 0, 0) > 0) { 138 139 switch (tMsg.message) { 140 141 case TM_PAINT: 142 { 143 wglMakeCurrent(hdc, glrc); 144 145 glClearColor(0.0f, 0.5f, 1.0f, 1.0f); 146 glClear(GL_COLOR_BUFFER_BIT); 147 148 glBegin(GL_LINE_STRIP); 149 glVertex2f(0, 0); 150 glVertex2f(0.2, 0.9); 151 glVertex2f(0.4, -0.9); 152 glEnd(); 153 154 GLenum glen = glGetError(); 155 156 switch (glen) { 157 case GL_INVALID_ENUM: 158 MessageBox(hWnd, L"ENUM", L"GL ERROE", MB_OK); 159 break; 160 161 case GL_INVALID_OPERATION: 162 MessageBox(hWnd, L"OPERATION", L"GL ERROE", MB_OK); 163 break; 164 } 165 166 glFlush(); 167 SwapBuffers(hdc); 168 wglMakeCurrent(NULL, NULL); 169 } 170 break; 171 172 case TM_DESTROY: 173 wglMakeCurrent(NULL, NULL); 174 wglDeleteContext(glrc); 175 ReleaseDC(hWnd, hdc); 176 177 _endthreadex(0); 178 return 0; 179 } 180 181 } 182}
補足情報
Windows10 Pro
VisualStudio2017 Community

回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2019/03/11 17:34 編集