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.

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.

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.

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.

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:

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.

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?

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?

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.

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.

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.

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.

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...

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:I have mouse driver now. Enjoy a ex_mouse port to Emscripten It's not perfect. I haven't yet found a way to prevent middle mouse button to start scrolling, for example. And of course it does not support setting cursor position. But the basic mouse support is here.

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.