Project
Loading...
Searching...
No Matches
GPUDisplayFrontendGlfw.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
18#include "GPULogging.h"
19
20#ifdef GPUCA_BUILD_EVENT_DISPLAY_VULKAN
21#define GLFW_INCLUDE_VULKAN
22#endif
23#include <GLFW/glfw3.h>
24
25#include <cstdio>
26#include <cstring>
27#include <unistd.h>
28
29#ifndef GPUCA_STANDALONE
30#include <DebugGUI/imgui.h>
31#include <DebugGUI/DebugGUI.h>
32#endif
33
34using namespace o2::gpu;
35
41
42static GPUDisplayFrontendGlfw* me = nullptr;
43
44int32_t GPUDisplayFrontendGlfw::GetKey(int32_t key)
45{
46 if (key == GLFW_KEY_KP_SUBTRACT) {
47 return ('-');
48 }
49 if (key == GLFW_KEY_KP_ADD) {
50 return ('+');
51 }
52 if (key == GLFW_KEY_LEFT_SHIFT || key == GLFW_KEY_RIGHT_SHIFT) {
53 return (KEY_SHIFT);
54 }
55 if (key == GLFW_KEY_LEFT_ALT) {
56 return (KEY_ALT);
57 }
58 if (key == GLFW_KEY_RIGHT_ALT) {
59 return (KEY_RALT);
60 }
61 if (key == GLFW_KEY_LEFT_CONTROL) {
62 return (KEY_CTRL);
63 }
64 if (key == GLFW_KEY_RIGHT_CONTROL) {
65 return (KEY_RCTRL);
66 }
67 if (key == GLFW_KEY_UP) {
68 return (KEY_UP);
69 }
70 if (key == GLFW_KEY_DOWN) {
71 return (KEY_DOWN);
72 }
73 if (key == GLFW_KEY_LEFT) {
74 return (KEY_LEFT);
75 }
76 if (key == GLFW_KEY_RIGHT) {
77 return (KEY_RIGHT);
78 }
79 if (key == GLFW_KEY_PAGE_UP) {
80 return (KEY_PAGEUP);
81 }
82 if (key == GLFW_KEY_PAGE_DOWN) {
83 return (KEY_PAGEDOWN);
84 }
85 if (key == GLFW_KEY_ESCAPE) {
86 return (KEY_ESCAPE);
87 }
88 if (key == GLFW_KEY_SPACE) {
89 return (KEY_SPACE);
90 }
91 if (key == GLFW_KEY_HOME) {
92 return (KEY_HOME);
93 }
94 if (key == GLFW_KEY_END) {
95 return (KEY_END);
96 }
97 if (key == GLFW_KEY_INSERT) {
98 return (KEY_INSERT);
99 }
100 if (key == GLFW_KEY_ENTER) {
101 return (KEY_ENTER);
102 }
103 if (key == GLFW_KEY_F1) {
104 return (KEY_F1);
105 }
106 if (key == GLFW_KEY_F2) {
107 return (KEY_F2);
108 }
109 if (key == GLFW_KEY_F3) {
110 return (KEY_F3);
111 }
112 if (key == GLFW_KEY_F4) {
113 return (KEY_F4);
114 }
115 if (key == GLFW_KEY_F5) {
116 return (KEY_F5);
117 }
118 if (key == GLFW_KEY_F6) {
119 return (KEY_F6);
120 }
121 if (key == GLFW_KEY_F7) {
122 return (KEY_F7);
123 }
124 if (key == GLFW_KEY_F8) {
125 return (KEY_F8);
126 }
127 if (key == GLFW_KEY_F9) {
128 return (KEY_F9);
129 }
130 if (key == GLFW_KEY_F10) {
131 return (KEY_F10);
132 }
133 if (key == GLFW_KEY_F11) {
134 return (KEY_F11);
135 }
136 if (key == GLFW_KEY_F12) {
137 return (KEY_F12);
138 }
139 return (0);
140}
141
142void GPUDisplayFrontendGlfw::GetKey(int32_t key, int32_t scancode, int32_t mods, int32_t& keyOut, int32_t& keyPressOut)
143{
144 int32_t specialKey = GetKey(key);
145 const char* str = glfwGetKeyName(key, scancode);
146 char localeKey = str ? str[0] : 0;
147 if ((mods & GLFW_MOD_SHIFT) && localeKey >= 'a' && localeKey <= 'z') {
148 localeKey += 'A' - 'a';
149 }
150 // GPUInfo("Key: key %d (%c) scancode %d -> %d (%c) special %d (%c)", key, (char)key, scancode, (int32_t)localeKey, localeKey, specialKey, (char)specialKey);
151
152 if (specialKey) {
153 keyOut = keyPressOut = specialKey;
154 } else {
155 keyOut = keyPressOut = (uint8_t)localeKey;
156 if (keyPressOut >= 'a' && keyPressOut <= 'z') {
157 keyPressOut += 'A' - 'a';
158 }
159 }
160}
161
162void GPUDisplayFrontendGlfw::error_callback(int32_t error, const char* description) { fprintf(stderr, "Error: %s\n", description); }
163
164void GPUDisplayFrontendGlfw::key_callback(GLFWwindow* window, int32_t key, int32_t scancode, int32_t action, int32_t mods)
165{
166 int32_t handleKey = 0, keyPress = 0;
167 GetKey(key, scancode, mods, handleKey, keyPress);
168 if (handleKey < 32) {
169 if (action == GLFW_PRESS) {
170 me->mKeys[keyPress] = true;
171 me->mKeysShift[keyPress] = mods & GLFW_MOD_SHIFT;
172 me->HandleKey(handleKey);
173 } else if (action == GLFW_RELEASE) {
174 me->mKeys[keyPress] = false;
175 me->mKeysShift[keyPress] = false;
176 }
177 } else if (handleKey < 256) {
178 if (action == GLFW_PRESS) {
179 me->mLastKeyDown = handleKey;
180 } else if (action == GLFW_RELEASE) {
181 keyPress = (uint8_t)me->mKeyDownMap[handleKey];
182 me->mKeys[keyPress] = false;
183 me->mKeysShift[keyPress] = false;
184 }
185 }
186}
187
188void GPUDisplayFrontendGlfw::char_callback(GLFWwindow* window, uint32_t codepoint)
189{
190 // GPUInfo("Key (char callback): %d %c - key: %d", codepoint, (char)codepoint, (int32_t)me->mLastKeyDown);
191 if (codepoint < 256) {
192 uint8_t keyPress = codepoint;
193 if (keyPress >= 'a' && keyPress <= 'z') {
194 keyPress += 'A' - 'a';
195 }
196 me->mKeyDownMap[me->mLastKeyDown] = keyPress;
197 me->mKeys[keyPress] = true;
198 me->mKeysShift[keyPress] = me->mKeys[KEY_SHIFT];
199 me->HandleKey(codepoint);
200 }
201}
202
203void GPUDisplayFrontendGlfw::mouseButton_callback(GLFWwindow* window, int32_t button, int32_t action, int32_t mods)
204{
205 if (action == GLFW_PRESS) {
206 if (button == 0) {
207 me->mMouseDn = true;
208 } else if (button == 1) {
209 me->mMouseDnR = true;
210 }
211 me->mMouseDnX = me->mMouseMvX;
212 me->mMouseDnY = me->mMouseMvY;
213 } else if (action == GLFW_RELEASE) {
214 if (button == 0) {
215 me->mMouseDn = false;
216 } else if (button == 1) {
217 me->mMouseDnR = false;
218 }
219 }
220}
221
222void GPUDisplayFrontendGlfw::scroll_callback(GLFWwindow* window, double x, double y) { me->mMouseWheel += y * 100; }
223
224void GPUDisplayFrontendGlfw::cursorPos_callback(GLFWwindow* window, double x, double y)
225{
226 me->mMouseMvX = x;
227 me->mMouseMvY = y;
228}
229
230void GPUDisplayFrontendGlfw::resize_callback(GLFWwindow* window, int32_t width, int32_t height) { me->ResizeScene(width, height); }
231
232#ifndef GPUCA_STANDALONE
233void GPUDisplayFrontendGlfw::DisplayLoop()
234{
235 ImGui::SetNextWindowPos(ImVec2(0, 0));
236 ImGui::SetNextWindowSize(ImVec2(me->mDisplayWidth, me->mDisplayHeight));
237 ImGui::SetNextWindowBgAlpha(0.f);
238 ImGui::Begin("Console", nullptr, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove);
239 me->DrawGLScene();
240 ImGui::End();
241}
242#endif
243
244int32_t GPUDisplayFrontendGlfw::FrontendMain()
245{
246 me = this;
247
248 if (!glfwInit()) {
249 fprintf(stderr, "Error initializing glfw\n");
250 return (-1);
251 }
252 glfwSetErrorCallback(error_callback);
253
254 glfwWindowHint(GLFW_MAXIMIZED, 1);
255 if (backend()->backendType() == GPUDisplayBackend::TYPE_VULKAN) {
256 glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
257 }
258 if (backend()->backendType() == GPUDisplayBackend::TYPE_OPENGL) {
259 glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, GL_MIN_VERSION_MAJOR);
260 glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, GL_MIN_VERSION_MINOR);
261 glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, 0);
262 glfwWindowHint(GLFW_OPENGL_PROFILE, mBackend->CoreProfile() ? GLFW_OPENGL_CORE_PROFILE : GLFW_OPENGL_COMPAT_PROFILE);
263 }
264 mWindow = glfwCreateWindow(INIT_WIDTH, INIT_HEIGHT, DISPLAY_WINDOW_NAME, nullptr, nullptr);
265 if (!mWindow) {
266 fprintf(stderr, "Error creating glfw window\n");
267 glfwTerminate();
268 return (-1);
269 }
270 if (backend()->backendType() == GPUDisplayBackend::TYPE_OPENGL) {
271 glfwMakeContextCurrent(mWindow);
272 }
273
274 glfwSetKeyCallback(mWindow, key_callback);
275 glfwSetCharCallback(mWindow, char_callback);
276 glfwSetMouseButtonCallback(mWindow, mouseButton_callback);
277 glfwSetScrollCallback(mWindow, scroll_callback);
278 glfwSetCursorPosCallback(mWindow, cursorPos_callback);
279 glfwSetWindowSizeCallback(mWindow, resize_callback);
280 if (backend()->backendType() == GPUDisplayBackend::TYPE_OPENGL) {
281 glfwSwapInterval(1);
282 }
283
284 pthread_mutex_lock(&mSemLockExit);
285 mGlfwRunning = true;
286 pthread_mutex_unlock(&mSemLockExit);
287
288 if (mBackend->ExtInit()) {
289 fprintf(stderr, "Error initializing GL extension wrapper\n");
290 return (-1);
291 }
292
293 if (InitDisplay()) {
294 fprintf(stderr, "Error in GLFW display initialization\n");
295 return (1);
296 }
297
298 while (!glfwWindowShouldClose(mWindow)) {
300 if (DrawGLScene()) {
301 fprintf(stderr, "Error drawing GL scene\n");
302 return (1);
303 }
304 if (backend()->backendType() == GPUDisplayBackend::TYPE_OPENGL) {
305 glfwSwapBuffers(mWindow);
306 }
307 glfwPollEvents();
308 }
309
310 ExitDisplay();
311 mDisplayControl = 2;
312 pthread_mutex_lock(&mSemLockExit);
313 glfwDestroyWindow(mWindow);
314 glfwTerminate();
315 mGlfwRunning = false;
316 pthread_mutex_unlock(&mSemLockExit);
317
318 return 0;
319}
320
322{
323 pthread_mutex_lock(&mSemLockExit);
324 if (mGlfwRunning) {
325 glfwSetWindowShouldClose(mWindow, true);
326 }
327 pthread_mutex_unlock(&mSemLockExit);
328 while (mGlfwRunning) {
329 usleep(10000);
330 }
331}
332
333void GPUDisplayFrontendGlfw::OpenGLPrint(const char* s, float x, float y, float r, float g, float b, float a, bool fromBotton)
334{
335}
336
338{
339 GPUInfo("Setting Full Screen %d", (int32_t)set);
340 if (set) {
341 glfwGetWindowPos(mWindow, &mWindowX, &mWindowY);
342 glfwGetWindowSize(mWindow, &mWindowWidth, &mWindowHeight);
343 GLFWmonitor* primary = glfwGetPrimaryMonitor();
344 const GLFWvidmode* mode = glfwGetVideoMode(primary);
345 glfwSetWindowMonitor(mWindow, primary, 0, 0, mode->width, mode->height, mode->refreshRate);
346 } else {
347 glfwSetWindowMonitor(mWindow, nullptr, mWindowX, mWindowY, mWindowWidth, mWindowHeight, GLFW_DONT_CARE);
348 }
349}
350
352{
353 if (set) {
354 glfwMaximizeWindow(mWindow);
355 } else {
356 glfwRestoreWindow(mWindow);
357 }
358}
359
360void GPUDisplayFrontendGlfw::SetVSync(bool enable) { glfwSwapInterval(enable); }
361
363{
364#ifdef GPUCA_STANDALONE
365 return true;
366#else
367 return false;
368#endif
369}
370
372{
373 glfwGetFramebufferSize(mWindow, &width, &height);
374}
375
376int32_t GPUDisplayFrontendGlfw::getVulkanSurface(void* instance, void* surface)
377{
378#ifdef GPUCA_BUILD_EVENT_DISPLAY_VULKAN
379 return glfwCreateWindowSurface(*(VkInstance*)instance, mWindow, nullptr, (VkSurfaceKHR*)surface) != VK_SUCCESS;
380#else
381 return 1;
382#endif
383}
384
386{
387 uint32_t glfwExtensionCount = 0;
388#ifdef GPUCA_BUILD_EVENT_DISPLAY_VULKAN
389 p = glfwGetRequiredInstanceExtensions(&glfwExtensionCount);
390#endif
391 return glfwExtensionCount;
392}
header::DataDescription description
StringRef key
void getSize(int32_t &width, int32_t &height) override
void OpenGLPrint(const char *s, float x, float y, float r, float g, float b, float a, bool fromBotton=true) override
uint32_t getReqVulkanExtensions(const char **&p) override
int32_t getVulkanSurface(void *instance, void *surface) override
static constexpr int32_t KEY_F9
static constexpr int32_t KEY_F2
static constexpr int32_t KEY_ALT
static constexpr int32_t KEY_F12
static constexpr int32_t KEY_F7
static constexpr int32_t KEY_END
static constexpr int32_t KEY_PAGEDOWN
static constexpr int32_t KEY_RALT
static constexpr int32_t KEY_F10
static constexpr int32_t KEY_F4
static constexpr int32_t KEY_LEFT
static constexpr int32_t KEY_ENTER
static constexpr int32_t KEY_F6
static constexpr int32_t KEY_CTRL
static constexpr int32_t KEY_F1
static constexpr const char * DISPLAY_WINDOW_NAME
static constexpr int32_t INIT_WIDTH
static constexpr int32_t GL_MIN_VERSION_MAJOR
static constexpr int32_t KEY_SHIFT
static constexpr int32_t KEY_F3
static constexpr int32_t KEY_INSERT
static constexpr int32_t KEY_F11
static constexpr int32_t KEY_SPACE
static constexpr int32_t KEY_F5
static constexpr int32_t KEY_PAGEUP
static constexpr int32_t KEY_HOME
static constexpr int32_t GL_MIN_VERSION_MINOR
int32_t InitDisplay(bool initFailure=false)
static constexpr int32_t KEY_UP
static constexpr int32_t KEY_DOWN
static constexpr int32_t KEY_F8
static constexpr int32_t INIT_HEIGHT
static constexpr int32_t KEY_RIGHT
static constexpr int32_t KEY_RCTRL
static constexpr int32_t KEY_ESCAPE
GLint GLenum GLint x
Definition glcorearb.h:403
GLenum mode
Definition glcorearb.h:266
GLint GLsizei GLsizei height
Definition glcorearb.h:270
GLint GLsizei width
Definition glcorearb.h:270
GLboolean GLboolean GLboolean b
Definition glcorearb.h:1233
GLint y
Definition glcorearb.h:270
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
uint8_t itsSharedClusterMap uint8_t
constexpr value_T me
Definition TrackUtils.h:128
const std::string str