Uderzo
Uderzo is a flexible way to add simple OpenGL/NanoVG UIs to Elixir projects. One clear target is Nerves systems.
Currently, Uderzo is being prototyped. Running a demo on Nerves
works. This repository combines two subprojects in "poncho" style: *
uderzo/
, the actual library; * uderzo_demo_nerves/
, a Nerves RPi3
demo (burn it, boot it, and watch graphics animations). Everything is
rough around the edges, but the end-to-end system is there and making
it nicer is pretty much a downhill run.
Why?
Today, all your UIs are Web. I think html/javascript/css is not a very nice environment for developing rich UIs, and I rather stay in Elixir when I'm developing in Elixir as much as possible. Also, when creating small systems like a RaspberryPi with a touchscreen hat, I think it's a bit rich to require a Phoenix server, a Qt browser, and a single page app just to, say, display the weather. Therefore, I wanted something leaner, simpler, and basically more fun than another Web UI. Uderzo is the system that came out, based on NanoVG for 2D graphics. You have a blank canvas and can paint on it with simple 2D primitives (or mix in full OpenGL ES2 calls), and you can choose what you want to run in Elixir, what in C, and what in between (more on that later).
Goals
The prime goal is stability. The GUI is not allowed to crash Erlang in any circumstances. Call me paranoid, but I want to run my house thermostat on this and don't want to come home to frozen pipes because OpenGL crashed ;-). I also think that this is in line with the Erlang philosophy: make it as stable as possible.
The second goal is flexibility. I probably want to stick with Elixir for my UI as much as possible, but if it's not fast enough, I want to be able to move to C. Or something in beween.
The third goal is to have an API that feels like a native Elixir API and stay as faithful to the BEAM/Erlang/Elixir design philosophy as possible. One of the design philosophies is system independence - I want to be able to design a GUI on a full development system, burn it to a Pi, and have it run the same.
Design
Uderzo runs a GraphicsServer
supervisor, which starts a Port to the
uderzo
executable. The executable contains all the graphics code,
and thus can do the silly stuff that makes C programs crash without
affecting the Erlang VM.
Communication is through the stdin/stdout connection - commands are sent out as Erlang tuples, responses are received in the same fashion. All responses go to a pid specified in the corresponding command, and everything is meant to be asynchronous - again, this is closest to how things are supposed to work on the BEAM.
Essentially, that's it. You have a C executable that initializes OpenGL
and NanoVG, then reads a command (using the ei
library), executes it,
and optionally sends a response back.
Clixir
However, that smells like typing a lot of repetitive code. Therefore, the
"glue" code is written in an Elixir subset/dialect that's dubbed Clixir. It's
the magic sauce that makes extending and adapting Uderzo fun. A (graphics) function
in Clixir is specified with defgfx
(the name will likely change, as Clixir is
applicable as a generic safe FFI mechanism). You can find examples in the uderzo
README. A Clixir function will expand into an Elixir function definition with the right
arguments that calls out to the GraphicsServer and a C function that has the body of
the function in equivalent C code wrapped in the code to demarshall arguments and
marshall any responses. Function dispatch is through a gperf
generated hashtable
and therefore extremely fast.
Given that all the boring/hard code is generated, it becomes easy to move graphics code between Elixir, Clixir, and C so you can pick and choose.
Clixir documentation for the latest published version of the library starts here.
Docs
Docs for the latest version of the library can be found here.
Demo
cd uderzo_demo_nerves; mix do deps.get, run
should pop up the NanoVG demo. If you burn the Nerves firmware, it should pop up a (currently worse looking) demo on a Pi3. Note that currently, only Linux has been tested but it should work on MacOS and Windows with little adaptation.
License
To stay compatible with Nerves, this work is licensed under the Apache License. Details can be found in the file LICENSE in this repository.
NanoVG is included in this repository and is under a MIT/BSD style license. Included in NanoVG are some utility routines from the STB collection that have been placed into the public domain.
TODO
See https://github.com/cdegroot/uderzo_poncho/projects/1
Contributing
Submit a pull request, an issue, or hit me up on Slack.