1 | #include <iostream> |
2 | #include <thread> |
3 |
|
4 | #include <SDL2/SDL.h> |
5 | #include "GL/gl3w.h" |
6 | #include <GL/gl.h> |
7 |
|
8 | #include "ZydecoCommon.hpp" |
9 | #include "CommonSDL2.hpp" |
10 | #include "EventHandlerSDL2.hpp" |
11 | #include "WindowSDL2.hpp" |
12 | #include "TimerSDL2.hpp" |
13 | #include "Renderer.hpp" |
14 | #include "Engine.hpp" |
15 |
|
16 |
|
17 | static Logger LOGGER("main"); |
18 |
|
19 | static const char *ZYDECO_TERMOUT[] = { |
20 | "Zydeco v0.1.0 Copyright (c) Joshua Stockin 2023", |
21 | "<https://joshstock.in> <josh@joshstock.in>", |
22 | }; |
23 |
|
24 |
|
25 | void on_terminate(void) |
26 | { |
27 | ZydecoFault("PROGRAM TERMINATED UNEXPECTEDLY."); |
28 | } |
29 |
|
30 | int main(int argc, char *argv[]) |
31 | { |
32 | // Print boilerplate copyright output |
33 | for (const char *line : ZYDECO_TERMOUT) |
34 | { |
35 | std::cout << line << std::endl; |
36 | } |
37 |
|
38 | // Runtime environment setup |
39 | std::set_terminate(static_cast<std::terminate_handler>(on_terminate)); |
40 |
|
41 | // Initialize logging |
42 | Logger::InitializeLogging(Logger::TRACE, &std::cout); |
43 | LOGGER.Log(Logger::INFO, "main(): Logging initialized"); |
44 |
|
45 | // Initialize SDL environment |
46 | LOGGER.Log(Logger::INFO, "main(): Initializing SDL..."); |
47 | SDL_CallErrorReturningFunction(SDL_Init, SDL_INIT_VIDEO | SDL_INIT_EVENTS); |
48 | LOGGER.Log(Logger::INFO, "main(): SDL initialized"); |
49 |
|
50 | // Create subsystems |
51 | LOGGER.Log(Logger::INFO, "main(): Creating subsystems..."); |
52 | EventHandlerSDL2 sdl_event_handler {}; |
53 | WindowSDL2 sdl_window {"Zydeco", SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE}; |
54 | TimerSDL2 sdl_core_timer {}; |
55 |
|
56 | // Load OpenGL |
57 | LOGGER.Log(Logger::INFO, "main(): Loading OpenGL with GL3W..."); |
58 |
|
59 | sdl_window.MakeContextCurrent(); |
60 | int gl3wRes = gl3wInit(); |
61 | if (gl3wRes != 0) |
62 | { |
63 | ZydecoFault("gl3wInit failed ({})", gl3wRes); |
64 | } |
65 |
|
66 | if (!gl3wIsSupported(GL_VERSION_MAJOR, GL_VERSION_MINOR)) |
67 | { |
68 | ZydecoFault("OpenGL/GL3W {}.{} not supported", GL_VERSION_MAJOR, GL_VERSION_MINOR); |
69 | } |
70 |
|
71 | LOGGER.Log(Logger::DEBUG, "main(): OpenGL {}, GLSL {}", glGetString(GL_VERSION), glGetString(GL_SHADING_LANGUAGE_VERSION)); |
72 | LOGGER.Log(Logger::DEBUG, "main(): Renderer: {}", glGetString(GL_RENDERER)); |
73 | LOGGER.Log(Logger::INFO, "main(): OpenGL loaded with GL3W"); |
74 |
|
75 | TimerSDL2 sdl_renderer_timer {}; |
76 | Renderer gl_renderer {sdl_event_handler, sdl_window, sdl_renderer_timer}; |
77 |
|
78 | LOGGER.Log(Logger::INFO, "main(): Subsystems created"); |
79 |
|
80 | // Constructor implictly creates a GL context and makes it current. Context must be current to load GL and ascertain |
81 | // capabilities. GL doesn't thread well, so we can't have that context be current here after initialization. |
82 | sdl_window.MakeNullCurrent(); |
83 |
|
84 | // Create engine |
85 | LOGGER.Log(Logger::INFO, "main(): Creating engine..."); |
86 | Engine engine {sdl_event_handler, sdl_core_timer, gl_renderer}; |
87 | LOGGER.Log(Logger::INFO, "main(): Engine created"); |
88 |
|
89 | // Enter loop |
90 | LOGGER.Log(Logger::INFO, "main(): Entering engine loop"); |
91 | engine.Execute(); |
92 |
|
93 | // Loop returned |
94 | LOGGER.Log(Logger::INFO, "main(): Quitting SDL"); |
95 | SDL_Quit(); |
96 |
|
97 | // Exiting program |
98 | LOGGER.Log(Logger::INFO, "main(): Exiting"); |
99 | return 0; |
100 | } |
101 |
|