Worldstone
 All Classes Files Functions Variables Enumerations Enumerator Macros Pages
BaseApp.cpp
1 #include "BaseApp.h"
2 #include <Platform.h>
3 
5 // Caused by winnt.h because SDL2 changes packing, see https://bugzilla.libsdl.org/show_bug.cgi?id=4159
6 WS_PRAGMA_DIAGNOSTIC_IGNORED_MSC(4121) // warning C4121:
7  // 'JOBOBJECT_IO_RATE_CONTROL_INFORMATION_NATIVE_V2':
8  // alignment of a member was sensitive to packing
9 #include <SDL.h>
10 #include <SDL_syswm.h>
11 #include <bgfx/platform.h>
13 
14 // List of stupid defines from Xlib.h, included by SDL_syswm
15 #undef False
16 #undef True
17 #undef None
18 #undef Status
19 #include <thread>
20 
21 int BaseApp::init()
22 {
23  stopRunning = false;
24 
25  // Setup SDL
26  if (SDL_Init(SDL_INIT_VIDEO) != 0) {
27  SDL_LogError(SDL_LOG_CATEGORY_ERROR, "Error initializing SDL: %s\n", SDL_GetError());
28  return -1;
29  }
30 
31  // Create the main window
32  mainWindow = SDL_CreateWindow(
33  // clang-format off
34  "Main window",
35  SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
36  windowWidth, windowHeight,
37  SDL_WINDOW_SHOWN
38  // clang-format on
39  );
40  if (!mainWindow) {
41  SDL_LogError(SDL_LOG_CATEGORY_ERROR, "Error creating window: %s\n", SDL_GetError());
42  return -1;
43  }
44 
45  // Initialize the renderer
46  SDL_SysWMinfo wmi;
47  SDL_VERSION(&wmi.version);
48  if (!SDL_GetWindowWMInfo(mainWindow, &wmi)) {
49  SDL_LogError(SDL_LOG_CATEGORY_ERROR, "Couldn't get window information: %s", SDL_GetError());
50  return -1;
51  }
52 
53  bgfx::PlatformData pd;
54  switch (wmi.subsystem)
55  {
56 #if defined(SDL_VIDEO_DRIVER_WINDOWS)
57  case SDL_SYSWM_WINDOWS:
58  pd.ndt = nullptr;
59  pd.nwh = wmi.info.win.window;
60  break;
61 #endif
62 #if defined(SDL_VIDEO_DRIVER_X11)
63  case SDL_SYSWM_X11:
64  pd.ndt = wmi.info.x11.display;
65  pd.nwh = (void*)(uintptr_t)wmi.info.x11.window;
66  break;
67 #endif
68 #if defined(SDL_VIDEO_DRIVER_COCOA)
69  case SDL_SYSWM_COCOA:
70  pd.ndt = nullptr;
71  pd.nwh = wmi.info.cocoa.window;
72  break;
73 #endif
74 #if defined(SDL_VIDEO_DRIVER_VIVANTE)
75  case SDL_SYSWM_VIVANTE:
76  pd.ndt = wmi.info.vivante.display;
77  pd.nwh = wmi.info.vivante.window;
78  break;
79 #endif
80  default: SDL_LogError(SDL_LOG_CATEGORY_ERROR, "Unsupported window system");
81  }
82 
83  for (int sysCursorIndex = 0; sysCursorIndex < SDL_NUM_SYSTEM_CURSORS; sysCursorIndex++)
84  {
85  systemCursors[sysCursorIndex] = SDL_CreateSystemCursor(SDL_SystemCursor(sysCursorIndex));
86  }
87 
88  // Let bgfx create the rendering context and back buffers
89  pd.context = nullptr;
90  pd.backBuffer = nullptr;
91  pd.backBufferDS = nullptr;
92  bgfx::setPlatformData(pd);
93 
94  // Call this before init to tell bgfx this is the render thread
95  bgfx::renderFrame();
96  return 0;
97 }
98 
99 bool BaseApp::initAppThread()
100 {
101  if (!bgfx::init()) return false;
102  bgfx::reset(uint32_t(windowWidth), uint32_t(windowHeight), 0 | BGFX_RESET_VSYNC);
103  bgfx::setDebug(BGFX_DEBUG_TEXT);
104 
105  // Set view 0 clear state.
106  bgfx::setViewClear(0, BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH, 0x303030ff, 1.0f, 0);
107 
108  // Clear the window
109  bgfx::frame();
110  return true;
111 }
112 
113 void BaseApp::shutdownAppThread() { bgfx::shutdown(); }
114 
115 void BaseApp::shutdown()
116 {
117  for (auto& systemCursorPtr : systemCursors)
118  {
119  SDL_FreeCursor(systemCursorPtr);
120  systemCursorPtr = nullptr;
121  }
122 
123  SDL_DestroyWindow(mainWindow);
124  mainWindow = nullptr;
125 
126  SDL_Quit();
127 }
128 
129 void BaseApp::executeLoopOnce()
130 {
131  {
132  InputsManager::ScopedTransfer transfer{inputsManager};
133 
134  SDL_Event event;
135  while (SDL_PollEvent(&event))
136  {
137  transfer.PushEvent(event);
138  }
139 
140  {
141  Inputs::MouseState mouseState;
142  mouseState.buttonsMask = SDL_GetMouseState(&mouseState.x, &mouseState.y);
143  if (!(SDL_GetWindowFlags(mainWindow) & SDL_WINDOW_MOUSE_FOCUS)) {
144  mouseState.x = mouseState.y = std::numeric_limits<int>::lowest();
145  }
146  transfer.PushMouseState(mouseState);
147  }
148 
149  // Done transferring events
150  }
151 
152  bgfx::RenderFrame::Enum ret = bgfx::renderFrame();
153  if (ret == bgfx::RenderFrame::Exiting) requireExit();
154 }
155 
156 void BaseApp::executeAppLoopOnce()
157 {
158  static bool debugDisplay = false;
159  const Inputs inputs = inputsManager.receiveAndProcessEvents();
160  for (const SDL_Event& event : inputs.events)
161  {
162  // Default handling of some events
163  switch (event.type)
164  {
165  case SDL_QUIT: requireExit(); break;
166  case SDL_KEYUP:
167  if (event.key.keysym.sym == SDLK_F1) {
168  debugDisplay = !debugDisplay;
169  }
170  break;
171  default: break;
172  }
173  }
174  bgfx::setDebug(BGFX_DEBUG_TEXT | (debugDisplay ? BGFX_DEBUG_STATS : 0));
175  // Set view 0 default viewport.
176  bgfx::setViewRect(0, 0, 0, uint16_t(windowWidth), uint16_t(windowHeight));
177 
178  // This dummy draw call is here to make sure that view 0 is cleared
179  // if no other draw calls are submitted to view 0.
180  bgfx::touch(0);
181 
182  // Advance to next frame. Rendering thread will be kicked to
183  // process submitted rendering primitives.
184  bgfx::frame();
185 }
186 
187 void BaseApp::run()
188 {
189  std::thread appThread{&BaseApp::runAppThread, this};
190  while (!stopRunning)
191  {
192  executeLoopOnce();
193  }
194  // Wait for destruction of the context
195  while (bgfx::RenderFrame::NoContext != bgfx::renderFrame())
196  {
197  };
198  appThread.join();
199 }
200 
201 void BaseApp::runAppThread()
202 {
203  if (!initAppThread()) {
204  requireExit();
205  shutdownAppThread();
206  return;
207  }
208  while (!stopRunning)
209  {
210  executeAppLoopOnce();
211  }
212  shutdownAppThread();
213  // End of the app thread
214 }
Definition: Inputs.h:8
#define WS_PRAGMA_DIAGNOSTIC_POP()
Restores the previous state of the compiler warnings.
Definition: Platform.h:94
#define WS_PRAGMA_DIAGNOSTIC_IGNORED_MSC(_x)
Silence MSC-specific warnings.
Definition: Platform.h:98
#define WS_PRAGMA_DIAGNOSTIC_PUSH()
Saves the current state of the compiler warnings.
Definition: Platform.h:93
Platform specific tools and macros.