Cross-Platform OpenGL Windowing Library
Revision | ae2115beca5eef14279ba02fa7c5c4842a825332 (tree) |
---|---|
Time | 2019-04-13 15:10:10 |
Author | AlaskanEmily <emily@alas...> |
Commiter | AlaskanEmily |
Add SDL2 backend
@@ -17,7 +17,13 @@ glow_x11.o: glow_x11.c glow.h | ||
17 | 17 | $(CC) $(CFLAGS) $(X11INCLUDE) -c glow_x11.c -o glow_x11.o |
18 | 18 | |
19 | 19 | glow_x11.os: glow_x11.c glow.h |
20 | - $(CC) $(CFLAGS)$(FPICFLAGS) $(X11INCLUDE) -c glow_x11.c -o glow_x11.os | |
20 | + $(CC) $(CFLAGS) $(FPICFLAGS) $(X11INCLUDE) -c glow_x11.c -o glow_x11.os | |
21 | + | |
22 | +glow_sdl2.o: glow_sdl2.c glow.h | |
23 | + $(CC) $(CFLAGS) -c glow_sdl2.c -o glow_sdl2.o | |
24 | + | |
25 | +glow_sdl2.os: glow_sdl2.c glow.h | |
26 | + $(CC) $(CFLAGS) $(FPICFLAGS) -c glow_sdl2.c -o glow_sdl2.os | |
21 | 27 | |
22 | 28 | libglow.so: glow_$(GLOWTARGET).os |
23 | 29 | $(LINKER) $(SHAREDFLAGS) glow_$(GLOWTARGET).os -o libglow.so |
@@ -0,0 +1,332 @@ | ||
1 | +/* Copyright (C) 2019 Alaskan Emily, Transnat Games | |
2 | + * | |
3 | + * This Source Code Form is subject to the terms of the Mozilla Public | |
4 | + * License, v. 2.0. If a copy of the MPL was not distributed with this | |
5 | + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | |
6 | + | |
7 | +#include "glow.h" | |
8 | +#include "SDL.h" | |
9 | +#include "SDL_video.h" | |
10 | +#include "SDL_syswm.h" | |
11 | + | |
12 | +/******************************************************************************/ | |
13 | + | |
14 | +struct Glow_Context{ | |
15 | + SDL_Window *win; | |
16 | + SDL_GLContext ctx; | |
17 | +}; | |
18 | + | |
19 | +/******************************************************************************/ | |
20 | + | |
21 | +struct Glow_Window{ | |
22 | + SDL_Window *win; | |
23 | + struct Glow_Context ctx; | |
24 | +}; | |
25 | + | |
26 | +/******************************************************************************/ | |
27 | + | |
28 | +void Glow_ViewportSize(unsigned w, unsigned h, | |
29 | + unsigned *out_w, unsigned *out_h){ | |
30 | + out_w[0] = w; | |
31 | + out_h[0] = h; | |
32 | +} | |
33 | + | |
34 | +/******************************************************************************/ | |
35 | + | |
36 | +void *Glow_GetSystemWindow(struct Glow_Window *window){ | |
37 | + SDL_SysWMinfo info; | |
38 | + if(!SDL_GetWindowWMInfo(window->win, &info)) | |
39 | + return NULL; | |
40 | + switch(info.subsystem){ | |
41 | +#ifdef SDL_VIDEO_DRIVER_WINDOWS | |
42 | + case SDL_SYSWM_WINDOWS: | |
43 | + return (void*)info.info.win.window; | |
44 | +#endif | |
45 | + | |
46 | +#ifdef SDL_VIDEO_DRIVER_WINRT | |
47 | + case SDL_SYSWM_WINRT: | |
48 | + return info.info.winrt.window; | |
49 | +#endif | |
50 | + | |
51 | +#ifdef SDL_VIDEO_DRIVER_MIR | |
52 | + case SDL_SYSWM_MIR: | |
53 | + return info.info.mir.surface; | |
54 | +#endif | |
55 | + | |
56 | +#ifdef SDL_VIDEO_DRIVER_WAYLAND | |
57 | + case SDL_SYSWM_WAYLAND: | |
58 | + return info.info.wl.surface; | |
59 | +#endif | |
60 | + | |
61 | +#ifdef SDL_VIDEO_DRIVER_X11 | |
62 | + case SDL_SYSWM_X11: | |
63 | + return (void*)info.info.x11.window; | |
64 | +#endif | |
65 | + | |
66 | +#ifdef SDL_VIDEO_DRIVER_DIRECTFB | |
67 | + case SDL_SYSWM_DIRECTFB: | |
68 | + return info.info.dfb.window; | |
69 | +#endif | |
70 | + | |
71 | +#ifdef SDL_VIDEO_DRIVER_COCOA | |
72 | + case SDL_SYSWM_COCOA: | |
73 | + return info.info.cocoa.window; | |
74 | +#endif | |
75 | + | |
76 | +#ifdef SDL_VIDEO_DRIVER_UIKIT | |
77 | + case SDL_SYSWM_UIKIT: | |
78 | + return info.info.uikit.window; | |
79 | +#endif | |
80 | + case SDL_SYSWM_UNKNOWN: /* FALLTHROUGH */ | |
81 | + default: | |
82 | + return NULL; | |
83 | + } | |
84 | +} | |
85 | + | |
86 | +/******************************************************************************/ | |
87 | + | |
88 | +void *Glow_GetProcAddress(const char *name){ | |
89 | + return SDL_GL_GetProcAddress(name); | |
90 | +} | |
91 | + | |
92 | +/******************************************************************************/ | |
93 | + | |
94 | +unsigned Glow_WindowStructSize(void){ | |
95 | + return sizeof(struct Glow_Window); | |
96 | +} | |
97 | + | |
98 | +/******************************************************************************/ | |
99 | + | |
100 | +void Glow_CreateWindow(struct Glow_Window *out, | |
101 | + unsigned w, unsigned h, const char *title, int flags){ | |
102 | + | |
103 | + int sdl_flags = SDL_WINDOW_OPENGL | SDL_WINDOW_HIDDEN; | |
104 | + | |
105 | +#ifdef SDL_WINDOW_ALLOW_HIGHDPI | |
106 | + sdl_flags |= SDL_WINDOW_ALLOW_HIGHDPI; | |
107 | +#endif | |
108 | + | |
109 | + if((flags & GLOW_RESIZABLE) != 0) | |
110 | + sdl_flags |= SDL_WINDOW_RESIZABLE; | |
111 | + if((flags & GLOW_UNDECORATED) != 0) | |
112 | + sdl_flags |= SDL_WINDOW_BORDERLESS; | |
113 | + | |
114 | + /* This is used every time a window is created. SDL2 ref-counts this, so | |
115 | + * it is OK to use this on window construction and a matched quit occurs on | |
116 | + * window destruction. | |
117 | + */ | |
118 | + SDL_InitSubSystem(SDL_INIT_VIDEO|SDL_INIT_JOYSTICK|SDL_INIT_EVENTS); | |
119 | + | |
120 | + out->ctx.win = out->win = SDL_CreateWindow(title, | |
121 | + SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, w, h, sdl_flags); | |
122 | + out->ctx.ctx = NULL; | |
123 | +} | |
124 | + | |
125 | +/******************************************************************************/ | |
126 | + | |
127 | +void Glow_DestroyWindow(struct Glow_Window *win){ | |
128 | + SDL_DestroyWindow(win->win); | |
129 | + if(win->ctx.ctx != NULL) | |
130 | + SDL_GL_DeleteContext(win->ctx.ctx); | |
131 | + SDL_QuitSubSystem(SDL_INIT_VIDEO|SDL_INIT_JOYSTICK|SDL_INIT_EVENTS); | |
132 | +} | |
133 | + | |
134 | +/******************************************************************************/ | |
135 | + | |
136 | +void Glow_SetTitle(struct Glow_Window *win, const char *title){ | |
137 | + SDL_SetWindowTitle(win->win, title); | |
138 | +} | |
139 | + | |
140 | +/******************************************************************************/ | |
141 | + | |
142 | +void Glow_ShowWindow(struct Glow_Window *win){ | |
143 | + SDL_ShowWindow(win->win); | |
144 | + SDL_RaiseWindow(win->win); | |
145 | +} | |
146 | + | |
147 | +/******************************************************************************/ | |
148 | + | |
149 | +void Glow_HideWindow(struct Glow_Window *win){ | |
150 | + SDL_HideWindow(win->win); | |
151 | +} | |
152 | + | |
153 | +/******************************************************************************/ | |
154 | + | |
155 | +void Glow_GetWindowSize(const struct Glow_Window *win, | |
156 | + unsigned *out_w, unsigned *out_h){ | |
157 | + | |
158 | + int w, h; | |
159 | + SDL_GetWindowSize(win->win, &w, &h); | |
160 | + out_w[0] = w; | |
161 | + out_h[0] = h; | |
162 | +} | |
163 | + | |
164 | +/******************************************************************************/ | |
165 | + | |
166 | +void Glow_FlipScreen(struct Glow_Window *win){ | |
167 | + SDL_GL_SwapWindow(win->win); | |
168 | +} | |
169 | + | |
170 | +/******************************************************************************/ | |
171 | + | |
172 | +static int glow_write_keyname(const SDL_Event *in, struct Glow_Event *out){ | |
173 | + const char *const name = SDL_GetKeyName(in->key.keysym.sym); | |
174 | +#if defined _WIN32 || defined __CYGWIN__ || defined WIN32 | |
175 | + strncpy(out->value.key, name, GLOW_MAX_KEY_NAME_SIZE-2); | |
176 | + out->value.key[GLOW_MAX_KEY_NAME_SIZE-1] = 0; | |
177 | +#else | |
178 | + strlcpy(out->value.key, name, GLOW_MAX_KEY_NAME_SIZE-1); | |
179 | +#endif | |
180 | + return 1; | |
181 | +} | |
182 | + | |
183 | +/******************************************************************************/ | |
184 | + | |
185 | +static enum Glow_MouseButton glow_translate_button(unsigned s){ | |
186 | + if((s & SDL_BUTTON_LMASK) != 0) | |
187 | + return eGlowLeft; | |
188 | + if((s & SDL_BUTTON_RMASK) != 0) | |
189 | + return eGlowRight; | |
190 | + if((s & SDL_BUTTON_MMASK) != 0) | |
191 | + return eGlowMiddle; | |
192 | + return eGlow_NUM_BUTTONS; | |
193 | +} | |
194 | + | |
195 | +/******************************************************************************/ | |
196 | + | |
197 | +static int glow_convert_sdl2_event(const SDL_Event *in, | |
198 | + struct Glow_Event *out){ | |
199 | + | |
200 | + switch(in->type){ | |
201 | + case SDL_QUIT: | |
202 | + case SDL_APP_TERMINATING: | |
203 | + out->type = eGlowQuit; | |
204 | + return 1; | |
205 | + case SDL_KEYDOWN: | |
206 | + out->type = eGlowKeyboardPressed; | |
207 | + return glow_write_keyname(in, out); | |
208 | + case SDL_KEYUP: | |
209 | + out->type = eGlowKeyboardReleased; | |
210 | + return glow_write_keyname(in, out); | |
211 | + case SDL_MOUSEMOTION: | |
212 | + out->type = eGlowMouseMoved; | |
213 | + out->value.mouse.xy[0] = in->motion.x; | |
214 | + out->value.mouse.xy[1] = in->motion.y; | |
215 | + out->value.mouse.button = glow_translate_button(in->motion.state); | |
216 | + return 1; | |
217 | + case SDL_MOUSEBUTTONDOWN: | |
218 | + out->type = eGlowMousePressed; | |
219 | + out->value.mouse.xy[0] = in->button.x; | |
220 | + out->value.mouse.xy[1] = in->button.y; | |
221 | + out->value.mouse.button = glow_translate_button(in->button.state); | |
222 | + return 1; | |
223 | + case SDL_MOUSEBUTTONUP: | |
224 | + out->type = eGlowMouseReleased; | |
225 | + out->value.mouse.xy[0] = in->button.x; | |
226 | + out->value.mouse.xy[1] = in->button.y; | |
227 | + out->value.mouse.button = glow_translate_button(in->button.state); | |
228 | + return 1; | |
229 | + case SDL_WINDOWEVENT: | |
230 | + switch(in->window.event){ | |
231 | + case SDL_WINDOWEVENT_SIZE_CHANGED: /* FALLTHROUGH */ | |
232 | + case SDL_WINDOWEVENT_RESIZED: | |
233 | + out->type = eGlowResized; | |
234 | + out->value.resize[0] = in->window.data1; | |
235 | + out->value.resize[1] = in->window.data2; | |
236 | + return 1; | |
237 | + } | |
238 | + break; | |
239 | + } | |
240 | + | |
241 | + return 0; | |
242 | +} | |
243 | + | |
244 | +/******************************************************************************/ | |
245 | + | |
246 | +unsigned Glow_GetEvent(struct Glow_Window *win, struct Glow_Event *out_event){ | |
247 | + | |
248 | + SDL_Event ev; | |
249 | + (void)win; | |
250 | + | |
251 | + while(SDL_PollEvent(&ev)){ | |
252 | + if(glow_convert_sdl2_event(&ev, out_event)) | |
253 | + return 1; | |
254 | + } | |
255 | + | |
256 | + return 0; | |
257 | +} | |
258 | + | |
259 | +/******************************************************************************/ | |
260 | + | |
261 | +void Glow_WaitEvent(struct Glow_Window *win, struct Glow_Event *out_event){ | |
262 | + | |
263 | + SDL_Event ev; | |
264 | + (void)win; | |
265 | + | |
266 | + do{ | |
267 | + SDL_WaitEvent(&ev); | |
268 | + }while(!glow_convert_sdl2_event(&ev, out_event)); | |
269 | +} | |
270 | + | |
271 | +/******************************************************************************/ | |
272 | + | |
273 | +unsigned Glow_ContextStructSize(void){ | |
274 | + return sizeof(struct Glow_Context); | |
275 | +} | |
276 | + | |
277 | +/******************************************************************************/ | |
278 | + | |
279 | +int Glow_CreateContext(struct Glow_Window *win, | |
280 | + struct Glow_Context *opt_share, | |
281 | + unsigned major, unsigned minor, | |
282 | + struct Glow_Context *out){ | |
283 | + | |
284 | + if(opt_share != NULL){ | |
285 | + SDL_GL_MakeCurrent(win->win, opt_share->ctx); | |
286 | + SDL_GL_SetAttribute(SDL_GL_SHARE_WITH_CURRENT_CONTEXT, 1); | |
287 | + } | |
288 | + else{ | |
289 | + SDL_GL_SetAttribute(SDL_GL_SHARE_WITH_CURRENT_CONTEXT, 0); | |
290 | + } | |
291 | + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, major); | |
292 | + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, minor); | |
293 | + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); | |
294 | + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, | |
295 | + SDL_GL_CONTEXT_PROFILE_CORE); | |
296 | + out->ctx = SDL_GL_CreateContext(win->win); | |
297 | + out->win = win->win; | |
298 | + return 0; | |
299 | +} | |
300 | + | |
301 | +/******************************************************************************/ | |
302 | + | |
303 | +void Glow_CreateLegacyContext(struct Glow_Window *win, | |
304 | + struct Glow_Context *out){ | |
305 | + | |
306 | + SDL_GL_SetAttribute(SDL_GL_SHARE_WITH_CURRENT_CONTEXT, 0); | |
307 | + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); | |
308 | + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); | |
309 | + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); | |
310 | + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, | |
311 | + SDL_GL_CONTEXT_PROFILE_COMPATIBILITY); | |
312 | + win->ctx.ctx = SDL_GL_CreateContext(win->win); | |
313 | + if(out) | |
314 | + out->ctx = win->ctx.ctx; | |
315 | +} | |
316 | + | |
317 | +/******************************************************************************/ | |
318 | + | |
319 | +void Glow_MakeCurrent(struct Glow_Context *ctx){ | |
320 | + SDL_GL_MakeCurrent(ctx->win, ctx->win); | |
321 | +} | |
322 | + | |
323 | +/******************************************************************************/ | |
324 | + | |
325 | +struct Glow_Window *Glow_CreateLegacyWindow( | |
326 | + unsigned w, unsigned h, const char *title){ | |
327 | + | |
328 | + struct Glow_Window *const win = malloc(sizeof(struct Glow_Window)); | |
329 | + Glow_CreateWindow(win, w, h, title, 0); | |
330 | + Glow_CreateLegacyContext(win, NULL); | |
331 | + return win; | |
332 | +} |
@@ -12,6 +12,12 @@ glow.lib: glow_win32.obj | ||
12 | 12 | glow.dll: glow_win32.obj |
13 | 13 | link /nologo /dll /out:glow.dll /implib:glow.lib OpenGL32.lib gdi32.lib user32.lib glow_win32.obj |
14 | 14 | |
15 | +glow_sdl2.obj: glow_sdl2.c glow.h | |
16 | + cl /I"$(MAKEDIR)\include" /DGLOW_EXPORTS /DGLOW_DLL /c glow_sdl2.c /nologo | |
17 | + | |
18 | +sdl2: glow_sdl2.obj | |
19 | + link /nologo /dll /out:glow.dll /implib:glow.lib sdl2.lib glow_sdl2.obj /LIBPATH:"$(MAKEDIR)\lib" | |
20 | + | |
15 | 21 | clean: |
16 | 22 | del glow.dll > nul || echo > nul |
17 | 23 | del glow.lib > nul || echo > nul |