Uderzo - drawing pretty pictures with Elixir

I’ve been toying for the past couple of weeks on Uderzo, which is my attempt to give Elixir a fresh new UI. I’m posting here with an extremely early release to get some hopefully extremely honest feedback ;-).

Design:

  • NanoVG is linked in to do the hard work of rendering 2D on OpenGL (not having OpenGL as the basis for a UI in 2018 is silly).
  • Currently targets OpenGL ES 3, which I hope will work on an RPi3 with a cheap GPIO TFT (to be done, of course), but that’s just a bunch of #defines and a bit of setup code. Also, I’m focusing on Linux, my development and target platform. Getting it to run on MacOS should be trivial though.
  • The graphics code runs in a separate executable connected through a stdio port; messages are exchanged that way through a genserver that monitors and if necessary restarts the executable.
  • DRY means that both the Elixir and the C side of the code come from a single source file written in what I named Clixir but is just a macro that generates C as a side effect (see the test for how it looks like).
  • The idea is to have the whole render loop, etcetera, in Elixir and have the C code be stupid. However, given that Clixir makes where you place the interface very fluid, you can tweak as you go. Currently, there are very low level methods (direct invocations of GLFW), mid-level methods (a call that also does some other setup), and a very high level method (“run the NanoVG demo”).
  • No callback functions, no synchronous methods, @joeerl - just messages to processes ;-). The entire protocol is async and just relies on sending completion messages and responses to passed-in pids.

Currently an extremely early proof of concept which just opens the NanoVG Demo, but I’ll be adding keyboard and mouse support (so that you can actually close the window ;-)) and will slowly pick the NanoVG demo apart fo add more low-level methods. My first milestone would be to have basic widgets in Clixir, ideally I’d also have all of NanoVG and later OpenGL in there but that’s Actual Work™. Ideally, it’d be low-level enough that I can replicate some of Morphic but that’s the Big Hairy Audacious Goal - in the short term I’d be delighted if it can run on a small touchscreen to show my room thermostat controls. The demo runs at around 200fps on Mesa on a 2011 Macbook Pro, so I have good hopes that the speed will be “good enough”.

(Also, I know that @boydm demo’d an early version of an OpenGL based Elixir UI last year. And there’s probably more prior art. I built this partly because Boyd hasn’t released anything yet, partly to see how far I could take Elixir macros, and partly to just get some lightweight skills in GUI stuff, as that bit is rapidly getting rusty since people introduced this “HTML” thing and proper GUI programming isn’t done that much anymore).

Feel free to let me know what you think. And of course, if you’re itching ping me here or on Slack or on Github with PRs :wink:

Thanks for your attention and (maybe) feedback!

(addition: Clixir is entirely generic, so once the project is a bit more complete I’m planning to make it separately available, it should make safely pulling in C libraries a breeze)

18 Likes

Hey - That’s awesome!

I’ll check it out over the weekend.

I’m still working on mine. It went and got kinda big. Hoping to have it in a showable state soonish. Maybe a month or so. Definitely at ElixirConf this year.

Reach out if you want some tips regarding getting it up on the Mac. Not so easy. Although that depends on how you build the C code.

9 Likes

Cool project! I’m looking forward to see what will come out of this. I’d love to see a nice UI lib for Elixir. I’ve been prototyping a Wx based React-style UI lib myself. I didn’t spend much time on it, but I hope to get back to this soon.

3 Likes

Thanks, but even though my hardware has Apple logos on it, I run Linux on it these days ;-).

My main target at the moment is Nerves - I’d like to have something small and simple that people can eventually mix in their Nerves project to put kiosk-style UIs on these little nifty TFT displays that, I noticed, are dirt cheap on Aliexpress. The idea is to render to the OpenGL framebuffer on the SoC and have a second utility copy that to the TFT’s SPI bus 20-30 times a second. That’s the practical side of things, as I’m building a Nerves thermostat for my house. As such, I’m gonna try to make it sweet and simple and focused towards just that.

And yes, I’m very much looking forward to the results of your project. One of my backburner ideas it so see how far I can take the concept of “the BEAM is actually an OS”, and a good graphics lib is missing. I’d like to write an IDE in Elixir, and I’m putting the bar very high given that I’m at heart a Smalltalker :wink: (one of the “conditios sine qua non” is that you can dig very deep in the stack without leavling the language, making things possible like modding the IDE, reusing bits of it, etcetera; in Squeak Smalltalk with a bitmap-based UI that went very low, all the way down from editor logic through UI widgets to bitblt).

3 Likes

Thanks :slight_smile:

The problem with Wx (and other efforts, why not Electron?) is that you firmly step out of the Elixir programming model. Which is a shame, so one of the main goals (if not the main goal) is to stay as close to BEAM idioms as possible. Here’s the render loop of my demo, for example:

defp render_loop(window, t_start, frame_counter \\ 0) do
    if rem(frame_counter, 100) == 0 do
      Logger.info("frame #{frame_counter}")
    end
    uderzo_start_frame(window, self())
    receive do
      {:uderzo_start_frame_result, mx, my, win_width, win_height} ->
        t = timestamp - t_start
        demo_render(mx * 1.0, my * 1.0, win_width * 1.0, win_height * 1.0, t)
        uderzo_end_frame(window, self())
        receive do
          :uderzo_end_frame_done ->
            render_loop(window, t_start, frame_counter + 1)
        end
    end
  end

All calls to the library are async (the uderzo_... and demo_render calls are Clixir functions) and if you want to turn it into sync, you pass in a process that receives a message on completion; note that demo_render doesn’t bother, as there’s nothing to synchronize on. I’ve used Wx in Elixir but it felt painful; also, a secondary goal is to make a truly native UI where you can change the look and feel of the widgets from Elixir (or, in my case, probably sometimes from Clixir - my next steps are to figure out a sweet spot for what goes where).

2 Likes

My goal is to bring component-based UI development experience to desktop. Similar to what Google is doing with Flutter and Dart. Wx is a nice starting point, since there are Erlang bindings for Wx, so you get cross-platform widgets for free. But with the framework in place, more components can be added and I’ve been thinking about adapting your and Boyd’s work so that one can use OpenGL based components. The second goal is to make the apps use little resources, as opposed to Electron.

Not sure which part of Wx you don’t like, since the bindings are done in the spirit of BEAM:

See the docs.

Disclaimer: all of this is in the ideation phase right now.

1 Like

From the docs you pointed at:

NOTE: Currently no form of inheritance is implemented.

I guess that’s my gripe, that wx is very OO heavy.

I must say, even in OO land I wasn’t a fan. I wrote a large-ish GUI using wx in Squeak (long story, but “native UI” was on the customer’s must have list so I set out to write wx bindings) and although there the inheritance paradigms between Wx and Smalltalk matched well, it felt a bit unnatural. There was also the whole threading and locking thing in Wx which kept giving headaches.

As a cross-platform UI it’s all in all not bad, but it’s 2018 and I think we should be moving to OpenGL and I think that native-from-scratch is going to result in a nicer developer interface.

Also, I don’t want a big and complex library like Wx running in the VM that runs my home’s thermostat; the C executable that Clixir generates is very trigger-happy to exit so any hiccup will result in a clean restart of things. I’ve managed to lock up a BEAM VM often enough with Wx, don’t want to come home to frozen pipes because of that :wink:

3 Likes

I’ve finished my end-to-end demo, which includes a Nerves project that boots into the NanoVG demo. So I pulled out the code from my monorepo to make it easier for others to kick the tires: https://github.com/cdegroot/uderzo_poncho

It’s still a bit rough around the edges, but it should work. Coming weeks will be spent on cleanups and similar housekeeping jobs :slight_smile:

5 Likes

Big cleanup has been done. I extracted the Clixir bits from Uderzo, meaning you can now use it
as a simple/safe FFI mechanism, and also the demo code from Uderzo so that both Clixir and
Uderzo are now stand-alone libraries.

Just in case people want to hang-out/ask questions, I’m lurking in #uderzo_clixir on Slack.

3 Likes

And another update: I just “achieved” the milestone where Uderzo will happily show up on a cheapo HAT TFT/Touchscreen display. Bad picture for “evidence”:

image

(why so bad? Because the Pi+display is in my home office, with a webcam pointed at it, while I’m hacking-from-couch downstairs ;-)).

Pending a final Nerves image burn (which “should just work”), this completes the core functionality of Uderzo. The HAT support is currently transparent and automatic - if a /dev/fb1 exists, every frame will be copied to it.

5 Likes

@cdegroot I’m not sure if you can still edit the original post but it would be nice to update the library link from https://github.com/cdegroot/palapa/tree/master/apps/uderzo to https://github.com/cdegroot/uderzo_poncho

1 Like

…done :slight_smile:

3 Likes

I’m just gonna keep this topic warm until people tell me to STFU ;-).

I’m slowly adding some abstractions, so that ~100 lines of Elixir code with 10 lines of Clixir produce this:

4 Likes

Nice - reminds me of the Asteroids game :023:

Tempting :slight_smile:

1 Like

Do it! :003:

A quick write-up about where I think Uderzo and Scenic stand: http://evrl.com/programming/elixir/2018/07/08/uderzo-vs-scenic.html

4 Likes

Cees did a very good writeup on Uderzo and Scenic. He is totally right that Uderzo is more of what I think of as an “Immediate Mode” library and should be great at solving a different set of problems than I was focused on.

For example, there are some people trying to make games in Scenic, and I really don’t know how that is going to go. Scenic purposefully removes a layer of control and adds some potential latency in order to gain lower power usage. Uderzo has a more do-it-now approach that might end up being better for that type of work.

Of course there is overlap, but that hardly matters. I want to encourage him to keep on with Uderzo and think it is an exciting project.

7 Likes