1#include <SDL2/SDL.h>
2
3#include "util.h"
4#include "platform/platform.h"
5
6static void platform_key_set(MGContext* ctx, MGKey key, i32 down);
7
8/* set the state of a logical key */
9static void platform_key_set(MGContext* ctx, MGKey key, i32 down)
10{
11 int i;
12
13 if (key == MGK_UNKNOWN)
14 return;
15
16 for (i = 0; i < MG_KEYS_DOWN_MAX; i++) {
17 if (ctx->keys[i] == key) {
18 if (!down)
19 ctx->keys[i] = MGK_UNKNOWN;
20 return;
21 }
22 }
23
24 if (!down)
25 return;
26
27 for (i = 0; i < MG_KEYS_DOWN_MAX; i++) {
28 if (ctx->keys[i] == MGK_UNKNOWN) {
29 ctx->keys[i] = key;
30 return;
31 }
32 }
33}
34
35void platform_get_drawable_size(MGContext* ctx, i32* width, i32* height)
36{
37#ifdef MG_RENDERER_SMALL3DLIB
38 SDL_GetWindowSize(ctx->win, width, height);
39#else
40 SDL_GL_GetDrawableSize(ctx->win, width, height);
41#endif
42}
43
44void platform_get_mouse_state(i32* x, i32* y)
45{
46 SDL_GetRelativeMouseState(x, y);
47}
48
49u64 platform_get_ticks(void)
50{
51 return SDL_GetTicks64();
52}
53
54void platform_init(MGContext* ctx)
55{
56 int i;
57
58 for (i = 0; i < MG_KEYS_DOWN_MAX; i++)
59 ctx->keys[i] = MGK_UNKNOWN;
60
61 if (SDL_Init(SDL_INIT_VIDEO) != 0)
62 mg_die(MG_EC_SDL_INIT, "SDL_Init failed: %s", SDL_GetError());
63
64#ifdef MG_RENDERER_SOKOL
65 /* TODO: OpenGL specifics */
66 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
67 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
68 SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
69 SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
70 SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
71#endif
72}
73
74i32 platform_poll(MGContext* ctx)
75{
76 SDL_Event ev;
77
78 while (SDL_PollEvent(&ev)) {
79 switch (ev.type) {
80 case SDL_QUIT:
81 return 0;
82
83 case SDL_KEYDOWN:
84 case SDL_KEYUP:
85 platform_key_set(ctx, ev.key.keysym.sym, ev.type == SDL_KEYDOWN);
86 break;
87
88 case SDL_WINDOWEVENT:
89 if (ev.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) {
90 ctx->width = ev.window.data1;
91 ctx->height = ev.window.data2;
92 }
93 }
94 }
95
96 return 1;
97}
98
99i32 platform_key_down(MGContext* ctx, MGKey key)
100{
101 int i;
102
103 if (!ctx || key == MGK_UNKNOWN)
104 return 0;
105
106 for (i = 0; i < MG_KEYS_DOWN_MAX; i++) {
107 if (ctx->keys[i] == key)
108 return 1;
109 }
110
111 return 0;
112}
113
114void platform_present(MGContext* ctx)
115{
116#ifdef MG_RENDERER_SMALL3DLIB
117 SDL_RenderPresent(ctx->vbe.renderer);
118#else
119 SDL_GL_SwapWindow(ctx->win);
120#endif
121}
122
123void platform_set_mouse_relative(i8 enabled)
124{
125 SDL_SetRelativeMouseMode(enabled);
126}
127
128void platform_shutdown(MGContext* ctx)
129{
130 if (!ctx)
131 return;
132
133#ifdef MG_RENDERER_SMALL3DLIB
134 if (ctx->vbe.renderer) {
135 SDL_DestroyRenderer(ctx->vbe.renderer);
136 ctx->vbe.renderer = NULL;
137 }
138#endif
139
140#ifdef MG_RENDERER_SOKOL
141 if (ctx->vbe.gl) {
142 SDL_GL_DeleteContext(ctx->vbe.gl);
143 ctx->vbe.gl = NULL;
144 }
145#endif
146
147 if (ctx->win) {
148 SDL_DestroyWindow(ctx->win);
149 ctx->win = NULL;
150 }
151
152 SDL_Quit();
153}
154
155void platform_window_create(MGContext* ctx)
156{
157 u32 flags = SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI;
158#ifdef MG_RENDERER_SOKOL
159 flags |= SDL_WINDOW_OPENGL;
160#endif
161
162 ctx->win = SDL_CreateWindow(ctx->title, ctx->x, ctx->y, ctx->width, ctx->height, flags);
163
164 if (!ctx->win)
165 mg_die(MG_EC_SDL_CREATE_WIN, "Failed to create window: %s", SDL_GetError());
166
167#ifdef MG_RENDERER_SMALL3DLIB
168 ctx->vbe.renderer = SDL_CreateRenderer(ctx->win, -1, SDL_RENDERER_ACCELERATED);
169 if (!ctx->vbe.renderer)
170 ctx->vbe.renderer = SDL_CreateRenderer(ctx->win, -1, SDL_RENDERER_SOFTWARE);
171 if (!ctx->vbe.renderer)
172 mg_die(MG_EC_SDL_CREATE_RENDERER, "Failed to create SDL renderer: %s", SDL_GetError());
173#endif
174
175#ifdef MG_RENDERER_SOKOL
176 ctx->vbe.gl = SDL_GL_CreateContext(ctx->win);
177 if (!ctx->vbe.gl)
178 mg_die(MG_EC_GL_CTX_CREATE, "Failed to initialise GL Context");
179
180 if (SDL_GL_MakeCurrent(ctx->win, ctx->vbe.gl) != 0)
181 mg_die(MG_EC_GL_CTX_ACTIVATE, "Failed to activate GL Context: %s", SDL_GetError());
182
183 SDL_GL_SetSwapInterval(1);
184#endif
185}
186
187void platform_wait(u32 ms)
188{
189 SDL_Delay(ms);
190}