Hey everyone, crazy rambling warning!
Some time ago I made an attempt to make a NaCl backend for SDL2, based on
the SDL 1.2 port which you can see here:
My initial attempt is here:
It “sort of” works, I could make the testsprite test run inside Chrome, but
it’s dead slow.
that mostly everything runs in a single thread, and that operations are
eminently non blocking (you issue a request, which returns immediately, and
then you get a callback with the results). You can spin threads, but to
spice things up (pun intended), you can’t call the Pepper API (the glue to
the browser) from these threads. So, no OpenGL calls from outside the main
The strategy for the SDL 1.2 is to spin up a worker thread where the SDL
app lives and works as if it were a regular desktop app, they get away with
it because they do all drawing in a 2D image buffer which then they flush
via the main thread onto the “screen”. This is not an option for SDL2, if
we want to take advantage of the OpenGL ES 2 backend.
My current solution is to make a SDL GLES2 renderer wrapper which
basically blocks itself on every call and waits for the main thread to
execute the real GLES2 renderer calls. It works, but it’s too slow for any
practical use due to technical reasons with the way Native Client is
implemented. The solution they gave me on the Native Client list was to
make a queue of functions, which should be much faster, and execute them on
the screen refresh call back (which always runs on the main thread).
This approach has a speed advantage, and a big disadvantage…you can for
example call SDL_RenderCopy with a texture, then destroy it, and by the
time the queued function will actually run in the main thread, the texture
may be gone. I think there’s a way around such cases which is on functions
such as those that destroy textures or that need to get something out of
the renderer (lock the texture for example), make those functions block
themselves until the renderer instruction queue is flushed…what other
problems that may bring, who knows.
There’s another alternative, and that is to ask the user to run the app in
a fashion similar to the GameCenter integration for iOS that Sam made,
where you don’t have an endless loop in your app, but rather answer to
callbacks. There’s drawbacks here as well, for example, we will not be able
to use SDL_RWops as they exist now in this case, because they operate under
the assumption of blocking I/O, which we can’t do on the main thread (it
doesn’t look really pretty on a worker thread either, but at least the
browser won’t offer to close your hanged app).
Finally, in the case of doing an instruction queue, I’m interested in
alternatives on how to implement that, considering we need to pass the
function pointer (or an enum indicating which function we are calling), and
a variable number of parameters with a variable number of types.
Any feedback is appreciated.