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.
There's a bunch of projects in here and some of them need quite a lot
of dependencies installed. Start at this directory's Makefile
for
a roadmap. The rest of the readme has some background info, this is
a quick list of elixir projects included here:
clixir
- a way to safely and easily integrate C codeclixir_example
- make C code print hello, world.uderzo
- a 2D vector graphics library for Elixiruderzo_example
- a simple example of an uderzo-based displayuderzo_demo_nerves
- use Nerves to make the example run on an RPi3 using VideoCore
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).
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.
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.
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 for the latest version of the library can be found here.
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 and Mac OS X have been tested but it should work on Windows with little adaptation.
cd uderzo_example; mix run -e Uderzo.Demo.run --no-halt
This should pop up a window showing fake temperature readings.
Ensure you are running a supported Elixir version. Uderzo has been tested with
Elixir 1.6.5 and Erlang 20.2. Install them by first installing
asdf. Then run asdf install
Assuming you're running X11 then installing the following packages should work:
sudo pacman -S gperf glfw-x11 glew
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.
See https://github.com/cdegroot/uderzo_poncho/projects/1
Submit a pull request, an issue, or hit me up on Slack.