aboutsummaryrefslogtreecommitdiffstats
path: root/README.asciidoc
blob: 1ab6055ec8a17b30dfce2276bdef31fb44f72f77 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
= ESDL2

SDL2 Erlang NIF.

The following sections list the state of the implementation
as of SDL 2.0.7. The implementation is cut into sections
corresponding to the public headers.

== Fully implemented

* 'SDL.h'
* 'SDL_blendmode.h'
* 'SDL_cpuinfo.h'
* 'SDL_filesystem.h'
* 'SDL_keyboard.h'
* 'SDL_keycode.h'
* 'SDL_mouse.h'
* 'SDL_platform.h'
* 'SDL_power.h'
* 'SDL_scancode.h'

== Partially implemented

* 'SDL_clipboard.h': We currently do not support UTF-8. We should probably switch to binaries as input/output to support it.
* 'SDL_events.h': The following events and functions are missing:
** `SDL_SYSWMEVENT`
** `SDL_TEXTEDITING`
** `SDL_TEXTINPUT`
** `SDL_JOYAXISMOTION`
** `SDL_JOYBALLMOTION`
** `SDL_JOYHATMOTION`
** `SDL_JOYBUTTONDOWN`
** `SDL_JOYBUTTONUP`
** `SDL_JOYDEVICEADDED`
** `SDL_JOYDEVICEREMOVED`
** `SDL_CONTROLLERAXISMOTION`
** `SDL_CONTROLLERBUTTONDOWN`
** `SDL_CONTROLLERBUTTONUP`
** `SDL_CONTROLLERDEVICEADDED`
** `SDL_CONTROLLERDEVICEREMOVED`
** `SDL_CONTROLLERDEVICEREMAPPED`
** `SDL_FINGERDOWN`
** `SDL_FINGERUP`
** `SDL_FINGERMOTION`
** `SDL_DOLLARGESTURE`
** `SDL_DOLLARRECORD`
** `SDL_MULTIGESTURE`
** `SDL_DROPFILE`
** `SDL_DROPTEXT`
** `SDL_DROPBEGIN`
** `SDL_DROPCOMPLETE`
** `SDL_AUDIODEVICEADDED`
** `SDL_AUDIODEVICEREMOVED`
** `SDL_PeepEvents` with action argument `SDL_ADDEVENT`
** `SDL_PushEvents`
** `SDL_SetEventFilter`
** `SDL_GetEventFilter`
** `SDL_AddEventWatch`
** `SDL_DelEventWatch`
** `SDL_FilterEvents`
** `SDL_EventState` and `SDL_GetEventState`
** `SDL_RegisterEvents`
* 'SDL_hints.h': We only have a proof of concept callback system.
* 'SDL_pixels.h': Only the pixel format enum and conversion function is defined.
* 'SDL_rect.h': Everything is missing except the map to point/rect conversion functions.
* 'SDL_render.h': The following elements are missing:
** `SDL_TextureAccess` enum
** `SDL_TextureModulate` enum
** `SDL_CreateWindowAndRenderer` is currently located in `sdl_window`. Move it?
** `SDL_CreateSoftwareRenderer` (renderer)
** `SDL_CreateTexture` (texture)
** `SDL_QueryTexture` (texture)
** `SDL_UpdateTexture` (texture)
** `SDL_UpdateYUVTexture` (texture)
** `SDL_LockTexture` (texture)
** `SDL_UnlockTexture` (texture)
** `SDL_SetRenderTarget` (renderer)
** `SDL_GetRenderTarget` (renderer)
** `SDL_RenderIsClipEnabled` (renderer)
** `SDL_RenderReadPixels` (renderer)
** `SDL_GL_BindTexture` (gl)
** `SDL_GL_UnbindTexture` (gl)
* 'SDL_stdinc.h': SDL_bool is implemented in 'sdl_bool.c'. Do we need anything else?
* 'SDL_surface.h': Only surface creation (via `IMG_Load`) and destruction is implemented. Might be better to move IMG_* functions in their own space.
* 'SDL_version.h': `SDL_GetRevisionNumber` must be implemented. The macros may also be useful.
* 'SDL_video.h': The following elements are missing:
** `SDL_WINDOWPOS_*` values for different displays
** `SDL_CreateWindowFrom` (unclear if we need it)
** We currently do not support UTF-8. We should probably switch to binaries as input/output to support it for `SDL_SetWindowTitle` and `SDL_GetWindowTitle`
** `SDL_SetWindowData` (unclear if we need it)
** `SDL_GetWindowData` (unclear if we need it)
** `SDL_GetWindowSurface` (window)
** `SDL_UpdateWindowSurface` (window)
** `SDL_UpdateWindowSurfaceRects` (window)
** `SDL_IsScreenSaverEnabled`
** `SDL_EnableScreenSaver`
** `SDL_DisableScreenSaver`
** `SDL_GL_LoadLibrary` (unclear if we need it)
** `SDL_GL_GetProcAddress` (unclear if we need it)
** `SDL_GL_UnloadLibrary` (unclear if we need it)
** `SDL_GL_ExtensionSupported`
** `SDL_GL_ResetAttributes`
** `SDL_GL_SetAttribute`
** `SDL_GL_GetAttribute`
** `SDL_GL_MakeCurrent`
** `SDL_GL_GetCurrentWindow`
** `SDL_GL_GetCurrentContext`
** `SDL_GL_GetDrawableSize`
** `SDL_GL_SetSwapInterval`
** `SDL_GL_GetSwapInterval`

The code sometimes uses `malloc`. Use `enif_alloc` everywhere instead.

== To be implemented

* 'SDL_audio.h'
* 'SDL_error.h' (for completion)
* 'SDL_gamecontroller.h'
* 'SDL_gesture.h'
* 'SDL_haptic.h'
* 'SDL_joystick.h'
* 'SDL_messagebox.h'
* 'SDL_rwops.h' (unclear if we need it)
* 'SDL_shape.h'
* 'SDL_system.h'
* 'SDL_syswm.h'
* 'SDL_timer.h' (unclear if we need it)
* 'SDL_touch.h'
* 'SDL_vulkan.h'

For OpenGL we need to figure out whether we can call the functions from
wxErlang. If we can, great! If not, find an automated way to provide
access to OpenGL.

SDL extensions also need to be investigated and implemented.
We definitely want at least some of SDL_image, SDL_mixer
and SDL_ttf. We probably do not need SDL_net or SDL_rtf.

== To be removed

* `SDL_SetMainReady` which has no public interface, only the NIF function.

== Don't implement

These don't make a lot of sense for Erlang.

* 'SDL_assert.h'
* 'SDL_atomic.h'
* 'SDL_bits.h'
* 'SDL_endian.h'
* 'SDL_events.h': the functions `SDL_WaitEvent` and `SDL_WaitEventTimeout` are blocking.
* 'SDL_loadso.h'
* 'SDL_log.h'
* 'SDL_main.h'
* 'SDL_mutex.h'
* 'SDL_quit.h' (only necessary when using `SDL_Main`?)
* 'SDL_thread.h'

== Nothing to implement

These are either private headers, duplicated OpenGL/Vulkan
headers or simply deprecated.

* 'SDL_config.h'
* 'SDL_config_android.h'
* 'SDL_config_iphoneos.h'
* 'SDL_config_macosx.h'
* 'SDL_config_minimal.h'
* 'SDL_config_pandora.h'
* 'SDL_config_psp.h'
* 'SDL_config_windows.h'
* 'SDL_config_winrt.h'
* 'SDL_config_wiz.h'
* 'SDL_copying.h'
* 'SDL_egl.h'
* 'SDL_name.h'
* 'SDL_opengl.h'
* 'SDL_opengl_glext.h'
* 'SDL_opengles.h'
* 'SDL_opengles2.h'
* 'SDL_opengles2_gl2.h'
* 'SDL_opengles2_gl2ext.h'
* 'SDL_opengles2_gl2platform.h'
* 'SDL_opengles2_khrplatform.h'
* 'SDL_revision.h'
* 'SDL_test.h'
* 'SDL_test_assert.h'
* 'SDL_test_common.h'
* 'SDL_test_compare.h'
* 'SDL_test_crc32.h'
* 'SDL_test_font.h'
* 'SDL_test_fuzzer.h'
* 'SDL_test_harness.h'
* 'SDL_test_images.h'
* 'SDL_test_log.h'
* 'SDL_test_md5.h'
* 'SDL_test_memory.h'
* 'SDL_test_random.h'
* 'SDL_types.h'
* 'begin_code.h'
* 'close_code.h'

== Thoughts on callbacks

SDL2 has a number of callback interfaces. While we probably
do not want to implement some of them (like the OS-specific
callbacks for Windows and iOS) we do need others.

Callbacks that have no return value are easy to implement.
The idea is to have an Erlang process that waits for messages
containing the callback MFA to execute. The following callbacks
have no return value and no other caveat:

* `SDL_AudioCallback`
* `SDL_iOSSetAnimationCallback` (iOS)
* `SDL_SetWindowsMessageHook` (Windows)

The callback functions for hints do not have a return value
either, but they have an extra caveat: there can be more
than one per hint. SDL2 identifies these callbacks with the
tuple `(callback, userdata)` and we need to give SDL2 this
same tuple in order to remove the callback.

The best way to handle this is probably to do it mostly via
Erlang where a process would take care of the callbacks and
would enable/disable the SDL2 callbacks when required. The
`userdata` would in this case always be `NULL` since all the
handling would be done from the Erlang side.

The alternative would be to create a resource per callback
that the user would have to keep around and that's not very
convenient.

The functions in question are:

* `SDL_AddHintCallback`
* `SDL_DelHintCallback`

Other callbacks have a return value but otherwise work in a
slightly different manner from each other. The callback can
be invoked in a similar manner to others, by sending a message
to the Erlang code. The difficulty comes in returning the
result to the NIF code. The solution for doing that
will vary depending on the callback in question.

There can be one window hit test callback per window. This
means we can use the window's user data for storing the
result and then signal the NIF to read from it using the
NIF mutex/cond mechanism. Both of those can also be stored
in the window's user data.

This means the window must be sent to Erlang and passed
back to the NIF when giving the result back, which should
be trivial. The callback data can stay empty since we
store everything in the window data.

The function in question is:

* `SDL_SetWindowHitTest`

The final set of callbacks is timers. When you add a timer
it returns a `TimerID` and you can use it to remove the
timer. In addition, the callback can decide to change the
timer interval or to stop the timer. Unlike for windows
there is no way to attach information to a `TimerID` so
a separate solution will be necessary. Since there can
be any number of timers and they can fire off at any
time then some kind of queue will be necessary to store
return values.

Even though we don't know the `TimerID` when setting up
the timer, we should be able to keep it around in the
same data structure used for the callback extra parameter.
There is however the concern of memory allocation: we
will probably need to hook into all functions that can
remove timers to make sure we free the memory we allocated
too.

They're the hardest callback functions to implement, but
thankfully they're also some of the least interesting
considering Erlang already comes with many ways to deal
with timers.

Even if we do implement them, their scope may be reduced
so that we always return the same interval as a return
value and therefore don't allow changing the interval or
stopping the timer from inside a timer callback.

The functions in question are:

* `SDL_AddTimer`
* `SDL_RemoveTimer`

Other than hints, it should be possible to have a common
mechanism for all callbacks. The following messages may
be sent from the NIF:

* `{callback, M, F, Args}` for `void`
* `{callback, M, F, Args, ResF, ResExtraArg}` for others

The `esdl2:ResF(Result, ResExtraArg)` function would be
called in the second case after the callback returns.
The NIF function can then decide what the appropriate
behavior is for sending the result back to the SDL2
callback.

The main concern when dealing with SDL2 callbacks is
the memory allocations since SDL2 will not free the
memory we allocate. Solutions should be extra careful
not to introduce leaks and try to avoid allocating
memory entirely for callbacks. When not possible then
the memory must be allocated and freed in the course
of running the Erlang callback and not be kept any
longer.