Project
Loading...
Searching...
No Matches
GPUDisplayFrontendWindows.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
14
15// Now the other headers
16#include <cstdio>
17#include <cstdlib>
18#include <cstring>
22#include "GPULogging.h"
23#include <windows.h>
24#include <winbase.h>
25#include <windowsx.h>
26
27using namespace o2::gpu;
28
29HDC hDC = nullptr; // Private GDI Device Context
30HGLRC hRC = nullptr; // Permanent Rendering Context
31HWND hWnd = nullptr; // Holds Our Window Handle
32HINSTANCE hInstance; // Holds The Instance Of The Application
33LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); // Declaration For WndProc
34
35bool active = TRUE; // Window Active Flag Set To TRUE By Default
36bool fullscreen = TRUE; // Fullscreen Flag Set To Fullscreen Mode By Default
37
39
40volatile int32_t mouseReset = false;
41
42void KillGLWindow() // Properly Kill The Window
43{
44 if (fullscreen) // Are We In Fullscreen Mode?
45 {
46 ChangeDisplaySettings(nullptr, 0); // If So Switch Back To The Desktop
47 ShowCursor(TRUE); // Show Mouse Pointer
48 }
49
50 if (hRC) // Do We Have A Rendering Context?
51 {
52 if (!wglMakeCurrent(nullptr, nullptr)) { // Are We Able To Release The DC And RC Contexts?
53 MessageBox(nullptr, "Release Of DC And RC Failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);
54 }
55
56 if (!wglDeleteContext(hRC)) { // Are We Able To Delete The RC?
57 MessageBox(nullptr, "Release Rendering Context Failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);
58 }
59 hRC = nullptr;
60 }
61
62 if (hDC && !ReleaseDC(hWnd, hDC)) // Are We Able To Release The DC
63 {
64 MessageBox(nullptr, "Release Device Context Failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);
65 hDC = nullptr;
66 }
67
68 if (hWnd && !DestroyWindow(hWnd)) // Are We Able To Destroy The Window?
69 {
70 MessageBox(nullptr, "Could Not Release hWnd.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);
71 hWnd = nullptr;
72 }
73
74 if (!UnregisterClass("OpenGL", hInstance)) // Are We Able To Unregister Class
75 {
76 MessageBox(nullptr, "Could Not Unregister Class.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);
77 hInstance = nullptr;
78 }
79}
80
81BOOL CreateGLWindow(char* title, int32_t width, int32_t height, int32_t bits, bool fullscreenflag)
82{
83 GLuint PixelFormat; // Holds The Results After Searching For A Match
84 WNDCLASS wc; // Windows Class Structure
85 DWORD dwExStyle; // Window Extended Style
86 DWORD dwStyle; // Window Style
87 RECT WindowRect; // Grabs Rectangle Upper Left / Lower Right Values
88 WindowRect.left = (int64_t)0; // Set Left Value To 0
89 WindowRect.right = (int64_t)width; // Set Right Value To Requested Width
90 WindowRect.top = (int64_t)0; // Set Top Value To 0
91 WindowRect.bottom = (int64_t)height; // Set Bottom Value To Requested Height
92
93 fullscreen = fullscreenflag; // Set The Global Fullscreen Flag
94
95 hInstance = GetModuleHandle(nullptr); // Grab An Instance For Our Window
96 wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; // Redraw On Size, And Own DC For Window.
97 wc.lpfnWndProc = (WNDPROC)WndProc; // WndProc Handles Messages
98 wc.cbClsExtra = 0; // No Extra Window Data
99 wc.cbWndExtra = 0; // No Extra Window Data
100 wc.hInstance = hInstance; // Set The Instance
101 wc.hIcon = LoadIcon(nullptr, IDI_WINLOGO); // Load The Default Icon
102 wc.hCursor = LoadCursor(nullptr, IDC_ARROW); // Load The Arrow Pointer
103 wc.hbrBackground = nullptr; // No Background Required For GL
104 wc.lpszMenuName = nullptr; // We Don't Want A Menu
105 wc.lpszClassName = "OpenGL"; // Set The Class Name
106
107 if (!RegisterClass(&wc)) // Attempt To Register The Window Class
108 {
109 MessageBox(nullptr, "Failed To Register The Window Class.", "ERROR", MB_OK | MB_ICONEXCLAMATION);
110 return FALSE; // Return FALSE
111 }
112
113 if (fullscreen) // Attempt Fullscreen Mode?
114 {
115 DEVMODE dmScreenSettings; // Device Mode
116 memset(&dmScreenSettings, 0, sizeof(dmScreenSettings)); // Makes Sure Memory's Cleared
117 dmScreenSettings.dmSize = sizeof(dmScreenSettings); // Size Of The Devmode Structure
118 dmScreenSettings.dmPelsWidth = width; // Selected Screen Width
119 dmScreenSettings.dmPelsHeight = height; // Selected Screen Height
120 dmScreenSettings.dmBitsPerPel = bits; // Selected Bits Per Pixel
121 dmScreenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
122
123 if (ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL) {
124 GPUError("The Requested Fullscreen Mode Is Not Supported By Your Video Card.");
125 return (FALSE);
126 }
127
128 dwExStyle = WS_EX_APPWINDOW;
129 dwStyle = WS_POPUP;
130 ShowCursor(FALSE);
131 } else {
132 dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; // Window Extended Style
133 dwStyle = WS_OVERLAPPEDWINDOW; // Windows Style
134 }
135
136 AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle);
137
138 // Create The Window
139 if (!(hWnd = CreateWindowEx(dwExStyle, "OpenGL", title, dwStyle | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, 0, 0, WindowRect.right - WindowRect.left, WindowRect.bottom - WindowRect.top, nullptr, nullptr, hInstance, nullptr))) {
140 KillGLWindow();
141 MessageBox(nullptr, "Window Creation Error.", "ERROR", MB_OK | MB_ICONEXCLAMATION);
142 return FALSE;
143 }
144
145 static PIXELFORMATDESCRIPTOR pfd = // pfd Tells Windows How We Want Things To Be
146 {
147 sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor
148 1, // Version Number
149 PFD_DRAW_TO_WINDOW | // Format Must Support Window
150 PFD_SUPPORT_OPENGL | // Format Must Support OpenGL
151 PFD_DOUBLEBUFFER, // Must Support Double Buffering
152 PFD_TYPE_RGBA, // Request An RGBA Format
153 (uint8_t)bits, // Select Our Color Depth
154 0,
155 0,
156 0,
157 0,
158 0,
159 0, // Color Bits Ignored
160 0, // No Alpha Buffer
161 0, // Shift Bit Ignored
162 0, // No Accumulation Buffer
163 0,
164 0,
165 0,
166 0, // Accumulation Bits Ignored
167 16, // 16Bit Z-Buffer (Depth Buffer)
168 0, // No Stencil Buffer
169 0, // No Auxiliary Buffer
170 PFD_MAIN_PLANE, // Main Drawing Layer
171 0, // Reserved
172 0,
173 0,
174 0 // Layer Masks Ignored
175 };
176
177 if (!(hDC = GetDC(hWnd))) // Did We Get A Device Context?
178 {
179 KillGLWindow();
180 MessageBox(nullptr, "Can't Create A GL Device Context.", "ERROR", MB_OK | MB_ICONEXCLAMATION);
181 return FALSE;
182 }
183
184 if (!(PixelFormat = ChoosePixelFormat(hDC, &pfd))) // Did Windows Find A Matching Pixel Format?
185 {
186 KillGLWindow();
187 MessageBox(nullptr, "Can't Find A Suitable PixelFormat.", "ERROR", MB_OK | MB_ICONEXCLAMATION);
188 return FALSE;
189 }
190
191 if (!SetPixelFormat(hDC, PixelFormat, &pfd)) // Are We Able To Set The Pixel Format?
192 {
193 KillGLWindow();
194 MessageBox(nullptr, "Can't Set The PixelFormat.", "ERROR", MB_OK | MB_ICONEXCLAMATION);
195 return FALSE;
196 }
197
198 if (!(hRC = wglCreateContext(hDC))) // Are We Able To Get A Rendering Context?
199 {
200 KillGLWindow();
201 MessageBox(nullptr, "Can't Create A GL Rendering Context.", "ERROR", MB_OK | MB_ICONEXCLAMATION);
202 return FALSE;
203 }
204
205 if (!wglMakeCurrent(hDC, hRC)) // Try To Activate The Rendering Context
206 {
207 KillGLWindow();
208 MessageBox(nullptr, "Can't Activate The GL Rendering Context.", "ERROR", MB_OK | MB_ICONEXCLAMATION);
209 return FALSE;
210 }
211
212 ShowWindow(hWnd, SW_SHOW);
213 SetForegroundWindow(hWnd);
214 SetFocus(hWnd);
215 ResizeScene(width, height);
216
217 return TRUE;
218}
219
220int32_t GetKey(int32_t key)
221{
222 if (key == 107 || key == 187) {
223 return ('+');
224 }
225 if (key == 109 || key == 189) {
226 return ('-');
227 }
228 if (key >= 'a' && key <= 'z') {
229 key += 'A' - 'a';
230 }
231
232 return (key);
233}
234
235LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
236{
237 switch (uMsg) // Check For Windows Messages
238 {
239 case WM_ACTIVATE: // Watch For Window Activate Message, check minimization state
240 if (!HIWORD(wParam)) {
241 active = TRUE;
242 } else {
243 active = FALSE;
244 }
245 return 0;
246
247 case WM_SYSCOMMAND: // Intercept System Commands
248 switch (wParam) // Check System Calls
249 {
250 case SC_SCREENSAVE: // Screensaver Trying To Start?
251 case SC_MONITORPOWER: // Monitor Trying To Enter Powersave?
252 return 0; // Prevent From Happening
253 }
254 break; // Exit
255
256 case WM_CLOSE: // Did We Receive A Close Message?
257 PostQuitMessage(0);
258 return 0;
259
260 case WM_KEYDOWN: // Is A Key Being Held Down?
261 wParam = GetKey(wParam);
262 mKeys[wParam] = TRUE;
263 mKeysShift[wParam] = mKeys[KEY_SHIFT];
264 HandleKey(wParam);
265 return 0;
266
267 case WM_KEYUP:
268 wParam = GetKey(wParam);
269 mKeysShift[wParam] = false;
270 mKeys[wParam] = false;
271 GPUInfo("Key: %d", wParam);
272 return 0;
273
274 case WM_SIZE:
275 ResizeScene(LOWORD(lParam), HIWORD(lParam)); // LoWord=Width, HiWord=Height
276 return 0;
277
278 case WM_LBUTTONDOWN:
279 mMouseDnX = GET_X_LPARAM(lParam);
280 mMouseDnY = GET_Y_LPARAM(lParam);
281 mMouseDn = true;
282 GetCursorPos(&mouseCursorPos);
283 return 0;
284
285 case WM_LBUTTONUP:
286 mMouseDn = false;
287 return 0;
288
289 case WM_RBUTTONDOWN:
290 mMouseDnX = GET_X_LPARAM(lParam);
291 mMouseDnY = GET_Y_LPARAM(lParam);
292 mMouseDnR = true;
293 GetCursorPos(&mouseCursorPos);
294 return 0;
295
296 case WM_RBUTTONUP:
297 mMouseDnR = false;
298 return 0;
299
300 case WM_MOUSEMOVE:
301 if (mouseReset) {
302 mMouseDnX = GET_X_LPARAM(lParam);
303 mMouseDnY = GET_Y_LPARAM(lParam);
304 mouseReset = 0;
305 }
306 mMouseMvX = GET_X_LPARAM(lParam);
307 mMouseMvY = GET_Y_LPARAM(lParam);
308 return 0;
309
310 case WM_MOUSEWHEEL:
311 mMouseWheel += GET_WHEEL_DELTA_WPARAM(wParam);
312 return 0;
313 }
314
315 // Pass All Unhandled Messages To DefWindowProc
316 return DefWindowProc(hWnd, uMsg, wParam, lParam);
317}
318
324
325int32_t GPUDisplayFrontendWindows::FrontendMain()
326{
327 MSG msg;
328 BOOL done = FALSE;
330
331 if (glewInit()) {
332 return (-1);
333 }
334
336 return -1;
337 }
338
339 if (InitDisplay()) {
340 KillGLWindow();
341 GPUError("Initialization Failed.");
342 return 1;
343 }
344
345 while (!done) {
346 if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) // Is There A Message Waiting?
347 {
348 if (msg.message == WM_QUIT) {
349 done = TRUE;
350 } else {
351 TranslateMessage(&msg); // Translate The Message
352 DispatchMessage(&msg); // Dispatch The Message
353 }
354 } else {
355 if (active) // Program Active?
356 {
357 if (mKeys[VK_ESCAPE]) {
358 done = TRUE;
359 } else {
360 DrawGLScene(); // Draw The Scene
361 SwapBuffers(hDC); // Swap Buffers (Double Buffering)
362 }
363 }
364 }
365 }
366
367 // Shutdown
368 ExitDisplay();
369 KillGLWindow();
370 return (0);
371}
372
373void DisplayExit() {}
374void OpenGLPrint(const char* s, float x, float y, float r, float g, float b, float a, bool fromBotton) {}
375void SwitchFullscreen(bool set) {}
376void ToggleMaximized(bool set) {}
377void SetVSync(bool enable) {}
378
380{
381 HANDLE hThread;
382 if ((hThread = CreateThread(nullptr, nullptr, &OpenGLWrapper, this, nullptr, nullptr)) == nullptr) {
383 GPUError("Coult not Create GL Thread...");
384 return (1);
385 }
386 return (0);
387}
BOOL CreateGLWindow(char *title, int32_t width, int32_t height, int32_t bits, bool fullscreenflag)
POINT mouseCursorPos
HINSTANCE hInstance
void SetVSync(bool enable)
volatile int32_t mouseReset
void OpenGLPrint(const char *s, float x, float y, float r, float g, float b, float a, bool fromBotton)
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM)
void SwitchFullscreen(bool set)
void KillGLWindow()
int32_t GetKey(int32_t key)
void ToggleMaximized(bool set)
bool done
StringRef key
static constexpr const char * DISPLAY_WINDOW_NAME
static constexpr int32_t INIT_WIDTH
int32_t InitDisplay(bool initFailure=false)
static constexpr int32_t INIT_HEIGHT
GLint GLenum GLint x
Definition glcorearb.h:403
GLint GLsizei GLsizei height
Definition glcorearb.h:270
GLint GLsizei width
Definition glcorearb.h:270
unsigned int GLuint
Definition glcorearb.h:88
GLboolean GLboolean GLboolean b
Definition glcorearb.h:1233
GLenum GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const void * bits
Definition glcorearb.h:4150
GLboolean GLboolean g
Definition glcorearb.h:1233
GLboolean enable
Definition glcorearb.h:3991
GLboolean r
Definition glcorearb.h:1233
GLboolean GLboolean GLboolean GLboolean a
Definition glcorearb.h:1233
#define TRUE
Definition list.h:27
#define FALSE
Definition list.h:28
uint64_t const void const *restrict const msg
Definition x9.h:153