With the release of Android 2.3, there’s a decent way to integrate native applications with the NativeActivity class, an EGL library, and some C API to expose events, main loop, etc. So? how about porting Clutter to it now that it looks actually feasible? After a few days of work, the first results are there, quite promising!
There’s still a fairly large number of items in my TODO before being happy with the state of this work, the most prominent items are:
- Get a clean up pass done to have something upstreamable, this includes finishing the event integration (it receives events but not yet forward them to Clutter),
- Come up with a plan to manage the application life cycle and handle the case when Android destroys the EGL surface that you were using (probably by having the app save a state, and properly tear down Clutter).,
- While you probably have the droid font installed in /system/fonts, this is not part of the advertised NDK interface. The safest choice is to embed the font you want to use with your application. Unfortunately fontconfig + freetype + pango + compressed assets in your Android package don’t work really well together. Maybe solve it at the Pango level with a custom “direct” fontmap implementation that would let you register fonts from files easily?
- What to do with text entries? show soft keyboard? Mx or Clutter problem? what happens to the GL surface in that case?
- Better test the GMainLoop/ALooper main loop integration (esp. adding and removing file descriptors),
- All the libraries that Clutter depends on are linked into a big .so (which is the Android NDK application). It results in a big .so (~5 MB, ~1.7 MB compressed in the .apk). That size can be dramatically reduced, sometimes at the expense of changes that will break the current API/ABI, but hell, you’ll be statically linking anyway,
- Provide “prebuilt libraries”, ie. pre-compiled libraries that makes it easy to just use Clutter to build applications.
When doing something with graphics, your first need an idea (granted, as with pretty much everything else). In this case, a simple transition that I’ve seen somewhere a long time ago and I wanted to reproduce with Clutter.
The code is available in a branch of a media explorer I’m currently working on. A few bullet points to follow the code:
- As the effect needs a “screenshot” of a Clutter scene to play with. You first need to create a subclass of
ClutterOffscreenEffect as it does the work of redirecting the painting of a subtree of actors in an offscreen buffer that you can reuse to texture the rectangles you’ll be animating in the effect. This subclass has a “progress” property to control the animation.
- Then actually compute the coordinates of the grid cells both in screen space and in texture space. To be able to use
cogl_rectangles_with_texture_coords(), to try limit the number of GL calls (and/or by the Cogl journal and to ease the animation of the cells fading out, I decided to store the diagonals of the rectangle in a 1D array so that the following grid:
is stored as:
::paint_target()looks at the “progress” property, animate those grid cells accordingly and draw them.
priv->rects is the array storing the initial rectangles,
priv->animated_rects the animated ones and
priv->chunks stores the start and duration of each diagonal animation along with a (index, length) tuple that references the diagonal rectangles in priv->rects and priv->animated_rects.
Some more details:
- in the
::paint_target() function, you can special case when the progress is 0.0 (paint the whole FBO instead of the textured grid) and 1.0 (don’t do anything),
- Clutter does not currently allow to just rerun the effect when you animate a property of an offscreen effect for instance. This means that when animating the “progress” property on the effect, it queues a redraw on the actor that end up in the offscreen to trigger the effect
::paint_target() again. A branch from Neil allows to queue a “rerun” on the effect to avoid having to do that,
- The code has some limitations right now (ie, n_colums must be equal to n_rows) but easily fixable. Once done, it makes sense to try to push the effect to Mx.
Two weeks ago I attended the first GStreamer conference, and it was great. I won’t talk about the 1.0 plan that seems to take shape and looks really good but just what stroke me the most: Happy Clutter Stories and an Tale To Be Told to your manager.
Let’s move on the Clutter stories. You had a surprising number of people mixing GStreamer and Clutter, two talks especially:
- Florent Thiery founder of Ubicast talked about one of their products: a portable recording system with quite a bit of bling (records the slides, movement detection with OpenCV, RoI, …). The system was used to record the talks on the main track. Now, what was of particular interest for me is that the UI to control the system is entirely written with Clutter and python. They have built a whole toolkit on top of Clutter, in python, called candies/touchwizard and written their UI with it, cooool.
- A very impressive talk from the Tanberg (now Cisco) guys about their Movi software, video conferencing at its finest. It uses GStreamer extensively and Clutter for its UI (on Windows!). They said that about 150,000 copies of Movi are deployed in the wild. Patches from Ole André Vadla Ravnås and Haakon Sporsheim have been flowing to Clutter and Clutter-gst (win32 support).
As a side note, Fluendo talked about their Open Source, Intel founded, GStreamer codecs for Intel CE3100/CE4100. This platform specificities are supported natively by Clutter (./configure –with-flavour=cex100) using the native EGL winsys called “GDL” and evdev events coming from the kernel. More on this later :p
A very interesting point about those success stories is that the companies and engineers working with open source software to build their applications, sometimes with parts heavily covered by patents, while contributing back to the ecosystem that allowed to build those applications in the first place. Contributing is done at many levels: directly patches but also feedback on the libraries/platform (eg. input for GStreamer 1.0). And guess what? It works! To me, that’s exactly how the GNOME platform should be used to build proprietary applications: build on top and contribute back to consolidate the libraries. I’d go as far as saying that contributing upstream is the best way to share code inside the same big corporation. Such companies are always very bad a cooperating between divisions.