|
Experiments: Allegro + Emscripten. |
Max Savenkov
Member #4,613
May 2004
|
I decided to give compiling Allegro with Emscripten a try. So far, I got past slight CMake and Emscriptent problems (Emscripten's libc does not have getexecname, so I had to add a stub for it) and managed to produce liballegro_monolith.so and link my test program against it. A test consisting of a single call to al_init() works, but of course doing anything else requires far more work. During this weekend, I'll try to see if I can rig up graphic driver which could at least create a display and clear it. If you are interested or want to help, post here and we'll think of something. Why am I doing this: well, my good friend is always taunting me with Unity's ability to quickly demonstrate things through browser. I want Allegro to do the same. Also, there is a Game Jam coming up in Russia, where ability to run code in browser is needed, so I want to try to make Allegro work with Emscripten before it starts, but I might be waaaaaay to optimistic.
|
AMCerasoli
Member #11,955
May 2010
|
What is the process you're following right now to convert C code into Javascript code, can we have a demonstration, it's a very interesting feature indeed.
|
Max Savenkov
Member #4,613
May 2004
|
Emscripten uses LLVM to compile C/C++ code into bytecode and then transform bytecode into JavaScript. See Emscripten: Building Projects. The demo of my test is here: http://zxstudio.org/projects/allegro/my.html. Basically, I did these steps: 1. Install Emscripten base SDK (Since I'm on Windows, there is a ready-made binaries, but there is an instruction on building it from sources on Linux) 2. Run emcmdprompt.bat to get shell with Emscripten added to PATH 3. Install latest SDK elements via: Install MinGW, because Emscriptent does not seem to work with cygwin and Visual Studio support is experimental: 4. Fix the lack of getexecname by adding the following lines to emscripten\1.13.0\src\library.js: getexecname: function() { return ""; }, 5. In Allegro's main CMakeLists.txt, comment out if(NOT IPHONE) test_big_endian(ALLEGRO_BIG_ENDIAN) endif(NOT IPHONE) We should add a real check for Emscripten here instead of just removing this check, but I'm in hurry 6. Try to run CMake with -DCMAKE_TOOLCHAIN_FILE=C:\X\emscripten\emscripten\1.13.0\cmake\Platform\Emscripten.cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -G "MinGW Makefiles" .. -DWANT_X11=OFF -DWANT-OPENGLES=ON -DALLEGRO_EXCLUDE_GLX=ON -DWANT_MONOLITH=ON Note the use of ALLEGRO_EXCLUDE_GLX. We're building for Unix-like environment, but it does not have X11 7. See it fail, mess around with set of flags until everything compiles. Here's my list of WANTs: 1//Enable DLL loading in acodec (Windows)
2WANT_ACODEC_DYNAMIC_LOAD:BOOL=OFF
3
4//Allow compiler to use SSE instructions (x86)
5WANT_ALLOW_SSE:BOOL=OFF
6
7//Enable ALSA digital audio driver (Unix)
8WANT_ALSA:BOOL=OFF
9
10//Build for Android
11WANT_ANDROID:BOOL=OFF
12
13//Build for Android 4 (1.6)
14WANT_ANDROID_LEGACY:BOOL=OFF
15
16//Enable AudioQueue digital audio driver (Mac)
17WANT_AQUEUE:BOOL=OFF
18
19//Enable allegro_audio engine
20WANT_AUDIO:BOOL=OFF
21
22//Enable color addon
23WANT_COLOR:BOOL=ON
24
25//Build ex_curl example
26WANT_CURL_EXAMPLE:BOOL=OFF
27
28//Enable Direct3D graphics driver (Windows)
29WANT_D3D:BOOL=OFF
30
31//Enable Direct3D 9Ex extensions (Vista)
32WANT_D3D9EX:BOOL=OFF
33
34//Build demo programs
35WANT_DEMO:BOOL=OFF
36
37//Force use of DllMain for TLS (Windows)
38WANT_DLL_TLS:BOOL=OFF
39
40//Generate documentation
41WANT_DOCS:BOOL=OFF
42
43//Enable DSound digital audio driver (Windows)
44WANT_DSOUND:BOOL=OFF
45
46//Make frameworks embeddable in application bundles (Mac OS X)
47WANT_EMBED:BOOL=OFF
48
49//Build example programs
50WANT_EXAMPLES:BOOL=ON
51
52//Enable FFMPEG video driver
53WANT_FFMPEG:BOOL=OFF
54
55//Enable FLAC support
56WANT_FLAC:BOOL=OFF
57
58//Enable bitmap font add-on
59WANT_FONT:BOOL=ON
60
61//Want frameworks on Mac OS X
62WANT_FRAMEWORKS:BOOL=OFF
63
64//Compile with GLES2 support
65WANT_GLES2:BOOL=ON
66
67//Enable image load/save addon
68WANT_IMAGE:BOOL=ON
69
70//Enable JPEG support in image addon
71WANT_IMAGE_JPG:BOOL=ON
72
73//Enable PNG support in image addon
74WANT_IMAGE_PNG:BOOL=ON
75
76//Enable memfile addon
77WANT_MEMFILE:BOOL=ON
78
79//Enable MOD Audio support
80WANT_MODAUDIO:BOOL=OFF
81
82//Include all addons in the main library
83WANT_MONOLITH:BOOL=ON
84
85//Enable gcc mudflap (requires gcc 4.0+)
86WANT_MUDFLAP:BOOL=OFF
87
88//Enable native dialog addon
89WANT_NATIVE_DIALOG:BOOL=OFF
90
91//Enable the native platform image loader (if available)
92WANT_NATIVE_IMAGE_LOADER:BOOL=OFF
93
94//Enable Ogg video (requires Theora and Vorbis)
95WANT_OGG_VIDEO:BOOL=OFF
96
97//Enable OpenAL digital audio driver
98WANT_OPENAL:BOOL=ON
99
100//Enable OpenGL graphics driver (Windows, X11, OS X))
101WANT_OPENGL:BOOL=ON
102
103//Enable OpenSL digital audio driver (Android)
104WANT_OPENSL:BOOL=OFF
105
106//Enable OSS digital audio driver (Unix)
107WANT_OSS:BOOL=OFF
108
109//Enable PhysicsFS addon
110WANT_PHYSFS:BOOL=OFF
111
112//Use popups instead of printf for fatal errors
113WANT_POPUP_EXAMPLES:BOOL=OFF
114
115//Enable primitives addon
116WANT_PRIMITIVES:BOOL=ON
117
118//Enable PulseAudio audio driver (Unix)
119WANT_PULSEAUDIO:BOOL=OFF
120
121//Enable generation of the Python wrapper
122WANT_PYTHON_WRAPPER:BOOL=OFF
123
124//Enable logging even in release mode
125WANT_RELEASE_LOGGING:BOOL=OFF
126
127//Build HLSL shader support (Direct3D)
128WANT_SHADERS_D3D:BOOL=OFF
129
130//Build GLSL shader support (OpenGL)
131WANT_SHADERS_GL:BOOL=ON
132
133//Build test programs
134WANT_TESTS:BOOL=OFF
135
136//Enable Ogg Vorbis support using Tremor
137WANT_TREMOR:BOOL=OFF
138
139//Enable TTF addon
140WANT_TTF:BOOL=OFF
141
142//Enable video player addon
143WANT_VIDEO:BOOL=OFF
144
145//Enable Ogg Vorbis support using libvorbis
146WANT_VORBIS:BOOL=OFF
147
148//X11 support
149WANT_X11:BOOL=OFF
150
151//X11 XF86VidMode Extension support
152WANT_X11_XF86VIDMODE:BOOL=OFF
153
154//X11 Xinerama Extension support
155WANT_X11_XINERAMA:BOOL=OFF
156
157//X11 XRandR Extension support
158WANT_X11_XRANDR:BOOL=OFF
I don't have any dependencies compiled yet, so most of addons won't work. But for now, the goal is to just get Allegro running, so it does not matter. 8. Run make install 9. Compile my own test with: emcc test.cpp -o test.html -I%PATH_TO_ALLEGRO_INCLUDE% -L%PATH_TO_ALLEGRO_LIB% -lallegro_monolith -g4 Note that there must be a space after "-o" because otherwise it is ignored (emcc isn't as robust as it should be).
|
Aikei_c
Member #14,871
January 2013
|
The test fails for me. It says "al_init failed: 2". |
Max Savenkov
Member #4,613
May 2004
|
That's normal. I did not check return value of al_init yesterday, and of course al_init cannot succeed since I did not provide a system driver for it! I'm working on it. I'll update the test to reflect progress when I have it failing later that presently
|
Aikei_c
Member #14,871
January 2013
|
I probably misunderstood you, you said "a single call to al_init() works" which I assumed to mean "al_init() finishes successfully". |
Max Savenkov
Member #4,613
May 2004
|
No, it was my error. Yesterday, I thought it did finish successfully, but today I checked return value and was disappointed Which just shows I shouldn't really be coding at 11pm after work.
|
Thomas Fjellstrom
Member #476
June 2000
|
Either way, progress is progress. -- |
AMCerasoli
Member #11,955
May 2010
|
I'm completely ignorant about Emscripten but it seems a lot of work to get Allegro 5 fully supported, the good think is that I think it's possible. I'm not so interested though. I think it would be nice to have the ability to convert C code into javascript, but I can't stop thinking that if I'm using C and compiling a native game it's because it has some advantages compared to Javascript and a browser based game. If you think about, if you create a browser game, there is no need to create a native version of it. But if you create a native game you might want to be able to run it on a browser, but if your game is able to run well on a browser why did you made it in native code in the first place? I don't know if you can understand what I'm trying to say. In my current game for example, I'm not only using Allegro, but protobuf, sqlite, enet, etc... I think it would be impossible to magically convert my game and run it on a browser, so you might argue: "Of course not, this is something for simpler games", and then I would say, why are you using native code and Allegro when you could do it directly with "web software"? Those are the points that are kind of confusing my about this, and always had actually. If I could just press a button and that's it my game is ready then it would be fine. But I think these tools are great for game-makers software like unity that have everything already integrated. They have the disadvantage that they limit you, but at the same time thanks to this limitations they can compile their projects in multiple formats. Now, I still think that it would be great for a simple game made with Allegro be able to run it on a browser, but tomorrow when your friend create a game that uses networking and you won't be able to do the same with Allegro it will be reproaching you again about unity being able to do something that Allegro doesn't.
|
Max Savenkov
Member #4,613
May 2004
|
Well, I can see at least one benefit in compiling Allegro into JS for myself: ability to quickly demo my games via web. So maybe the final game couldn't be ever compiled to JS, but a prototype could, and that's enough for me. I'm not really interested in getting my games to run in browser, because browser games require completely different gameplay. EDIT: Aaaaand we have working al_init! Example is updated, so you can see it for yourself. I had to write a stub for get_path. Running in browser does not provide you with much access to filesystem, so my implementation just returns "./" for any type of standard path. Example is uploaded as a debug build, so you can step through it with Firefox web console/debugger. EDIT2: OK, now I can create a display and even clear it to red color. That's halfway to a complete port! (Example updated). On a more serious note, I'll try to load and display a bitmap next. Also, I get a lot of messages about missing OpenGL extensions from Allegro. I don't know how essential those are... Also, Emscripten does not support any fixed pipeline functions at all, so if Allegro relies on those anywhere it won't fly.
|
Aikei_c
Member #14,871
January 2013
|
That's nice! You are actually getting somewhere. |
Thomas Fjellstrom
Member #476
June 2000
|
Oh wow, I am seriously looking forward to this. I want to try my silly little Canva5 lib on it. You may have to make a modified GL driver, base it on the generic gl/*.c code. The current mess we have in gl/* with all the ifdefs is getting kinda messy. What we need is someone to go in there and replace most of them with a single #ifdef GLES in only the absolutely required parts, and maybe simplify it into separate drivers for iphone, android and a more generic target. So the gl code should be stripped of any kind of platform specific assumptions. But that could be hard and or complex. Tedious at the very least. -- |
Max Savenkov
Member #4,613
May 2004
|
I'm mostly basing Emscripten code on Raspberry Pi port, because there are more similarities between them than with Android or iPhone. Maybe I'm wrong to do it, of course, but I know little about OpenGL, desktop or ES, so I mostly copy & paste stuff, for now There had been little progress today. I fixed error in display initialization and loaded a bitmap, but I can't get to appear on screen. So I have a question for those who know a bit more about Allegro internals and/or OpenGL ES. Presently, I get this error from ogl_flush_vertex_cache -> vert_ptr_on -> glVertexAttribPointer: Error: WebGL: vertexAttribPointer: must have valid GL_ARRAY_BUFFER binding It seems that this error happens, because Allegro is attempting to draw something without using VBOs, which is the only way to work with OpenGL ES2. But I have WANT_OPENGLES2 defined, and from what I can see in code, mostly the checks are for OPENGLES && PROGRAMMABLE_PIPELINE, not specifically from OPENGLES2. Let's have a look at the code for ogl_flush_vertex_cache together: 1static void ogl_flush_vertex_cache(ALLEGRO_DISPLAY *disp)
2{
3 GLuint current_texture;
4 ALLEGRO_OGL_EXTRAS *o = disp->ogl_extras;
5 (void)o; /* not used in all ports */
6
7 if (!disp->vertex_cache)
8 return;
9 if (disp->num_cache_vertices == 0)
10 return;
11
12 if (disp->flags & ALLEGRO_PROGRAMMABLE_PIPELINE) {
13#ifdef ALLEGRO_CFG_OPENGL_PROGRAMMABLE_PIPELINE
14 if (disp->ogl_extras->varlocs.use_tex_loc >= 0) {
15 glUniform1i(disp->ogl_extras->varlocs.use_tex_loc, 1);
16 }
17 if (disp->ogl_extras->varlocs.use_tex_matrix_loc >= 0) {
18 glUniform1i(disp->ogl_extras->varlocs.use_tex_matrix_loc, 0);
19 }
20#endif
21 }
22 else {
23 glEnable(GL_TEXTURE_2D);
24 }
25
26 glGetIntegerv(GL_TEXTURE_BINDING_2D, (GLint*)¤t_texture);
27 if (current_texture != disp->cache_texture) {
28 if (disp->flags & ALLEGRO_PROGRAMMABLE_PIPELINE) {
29#ifdef ALLEGRO_CFG_OPENGL_PROGRAMMABLE_PIPELINE
30 /* Use texture unit 0 */
31 glActiveTexture(GL_TEXTURE0);
32 if (disp->ogl_extras->varlocs.tex_loc >= 0)
33 glUniform1i(disp->ogl_extras->varlocs.tex_loc, 0);
34#endif
35 }
36 glBindTexture(GL_TEXTURE_2D, disp->cache_texture);
37 }
38
39#if !defined(ALLEGRO_CFG_OPENGLES) && !defined(ALLEGRO_MACOSX)
40 if (disp->flags & ALLEGRO_PROGRAMMABLE_PIPELINE) {
41 int stride = sizeof(ALLEGRO_OGL_BITMAP_VERTEX);
42 int bytes = disp->num_cache_vertices * stride;
43
44 /* We create the VAO and VBO on first use. */
45 if (o->vao == 0) {
46 glGenVertexArrays(1, &o->vao);
47 ALLEGRO_DEBUG("new VAO: %u\n", o->vao);
48 }
49 glBindVertexArray(o->vao);
50
51 if (o->vbo == 0) {
52 glGenBuffers(1, &o->vbo);
53 ALLEGRO_DEBUG("new VBO: %u\n", o->vbo);
54 }
55 glBindBuffer(GL_ARRAY_BUFFER, o->vbo);
56
57 /* Then we upload data into it. */
58 glBufferData(GL_ARRAY_BUFFER, bytes, disp->vertex_cache, GL_STREAM_DRAW);
59
60 /* Finally set the "pos", "texccord" and "color" attributes used by our
61 * shader and enable them.
62 */
63 if (o->varlocs.pos_loc >= 0) {
64 glVertexAttribPointer(o->varlocs.pos_loc, 2, GL_FLOAT, false, stride,
65 (void *)offsetof(ALLEGRO_OGL_BITMAP_VERTEX, x));
66 glEnableVertexAttribArray(o->varlocs.pos_loc);
67 }
68
69 if (o->varlocs.texcoord_loc >= 0) {
70 glVertexAttribPointer(o->varlocs.texcoord_loc, 2, GL_FLOAT, false, stride,
71 (void *)offsetof(ALLEGRO_OGL_BITMAP_VERTEX, tx));
72 glEnableVertexAttribArray(o->varlocs.texcoord_loc);
73 }
74
75 if (o->varlocs.color_loc >= 0) {
76 glVertexAttribPointer(o->varlocs.color_loc, 4, GL_FLOAT, false, stride,
77 (void *)offsetof(ALLEGRO_OGL_BITMAP_VERTEX, r));
78 glEnableVertexAttribArray(o->varlocs.color_loc);
79 }
80 }
81 else
82#endif
83 {
84 vert_ptr_on(disp, 2, GL_FLOAT, sizeof(ALLEGRO_OGL_BITMAP_VERTEX),
85 (char *)(disp->vertex_cache) + offsetof(ALLEGRO_OGL_BITMAP_VERTEX, x));
86 tex_ptr_on(disp, 2, GL_FLOAT, sizeof(ALLEGRO_OGL_BITMAP_VERTEX),
87 (char*)(disp->vertex_cache) + offsetof(ALLEGRO_OGL_BITMAP_VERTEX, tx));
88 color_ptr_on(disp, 4, GL_FLOAT, sizeof(ALLEGRO_OGL_BITMAP_VERTEX),
89 (char*)(disp->vertex_cache) + offsetof(ALLEGRO_OGL_BITMAP_VERTEX, r));
90
91 if (!(disp->flags & ALLEGRO_PROGRAMMABLE_PIPELINE))
92 glDisableClientState(GL_NORMAL_ARRAY);
93 }
94
95 glGetError(); /* clear error */
96 glDrawArrays(GL_TRIANGLES, 0, disp->num_cache_vertices);
97
98#ifdef DEBUGMODE
99 {
100 int e = glGetError();
101 if (e) {
102 ALLEGRO_WARN("glDrawArrays failed: %s\n", _al_gl_error_string(e));
103 }
104 }
105#endif
106
107#if !defined ALLEGRO_CFG_OPENGLES && !defined ALLEGRO_MACOSX
108 if (disp->flags & ALLEGRO_PROGRAMMABLE_PIPELINE) {
109 if (o->varlocs.pos_loc >= 0)
110 glDisableVertexAttribArray(o->varlocs.pos_loc);
111 if (o->varlocs.texcoord_loc >= 0)
112 glDisableVertexAttribArray(o->varlocs.texcoord_loc);
113 if (o->varlocs.color_loc >= 0)
114 glDisableVertexAttribArray(o->varlocs.color_loc);
115 glBindBuffer(GL_ARRAY_BUFFER, 0);
116 glBindVertexArray(0);
117 }
118 else
119#endif
120 {
121 vert_ptr_off(disp);
122 tex_ptr_off(disp);
123 color_ptr_off(disp);
124 }
125
126 disp->num_cache_vertices = 0;
127
128 if (disp->flags & ALLEGRO_PROGRAMMABLE_PIPELINE) {
129#ifdef ALLEGRO_CFG_OPENGL_PROGRAMMABLE_PIPELINE
130 if (disp->ogl_extras->varlocs.use_tex_loc >= 0)
131 glUniform1i(disp->ogl_extras->varlocs.use_tex_loc, 0);
132#endif
133 }
134 else {
135 glDisable(GL_TEXTURE_2D);
136 }
137}
All code that deals with VBOs and GL_ARRAY_BUFFER is hidden under ifdefs for desktop OpenGL. I'd like to know if I'm reading things wrong here, or if it's a real problem. I have compiled programs for OpenGL ES2 for mobile devices and they ran just fine. But maybe mobile platforms are more forgiving? Then, I'll need a separate branch specifically from Emscripten? Or one for OpenGL ES2 for all platforms, which will use VBOs?
|
Thomas Fjellstrom
Member #476
June 2000
|
I think its good to be correct in this case. if ES2 is specified to require Buffer Objects, then they should be used when ES2 is being used. If possible, it might make sense to have the ES+Prog == ES2, but that could be my GL noobishness showing. Also anything that helps clean up the GL code is a good thing. -- |
Max Savenkov
Member #4,613
May 2004
|
Hm. I have to wonder. Peter Wang and Trent Gamblin shuffled these defines around in 2012 and since then they went pretty much untouched. The last comment states that "Even if using the programmable pipeline, on iOS and Android the 'else' block should always be executed.". The reason for this, unfortunately, is not provided I think I need Trent or someone with more knowledge than me to understand WHY should be this way, and if it applies to OpenGL ES2/Emscripten too. Anyway, I'm off for the night. I hope someone would pop into this thread to give me an advice. As far as I can see, Allegro is using OpenGL ES 1 code path to draw things even when OpenGL ES 2 is specified, and it only works on Android/iOS because of backward compatibility or something?
|
Elias
Member #358
May 2000
|
OpenGL ES 2 is used with ALLEGRO_PROGRAMMABLE_PIPELINE. That define decides in general whether classic opengl (OpenGL 2.0, ES 1.0) or shaders (OpenGL 3+, ES 2). So in your case, just make sure that flag is always set. -- |
Max Savenkov
Member #4,613
May 2004
|
ALLEGRO_PROGRAMMABLE_PIPELINE is set. But I can see 3 paths in this code instead of two: if (!OPENGLES && !MACOSX) && PROGRAMABLE_PIPELINE { Create & use VBOs } else { // Inside vert_ptr_on: if PROGRAMMABLE_PIPELINE Use shaders, but with Vertex Arrays instead of VBOs? else Use fixed pipeline } The problem is, code path for OpenGL ES with PORGRAMMABLE_PIPELINE seems to be using Vertex Arrays instead of Vertex Buffer Objects. Clarification: OK, now I see it. OpenGL ES 2 support using glVertexAttribPointer without bound VBO, so Allegro is right. But WebGL is a subset of ES2 and it does nnot have that ability, so there we should awlays use VBOs, unless emulation is enabled. I'll try to see if things work with emulation first, and then maybe someday think about creating a special code path for WebGL (OPENGLES@ && EMSCRIPTEN). Edit: with full ES2 emulation enabled, errors are gone, but I still can't get al_draw_bitmap to work, it does not display anything. Off to work, will continue investigation in the evening. ------------------------------------------------------------- Edit 2: Yay me! Bitmap drawing is working. Example updated. Do you find that hypnotic? I do! Just needs some relaxing music! Next on "Screwing around with Emscripten": do I have everything to start running Allegro examples? Probably not, but I'll have to try to do it to see what I'm missing! I had to put a crutch into my code for now: unless I call al_set_target_bitmap( al_get_backbuffer( pDisp ) ); after creating display, default shader is not set for the backbuffer and nothing gets drawn. Here's a question for those in the know. Why do we first set target bitmap, and only THEN create default shader in the following code (a part of create_display)? As far as I can see, al_set_target_bitmap would be happier if we created default shader before calling it. 1 _al_vector_init(&display->bitmaps, sizeof(ALLEGRO_BITMAP*));
2
3 if (settings->settings[ALLEGRO_COMPATIBLE_DISPLAY])
4 al_set_target_bitmap(al_get_backbuffer(display));
5 else {
6 ALLEGRO_DEBUG("ALLEGRO_COMPATIBLE_DISPLAY not set\n");
7 _al_set_current_display_only(display);
8 }
9
10 if (display->flags & ALLEGRO_PROGRAMMABLE_PIPELINE) {
11 display->default_shader = _al_create_default_shader(display->flags);
12 if (!display->default_shader) {
13 al_destroy_display(display);
14 return NULL;
15 }
16 }
17
18 al_identity_transform(&identity);
19 al_use_transform(&identity);
------------------------------------------------------------- Edit 3: Hey! Somebody! Post something, so I could write about progress in a new post! Good news: I got a simple keyboard driver working (it returns key codes in events, but not unichars or key names). To celebrate the fact, here's a port of ex_bitmap to Emscripten. Bad news 1: Unfortunately, I don't see a way to completely abstract away Emscripten from end-user. The problem is, there is simple no way to write things like "while( true ) { // main loop }" in JS. Instead, one must use a callback. This is contrary to Allegro ideology, so I'm afraid here we're gonna let the end-user down... Bad news 2: Emscripten does not have pthreads, so I'll have to write a new implementation for thread functions. Emscripten provides WebWorkers to do that, but they only support threading: no mutexes, no conditional variables, no nothing. So, Emscripten port is never going to be complete in this respect. This might mean some problems for timer functions, but to be honest, I never once have used Allegro timers in my life, and Allegro threads only once, so I'll try to postpone implementation of JS threads for now, and do mouse driver next - it should be easy. What do you think I should try next? I think sound. But sound functions will surely need threads. TTF addon? I know it is possible to compile FreeType with Emscripten, so it's doable.
|
ks
Member #1,086
March 2001
|
An update in a separate post would be appreciated.
|
Elias
Member #358
May 2000
|
Max Savenkov said: The problem is, there is simple no way to write things like "while( true ) { // main loop }" in JS. You could either rely on al_wait_for_event being called by every allegro program and change that to call an update function in the system driver (that would do nothing on other platforms), or just have an explicit al_heart_beat or similar function. About timers, having a way to insert timer events into an event queue certainly would be nice to make most of the examples work. User threads shouldn't be needed except for the few explicit threading examples. -- |
Max Savenkov
Member #4,613
May 2004
|
Elias said: You could either rely on al_wait_for_event being called by every allegro program and change that to call an update function in the system driver (that would do nothing on other platforms), or just have an explicit al_heart_beat or similar function. I could not rely on that, since my own Allegro-based projects never use al_wait_for_event Maybe I should add platform specific al_emscripten_set_frame_callback. Quote: About timers, having a way to insert timer events into an event queue certainly would be nice to make most of the examples work. User threads shouldn't be needed except for the few explicit threading examples. Thing is, it's very easy to have timers in Emscripten. But Allegro timers explicitly rely on threads. I guess I can simply enclose platform-specific code in #ifdefs, though...
|
Elias
Member #358
May 2000
|
Yes, but you could make a timer driver which does not rely on threads. It's just how the existing ones are implemented. Bit nothing in the timer API itself would require a thread. -- |
Max Savenkov
Member #4,613
May 2004
|
As far as I can see, Allegro does not have a timer driver per se, just some general functions, which should be platform-independent, like al_start_timer: 1void al_start_timer(ALLEGRO_TIMER *timer)
2{
3 ASSERT(timer);
4 {
5 size_t new_size;
6
7 if (timer->started)
8 return;
9
10 _al_mutex_lock(&timers_mutex);
11 {
12 ALLEGRO_TIMER **slot;
13
14 timer->started = true;
15 timer->counter = timer->speed_secs;
16
17 slot = _al_vector_alloc_back(&active_timers);
18 *slot = timer;
19
20 new_size = _al_vector_size(&active_timers);
21 }
22 _al_mutex_unlock(&timers_mutex);
23
24 if (new_size == 1) {
25 timer_thread = al_malloc(sizeof(_AL_THREAD));
26 _al_thread_create(timer_thread, timer_thread_proc, NULL);
27 }
28 }
29}
You can see it calls _al_thread_create to create a thread to watch over timers. I could implement _al_thread_create in a certain specific way, but it wouldn't be right. What if I decided later to add a true threading support? And anyway when I create timer in JS I need a platform-specific function which would be called for each timer. I think Allegro timers are dependent on threads in their present state. The only way to provide a set of platform-specific functions now would be to exclude timernu.c from Emscripten build and add my own file, timernu_ems.c, for example, instead. On a brighter note: Next: timers and sound and threads?
|
Elias
Member #358
May 2000
|
I don't see a problem with having a different al_start_thread implementation for emscripten. -- |
Max Savenkov
Member #4,613
May 2004
|
I'll see about al_start_thread later. For now, I wrote special implementation of timer API for Emscripten. Results are... Less than stellar. Accuracy of my timers is very shitty and they seems to experience random slow-downs and speed-ups. Later, I'll try to see if I can do anything about it, but for now, you all can check out ex_timer port. I'm moving on to sound. My goal now is to have at least one demo project functional by the end of the weekend. I have already tried to compile "speed", but it uses some functionality of graphic subsystem which is not yet supported, and so it does not show anything but OpenGL errors in console... By the way, makefile which is provided with speed is broken, because it does not include a4_aux in list of sources I realize there is a CMakeLists.txt there, but then we should either delete or fix provided makefile.
|
Elias
Member #358
May 2000
|
Ah, sorry, I meant al_start_timer. So exactly what you did I guess Not sure why performance is so bad. [edit2:] Actually, not at all sure what those numbers mean, that seems to be some cumulative error as it keeps rising. Still, amazing progress. [edit:] And thanks, I removed the speed makefile. -- |
|
|