3 * (C) 2018 by Andreas Eversberg <jolly@eversberg.eu>
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
27 #define GL3_PROTOTYPES 1
30 static int sdl_initialized = 0;
31 static int audio_initialized = 0;
32 static SDL_Window *gl_window = NULL;
33 static SDL_GLContext gl_context = NULL;
34 static void (*keyboard_sdl)(int down, SDL_Keycode sym) = NULL;
35 static void (*audio_sdl)(float *data, int len) = NULL;
37 static void audio_cb(void __attribute__((unused)) *userdata, Uint8 *stream, int len)
39 float audio_data[len / sizeof(float)];
41 SDL_memset(stream, 0, len);
42 audio_sdl(audio_data, len / sizeof(float) / 2);
43 SDL_MixAudio(stream, (Uint8 *)audio_data, len, SDL_MIX_MAXVOLUME);
46 int init_sdl(const char *progname, int width, int height, int sound_samplerate, int sound_chunk, void (*keyboard)(int down, SDL_Keycode sym), void (*audio)(float *data, int len), int multisampling)
50 keyboard_sdl = keyboard;
53 /* init SDL library */
54 rc = SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO);
56 print_error("Failed to init SDL\n");
62 SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
63 SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
64 SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
65 SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
66 SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
67 SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
68 SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, multisampling);
72 gl_window = SDL_CreateWindow(progname, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);
74 print_error("Failed to open SDL window: %s\n", SDL_GetError());
79 /* create GL context */
80 gl_context = SDL_GL_CreateContext(gl_window);
82 print_error("Failed to create SDL's OpenGL context: %s\n", SDL_GetError());
87 rc = SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
89 print_error("Failed to set SDL's OpenGL context profile\n");
93 rc = SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
95 print_error("Failed to set SDL's OpenGL major version\n");
98 rc = SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
100 print_error("Failed to set SDL's OpenGL minor version\n");
104 rc = SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
106 print_error("Failed to set SDL's OpenGL doublebuffer\n");
110 rc = SDL_GL_SetSwapInterval(1);
112 print_error("Failed to set SDL's OpenGL swap interval to VBLANK\n");
117 glewExperimental = GL_TRUE;
118 if (glewInit() != GLEW_OK) {
119 print_error("Failed to init GLEW\n");
125 glDisable(GL_DEPTH_TEST);
126 glDisable(GL_CULL_FACE);
128 glEnable(GL_MULTISAMPLE);
131 SDL_AudioSpec want, have;
132 SDL_memset(&want, 0, sizeof(want)); /* or SDL_zero(want) */
133 want.freq = sound_samplerate;
134 want.format = AUDIO_F32; /* we always use float in this project */
136 want.samples = sound_chunk; /* must be a power of two */
137 want.callback = audio_cb;
138 rc = SDL_OpenAudio(&want, &have);
140 print_error("Failed to open audio\n");
142 } else if (have.format != want.format) {
143 print_error("Failed to open audio with desired audio format\n");
147 } else if (have.freq != want.freq) {
148 print_error("Failed to open audio with desired sample rate\n");
152 } else if (have.channels != want.channels) {
153 print_error("Failed to open audio with desired channels (got %d)\n", have.channels);
159 audio_initialized = 1;
169 static int key_ctrl = 0, fullscreen = 0;
176 while (SDL_PollEvent(&event)) {
177 if (event.type == SDL_QUIT)
179 if (event.type == SDL_WINDOWEVENT) {
180 if (event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED)
181 resize_opengl(event.window.data1, event.window.data2);
183 if (event.type == SDL_KEYDOWN) {
184 switch (event.key.keysym.sym) {
189 SDL_SetWindowFullscreen(gl_window, 0);
190 SDL_ShowCursor(SDL_ENABLE);
192 SDL_SetWindowFullscreen(gl_window, SDL_WINDOW_FULLSCREEN_DESKTOP);
193 SDL_ShowCursor(SDL_DISABLE);
203 keyboard_sdl(1, event.key.keysym.sym);
205 if (event.type == SDL_KEYUP) {
206 switch (event.key.keysym.sym) {
212 keyboard_sdl(0, event.key.keysym.sym);
221 SDL_GL_SwapWindow(gl_window);
228 SDL_DestroyWindow(gl_window);
232 /* clear OpenGL context */
234 SDL_GL_DeleteContext(gl_context);
238 /* exit SDL library */
239 if (audio_initialized) {
242 audio_initialized = 0;
244 if (sdl_initialized) {