10 #include "../stdafx.h"
11 #include "../openttd.h"
12 #include "../gfx_func.h"
13 #include "../os/windows/win32.h"
15 #include "../blitter/factory.hpp"
16 #include "../core/geometry_func.hpp"
17 #include "../core/math_func.hpp"
18 #include "../core/random_func.hpp"
19 #include "../texteff.hpp"
20 #include "../thread.h"
21 #include "../progress.h"
22 #include "../window_gui.h"
23 #include "../window_func.h"
24 #include "../framerate_type.h"
29 #include "../safeguards.h"
32 #ifndef MAPVK_VK_TO_CHAR
33 #define MAPVK_VK_TO_CHAR (2)
37 #define PM_QS_INPUT 0x20000
40 bool _window_maximize;
47 bool VideoDriver_Win32Base::ClaimMousePointer()
49 MyShowCursor(
false,
true);
59 #define AS(x, z) {x, 0, z}
60 #define AM(x, y, z, w) {x, y - x, z}
64 AM(VK_PRIOR, VK_DOWN, WKC_PAGEUP, WKC_DOWN),
66 AM(
'A',
'Z',
'A',
'Z'),
67 AM(
'0',
'9',
'0',
'9'),
69 AS(VK_ESCAPE, WKC_ESC),
70 AS(VK_PAUSE, WKC_PAUSE),
71 AS(VK_BACK, WKC_BACKSPACE),
72 AM(VK_INSERT, VK_DELETE, WKC_INSERT, WKC_DELETE),
74 AS(VK_SPACE, WKC_SPACE),
75 AS(VK_RETURN, WKC_RETURN),
79 AM(VK_F1, VK_F12, WKC_F1, WKC_F12),
82 AM(VK_NUMPAD0, VK_NUMPAD9,
'0',
'9'),
83 AS(VK_DIVIDE, WKC_NUM_DIV),
84 AS(VK_MULTIPLY, WKC_NUM_MUL),
85 AS(VK_SUBTRACT, WKC_NUM_MINUS),
86 AS(VK_ADD, WKC_NUM_PLUS),
87 AS(VK_DECIMAL, WKC_NUM_DECIMAL),
103 static uint MapWindowsKey(uint sym)
108 for (map = _vk_mapping; map !=
endof(_vk_mapping); ++map) {
109 if ((uint)(sym - map->vk_from) <= map->vk_count) {
110 key = sym - map->vk_from + map->map_to;
115 if (GetAsyncKeyState(VK_SHIFT) < 0) key |= WKC_SHIFT;
116 if (GetAsyncKeyState(VK_CONTROL) < 0) key |= WKC_CTRL;
117 if (GetAsyncKeyState(VK_MENU) < 0) key |= WKC_ALT;
137 _fullscreen = full_screen;
159 if (settings.dmBitsPerPel == 8 && ChangeDisplaySettings(&
settings, CDS_FULLSCREEN | CDS_TEST) != DISP_CHANGE_SUCCESSFUL) {
164 if (ChangeDisplaySettings(&
settings, CDS_FULLSCREEN | CDS_TEST) != DISP_CHANGE_SUCCESSFUL) {
166 GetWindowRect(GetDesktopWindow(), &r);
169 if ((
int)
settings.dmPelsWidth != r.right - r.left || (
int)
settings.dmPelsHeight != r.bottom - r.top) {
174 if (ChangeDisplaySettings(&
settings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL) {
180 ChangeDisplaySettings(
nullptr, 0);
182 this->
width = _bck_resolution.width;
183 this->
height = _bck_resolution.height;
188 DWORD style, showstyle;
191 showstyle = SW_SHOWNORMAL;
197 style = WS_OVERLAPPEDWINDOW;
199 if (_window_maximize) showstyle = SW_SHOWMAXIMIZED;
203 AdjustWindowRect(&r, style, FALSE);
204 w = r.right - r.left;
205 h = r.bottom - r.top;
208 if (!_window_maximize) SetWindowPos(this->
main_wnd, 0, 0, 0, w, h, SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER | SWP_NOMOVE);
210 int x = (GetSystemMetrics(SM_CXSCREEN) - w) / 2;
211 int y = (GetSystemMetrics(SM_CYSCREEN) - h) / 2;
213 char window_title[64];
214 seprintf(window_title,
lastof(window_title),
"OpenTTD %s", _openttd_revision);
216 this->
main_wnd = CreateWindow(L
"OTTD",
OTTD2FS(window_title), style, x, y, w, h, 0, 0, GetModuleHandle(
nullptr),
this);
218 ShowWindow(this->
main_wnd, showstyle);
236 static WChar prev_char = 0;
240 if (prev_char != 0)
DEBUG(driver, 1,
"Got two UTF-16 lead surrogates, dropping the first one");
241 prev_char = charcode;
246 if (prev_char != 0) {
250 DEBUG(driver, 1,
"Got an UTF-16 lead surrogate without a trail surrogate, dropping the lead surrogate");
263 return (_imm_props & IME_PROP_AT_CARET) && !(_imm_props & IME_PROP_SPECIAL_UI);
269 HIMC hIMC = ImmGetContext(hwnd);
272 cf.dwStyle = CFS_POINT;
277 cf.ptCurrentPos.x = _focused_window->
left + pt.x;
278 cf.ptCurrentPos.y = _focused_window->
top + pt.y;
280 cf.ptCurrentPos.x = 0;
281 cf.ptCurrentPos.y = 0;
283 ImmSetCompositionWindow(hIMC, &cf);
285 ImmReleaseContext(hwnd, hIMC);
291 HIMC hIMC = ImmGetContext(hwnd);
295 cf.dwStyle = CFS_EXCLUDE;
299 cf.ptCurrentPos.x = _focused_window->
left + pt.x;
300 cf.ptCurrentPos.y = _focused_window->
top + pt.y;
302 cf.rcArea.left = _focused_window->
left;
303 cf.rcArea.top = _focused_window->
top;
304 cf.rcArea.right = _focused_window->
left + _focused_window->
width;
305 cf.rcArea.bottom = _focused_window->
top + _focused_window->
height;
313 cf.ptCurrentPos.x = 0;
314 cf.ptCurrentPos.y = 0;
315 SetRectEmpty(&cf.rcArea);
317 ImmSetCandidateWindow(hIMC, &cf);
319 ImmReleaseContext(hwnd, hIMC);
325 HIMC hIMC = ImmGetContext(hwnd);
328 if (lParam & GCS_RESULTSTR) {
330 LONG len = ImmGetCompositionString(hIMC, GCS_RESULTSTR,
nullptr, 0);
331 wchar_t *str = (
wchar_t *)_alloca(len +
sizeof(
wchar_t));
332 len = ImmGetCompositionString(hIMC, GCS_RESULTSTR, str, len);
333 str[len /
sizeof(wchar_t)] =
'\0';
343 lParam &= ~(GCS_RESULTSTR | GCS_RESULTCLAUSE | GCS_RESULTREADCLAUSE | GCS_RESULTREADSTR);
348 LONG len = ImmGetCompositionString(hIMC, GCS_COMPSTR,
nullptr, 0);
349 wchar_t *str = (
wchar_t *)_alloca(len +
sizeof(
wchar_t));
350 len = ImmGetCompositionString(hIMC, GCS_COMPSTR, str, len);
351 str[len /
sizeof(wchar_t)] =
'\0';
354 static char utf8_buf[1024];
358 LONG caret_bytes = ImmGetCompositionString(hIMC, GCS_CURSORPOS,
nullptr, 0);
359 const char *caret = utf8_buf;
360 for (
const wchar_t *c = str; *c !=
'\0' && *caret !=
'\0' && caret_bytes > 0; c++, caret_bytes--) {
374 lParam &= ~(GCS_COMPSTR | GCS_COMPATTR | GCS_COMPCLAUSE | GCS_CURSORPOS | GCS_DELTASTART);
377 ImmReleaseContext(hwnd, hIMC);
379 return lParam != 0 ? DefWindowProc(hwnd, WM_IME_COMPOSITION, wParam, lParam) : 0;
385 HIMC hIMC = ImmGetContext(hwnd);
386 if (hIMC != NULL) ImmNotifyIME(hIMC, NI_COMPOSITIONSTR, CPS_CANCEL, 0);
387 ImmReleaseContext(hwnd, hIMC);
392 LRESULT CALLBACK WndProcGdi(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
394 static uint32 keycode = 0;
395 static bool console =
false;
401 SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)((LPCREATESTRUCT)lParam)->lpCreateParams);
409 GetUpdateRect(hwnd, &r, FALSE);
410 video_driver->
MakeDirty(r.left, r.top, r.right - r.left, r.bottom - r.top);
412 ValidateRect(hwnd,
nullptr);
416 case WM_PALETTECHANGED:
417 if ((HWND)wParam == hwnd)
return 0;
420 case WM_QUERYNEWPALETTE:
425 HandleExitGameRequest();
466 int x = (int16)LOWORD(lParam);
467 int y = (int16)HIWORD(lParam);
475 tme.cbSize =
sizeof(tme);
476 tme.dwFlags = TME_LEAVE;
477 tme.hwndTrack = hwnd;
479 TrackMouseEvent(&tme);
486 while (PeekMessage(&m, hwnd, WM_MOUSEMOVE, WM_MOUSEMOVE, PM_REMOVE | PM_NOYIELD | PM_QS_INPUT)) {
487 x = (int16)LOWORD(m.lParam);
488 y = (int16)HIWORD(m.lParam);
494 pt.x = _cursor.
pos.x;
495 pt.y = _cursor.
pos.y;
496 ClientToScreen(hwnd, &pt);
497 SetCursorPos(pt.x, pt.y);
504 case WM_INPUTLANGCHANGE:
508 case WM_IME_SETCONTEXT:
513 case WM_IME_STARTCOMPOSITION:
518 case WM_IME_COMPOSITION:
521 case WM_IME_ENDCOMPOSITION:
532 console =
GB(lParam, 16, 8) == 41;
536 uint scancode =
GB(lParam, 16, 8);
537 uint charcode = wParam;
541 if (console && scancode == 41) {
548 uint cur_keycode = keycode;
556 uint scancode =
GB(lParam, 16, 8);
557 keycode = scancode == 41 ? (uint)WKC_BACKQUOTE : MapWindowsKey(wParam);
561 if (PeekMessage(&msg,
nullptr, 0, 0, PM_NOREMOVE)) {
562 if ((msg.message == WM_CHAR || msg.message == WM_DEADCHAR) &&
GB(lParam, 16, 8) ==
GB(msg.lParam, 16, 8)) {
567 uint charcode = MapVirtualKey(wParam, MAPVK_VK_TO_CHAR);
576 if (
HasBit(charcode, 31) && !console) {
577 if (scancode == 41) {
586 uint cur_keycode = keycode;
613 if (wParam != SIZE_MINIMIZED) {
616 _window_maximize = (wParam == SIZE_MAXIMIZED || (_window_maximize && _fullscreen));
617 if (_window_maximize || _fullscreen) _bck_resolution =
_cur_resolution;
618 video_driver->ClientSizeChanged(LOWORD(lParam), HIWORD(lParam));
623 RECT *r = (RECT*)lParam;
627 SetRect(&r2, 0, 0, 0, 0);
628 AdjustWindowRect(&r2, GetWindowLong(hwnd, GWL_STYLE), FALSE);
630 w = r->right - r->left - (r2.right - r2.left);
631 h = r->bottom - r->top - (r2.bottom - r2.top);
634 SetRect(&r2, 0, 0, w, h);
636 AdjustWindowRect(&r2, GetWindowLong(hwnd, GWL_STYLE), FALSE);
637 w = r2.right - r2.left;
638 h = r2.bottom - r2.top;
642 r->bottom = r->top + h;
645 case WMSZ_BOTTOMLEFT:
646 r->bottom = r->top + h;
647 r->left = r->right - w;
650 case WMSZ_BOTTOMRIGHT:
651 r->bottom = r->top + h;
652 r->right = r->left + w;
656 r->left = r->right - w;
660 r->right = r->left + w;
664 r->top = r->bottom - h;
668 r->top = r->bottom - h;
669 r->left = r->right - w;
673 r->top = r->bottom - h;
674 r->right = r->left + w;
681 #if !defined(WM_MOUSEWHEEL)
682 # define WM_MOUSEWHEEL 0x020A
684 #if !defined(GET_WHEEL_DELTA_WPARAM)
685 # define GET_WHEEL_DELTA_WPARAM(wparam) ((short)HIWORD(wparam))
688 case WM_MOUSEWHEEL: {
689 int delta = GET_WHEEL_DELTA_WPARAM(wParam);
693 }
else if (delta > 0) {
711 if (_exit_game)
break;
713 bool active = (LOWORD(wParam) != WA_INACTIVE);
714 bool minimized = (HIWORD(wParam) != 0);
716 if (active && minimized) {
718 ShowWindow(hwnd, SW_RESTORE);
720 }
else if (!active && !minimized) {
722 ShowWindow(hwnd, SW_MINIMIZE);
723 ChangeDisplaySettings(
nullptr, 0);
730 return DefWindowProc(hwnd, msg, wParam, lParam);
733 static void RegisterWndClass()
735 static bool registered =
false;
737 if (registered)
return;
739 HINSTANCE hinst = GetModuleHandle(
nullptr);
746 LoadIcon(hinst, MAKEINTRESOURCE(100)),
747 LoadCursor(
nullptr, IDC_ARROW),
754 if (!RegisterClass(&wnd))
usererror(
"RegisterClass failed");
757 static const Dimension default_resolutions[] = {
771 static void FindResolutions(uint8 bpp)
776 for (uint i = 0; EnumDisplaySettings(
nullptr, i, &dm) != 0; i++) {
777 if (dm.dmBitsPerPel != bpp || dm.dmPelsWidth < 640 || dm.dmPelsHeight < 480)
continue;
779 _resolutions.emplace_back(dm.dmPelsWidth, dm.dmPelsHeight);
784 _resolutions.assign(std::begin(default_resolutions), std::end(default_resolutions));
790 void VideoDriver_Win32Base::Initialize()
808 if (this->
fullscreen) ChangeDisplaySettings(
nullptr, 0);
822 this->
MakeDirty(0, 0, _screen.width, _screen.height);
843 (GetAsyncKeyState(VK_LEFT) < 0 ? 1 : 0) +
844 (GetAsyncKeyState(VK_UP) < 0 ? 2 : 0) +
845 (GetAsyncKeyState(VK_RIGHT) < 0 ? 4 : 0) +
846 (GetAsyncKeyState(VK_DOWN) < 0 ? 8 : 0);
858 if (!PeekMessage(&mesg,
nullptr, 0, 0, PM_REMOVE))
return false;
862 DispatchMessage(&mesg);
869 std::thread draw_thread;
875 this->
draw_signal =
new std::condition_variable_any();
876 this->
draw_mutex =
new std::recursive_mutex();
882 this->draw_lock = std::unique_lock<std::recursive_mutex>(*this->
draw_mutex);
889 this->draw_lock.unlock();
890 this->draw_lock.release();
896 DEBUG(driver, 1,
"Threaded drawing enabled");
904 if (_exit_game)
break;
924 if (this->draw_lock.owns_lock()) this->draw_lock.unlock();
925 this->draw_lock.release();
935 void VideoDriver_Win32Base::ClientSizeChanged(
int w,
int h,
bool force)
952 std::unique_lock<std::recursive_mutex>
lock;
953 if (this->
draw_mutex !=
nullptr) lock = std::unique_lock<std::recursive_mutex>(*this->
draw_mutex);
955 if (_window_maximize) ShowWindow(this->
main_wnd, SW_SHOWNORMAL);
965 std::unique_lock<std::recursive_mutex>
lock;
966 if (this->
draw_mutex !=
nullptr) lock = std::unique_lock<std::recursive_mutex>(*this->
draw_mutex);
983 std::unique_lock<std::recursive_mutex>
lock;
984 if (this->
draw_mutex !=
nullptr) lock = std::unique_lock<std::recursive_mutex>(*this->
draw_mutex);
993 return {
static_cast<uint
>(GetSystemMetrics(SM_CXSCREEN)),
static_cast<uint
>(GetSystemMetrics(SM_CYSCREEN)) };
998 typedef UINT (WINAPI *PFNGETDPIFORWINDOW)(HWND hwnd);
999 typedef UINT (WINAPI *PFNGETDPIFORSYSTEM)(VOID);
1000 typedef HRESULT (WINAPI *PFNGETDPIFORMONITOR)(HMONITOR hMonitor,
int dpiType, UINT *dpiX, UINT *dpiY);
1002 static PFNGETDPIFORWINDOW _GetDpiForWindow =
nullptr;
1003 static PFNGETDPIFORSYSTEM _GetDpiForSystem =
nullptr;
1004 static PFNGETDPIFORMONITOR _GetDpiForMonitor =
nullptr;
1006 static bool init_done =
false;
1010 _GetDpiForWindow = (PFNGETDPIFORWINDOW)GetProcAddress(GetModuleHandle(L
"User32"),
"GetDpiForWindow");
1011 _GetDpiForSystem = (PFNGETDPIFORSYSTEM)GetProcAddress(GetModuleHandle(L
"User32"),
"GetDpiForSystem");
1012 _GetDpiForMonitor = (PFNGETDPIFORMONITOR)GetProcAddress(LoadLibrary(L
"Shcore.dll"),
"GetDpiForMonitor");
1017 if (cur_dpi == 0 && _GetDpiForWindow !=
nullptr && this->
main_wnd !=
nullptr) {
1019 cur_dpi = _GetDpiForWindow(this->
main_wnd);
1021 if (cur_dpi == 0 && _GetDpiForMonitor !=
nullptr && this->
main_wnd !=
nullptr) {
1024 if (SUCCEEDED(_GetDpiForMonitor(MonitorFromWindow(this->
main_wnd, MONITOR_DEFAULTTOPRIMARY), 0 , &dpiX, &dpiY))) {
1028 if (cur_dpi == 0 && _GetDpiForSystem !=
nullptr) {
1030 cur_dpi = _GetDpiForSystem();
1033 return cur_dpi > 0 ? cur_dpi / 96.0f : 1.0f;
1044 assert(_screen.dst_ptr !=
nullptr);
1051 assert(_screen.dst_ptr !=
nullptr);
1052 if (_screen.dst_ptr !=
nullptr) {
1055 _screen.dst_ptr =
nullptr;
1071 this->MakePalette();
1094 w = std::max(w, 64);
1095 h = std::max(h, 64);
1097 if (!force && w == _screen.width && h == _screen.height)
return false;
1099 BITMAPINFO *bi = (BITMAPINFO *)alloca(
sizeof(BITMAPINFOHEADER) +
sizeof(RGBQUAD) * 256);
1100 memset(bi, 0,
sizeof(BITMAPINFOHEADER) +
sizeof(RGBQUAD) * 256);
1101 bi->bmiHeader.biSize =
sizeof(BITMAPINFOHEADER);
1103 bi->bmiHeader.biWidth = this->
width = w;
1104 bi->bmiHeader.biHeight = -(this->
height = h);
1106 bi->bmiHeader.biPlanes = 1;
1107 bi->bmiHeader.biBitCount = bpp;
1108 bi->bmiHeader.biCompression = BI_RGB;
1113 this->
dib_sect = CreateDIBSection(dc, bi, DIB_RGB_COLORS, (VOID **)&this->
buffer_bits,
nullptr, 0);
1118 _screen.pitch = (bpp == 8) ?
Align(w, 4) : w;
1131 void VideoDriver_Win32GDI::MakePalette()
1137 LOGPALETTE *pal = (LOGPALETTE*)alloca(
sizeof(LOGPALETTE) + (256 - 1) *
sizeof(PALETTEENTRY));
1139 pal->palVersion = 0x300;
1140 pal->palNumEntries = 256;
1142 for (uint i = 0; i != 256; i++) {
1146 pal->palPalEntry[i].peFlags = 0;
1153 void VideoDriver_Win32GDI::UpdatePalette(HDC dc, uint start, uint count)
1157 for (uint i = 0; i != count; i++) {
1161 rgb[i].rgbReserved = 0;
1164 SetDIBColorTable(dc, start, count, rgb);
1169 HDC hDC = GetWindowDC(hWnd);
1170 HPALETTE hOldPalette = SelectPalette(hDC, this->
gdi_palette, FALSE);
1171 UINT nChanged = RealizePalette(hDC);
1173 SelectPalette(hDC, hOldPalette, TRUE);
1174 ReleaseDC(hWnd, hDC);
1175 if (nChanged != 0) this->
MakeDirty(0, 0, _screen.width, _screen.height);
1185 HDC dc2 = CreateCompatibleDC(dc);
1187 HBITMAP old_bmp = (HBITMAP)SelectObject(dc2, this->
dib_sect);
1188 HPALETTE old_palette = SelectPalette(dc, this->
gdi_palette, FALSE);
1199 bool need_buf = _screen.dst_ptr ==
nullptr;
1204 _screen.dst_ptr =
nullptr;
1218 BitBlt(dc, 0, 0, this->
width, this->
height, dc2, 0, 0, SRCCOPY);
1219 SelectPalette(dc, old_palette, TRUE);
1220 SelectObject(dc2, old_bmp);
1251 int VideoDriver_Win32GDI::RedrawScreenDebug()
1270 #include "../3rdparty/opengl/glext.h"
1271 #include "../3rdparty/opengl/wglext.h"
1274 #ifndef PFD_SUPPORT_COMPOSITION
1275 # define PFD_SUPPORT_COMPOSITION 0x00008000
1278 static PFNWGLCREATECONTEXTATTRIBSARBPROC _wglCreateContextAttribsARB =
nullptr;
1279 static PFNWGLSWAPINTERVALEXTPROC _wglSwapIntervalEXT =
nullptr;
1280 static bool _hasWGLARBCreateContextProfile =
false;
1285 OGLProc ret =
reinterpret_cast<OGLProc
>(wglGetProcAddress(proc));
1286 if (ret ==
nullptr) {
1288 ret =
reinterpret_cast<OGLProc
>(GetProcAddress(GetModuleHandle(L
"opengl32"), proc));
1299 static const char *SelectPixelFormat(HDC dc,
bool fullscreen)
1301 PIXELFORMATDESCRIPTOR pfd = {
1302 sizeof(PIXELFORMATDESCRIPTOR),
1304 PFD_DRAW_TO_WINDOW |
1305 PFD_SUPPORT_OPENGL |
1310 0, 0, 0, 0, 0, 0, 0, 0,
1321 int format = ChoosePixelFormat(dc, &pfd);
1322 if (format == 0)
return "No suitable pixel format found";
1323 if (!SetPixelFormat(dc, format, &pfd))
return "Can't set pixel format";
1329 static void LoadWGLExtensions()
1336 HWND wnd = CreateWindow(_T(
"STATIC"), _T(
"dummy"), WS_OVERLAPPEDWINDOW, 0, 0, 0, 0,
nullptr,
nullptr, GetModuleHandle(
nullptr),
nullptr);
1337 HDC dc = GetDC(wnd);
1340 if (SelectPixelFormat(dc,
false) ==
nullptr) {
1342 HGLRC rc = wglCreateContext(dc);
1343 if (rc !=
nullptr) {
1344 wglMakeCurrent(dc, rc);
1347 PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC)wglGetProcAddress(
"wglGetExtensionsStringARB");
1348 if (wglGetExtensionsStringARB !=
nullptr) {
1349 const char *wgl_exts = wglGetExtensionsStringARB(dc);
1352 _wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)wglGetProcAddress(
"wglCreateContextAttribsARB");
1356 _wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC)wglGetProcAddress(
"wglSwapIntervalEXT");
1360 wglMakeCurrent(
nullptr,
nullptr);
1361 wglDeleteContext(rc);
1369 static FVideoDriver_Win32OpenGL iFVideoDriver_Win32OpenGL;
1371 const char *VideoDriver_Win32OpenGL::Start(
const StringList ¶m)
1378 LoadWGLExtensions();
1381 this->MakeWindow(_fullscreen);
1384 const char *err = this->AllocateContext();
1385 if (err !=
nullptr) {
1391 this->ClientSizeChanged(this->width, this->height,
true);
1393 this->draw_threaded =
false;
1399 void VideoDriver_Win32OpenGL::Stop()
1401 this->DestroyContext();
1405 void VideoDriver_Win32OpenGL::DestroyContext()
1409 wglMakeCurrent(
nullptr,
nullptr);
1410 if (this->gl_rc !=
nullptr) {
1411 wglDeleteContext(this->gl_rc);
1412 this->gl_rc =
nullptr;
1414 if (this->dc !=
nullptr) {
1415 ReleaseDC(this->main_wnd, this->dc);
1420 const char *VideoDriver_Win32OpenGL::AllocateContext()
1422 this->dc = GetDC(this->main_wnd);
1424 const char *err = SelectPixelFormat(this->dc, this->fullscreen);
1425 if (err !=
nullptr)
return err;
1430 if (_wglCreateContextAttribsARB !=
nullptr) {
1432 WGL_CONTEXT_MAJOR_VERSION_ARB, 3,
1433 WGL_CONTEXT_MINOR_VERSION_ARB, 2,
1434 WGL_CONTEXT_FLAGS_ARB, _debug_driver_level >= 8 ? WGL_CONTEXT_DEBUG_BIT_ARB : 0,
1435 _hasWGLARBCreateContextProfile ? WGL_CONTEXT_PROFILE_MASK_ARB : 0, WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
1438 rc = _wglCreateContextAttribsARB(this->dc,
nullptr, attribs);
1441 if (rc ==
nullptr) {
1443 rc = wglCreateContext(this->dc);
1444 if (rc ==
nullptr)
return "Can't create OpenGL context";
1446 if (!wglMakeCurrent(this->dc, rc))
return "Can't active GL context";
1449 if (_wglSwapIntervalEXT !=
nullptr) {
1450 _wglSwapIntervalEXT(this->vsync ? 1 : 0);
1452 DEBUG(driver, 0,
"OpenGL: Vsync requested, but not supported by driver");
1459 bool VideoDriver_Win32OpenGL::ToggleFullscreen(
bool full_screen)
1461 if (_screen.dst_ptr !=
nullptr) this->ReleaseVideoPointer();
1462 this->DestroyContext();
1464 res &= this->AllocateContext() ==
nullptr;
1465 this->ClientSizeChanged(this->width, this->height,
true);
1469 bool VideoDriver_Win32OpenGL::AfterBlitterChange()
1472 this->ClientSizeChanged(this->width, this->height,
true);
1476 void VideoDriver_Win32OpenGL::ClearSystemSprites()
1481 bool VideoDriver_Win32OpenGL::AllocateBackingStore(
int w,
int h,
bool force)
1483 if (!force && w == _screen.width && h == _screen.height)
return false;
1485 this->width = w = std::max(w, 64);
1486 this->height = h = std::max(h, 64);
1488 if (this->gl_rc ==
nullptr)
return false;
1490 if (_screen.dst_ptr !=
nullptr) this->ReleaseVideoPointer();
1492 this->dirty_rect = {};
1494 _screen.dst_ptr = this->GetVideoPointer();
1499 void *VideoDriver_Win32OpenGL::GetVideoPointer()
1507 void VideoDriver_Win32OpenGL::ReleaseVideoPointer()
1511 this->dirty_rect = {};
1512 _screen.dst_ptr =
nullptr;
1513 this->anim_buffer =
nullptr;
1516 void VideoDriver_Win32OpenGL::Paint()
1535 SwapBuffers(this->dc);