Native GUI application with SWT and Skija on Raspberry Pi


To create a Java GUI with native look and feel at native performance, SWT(Standard Widget Toolkit) is a good choice. With Skija, it got even more powerful. And finally it’s able to create a real native application with the help of the GraalVM native image.

SWT and Skija

For some applications, standard widgets is enough. Though if you want draw some fancy graphics, the 2D graphics in SWT is not powerful enough. Java 2D is quite powerful, but it can’t be used on SWT directly. You have to use off screen buffer then copy data around, it’s often slow and use more memory. Using Skia in SWT is much easier with Skija, which is the Java binding for Skia.

To use Skija in SWT, simply create a GLCanvas.

GLData data = new GLData();
data.doubleBuffer = true;

GLCanvas glCanvas = new GLCanvas(shell, SWT.NO_BACKGROUND | SWT.NO_REDRAW_RESIZE, data);
glCanvas.setCurrent();
DirectContext context = DirectContext.makeGL();

After that you can you can create Surface and canvas

Rectangle rect = glCanvas.getClientArea();
BackendRenderTarget renderTarget = BackendRenderTarget.makeGL(rect.width, rect.height, /*samples*/0, /*stencil*/8, 0, FramebufferFormat.GR_GL_RGBA8);
Surface surface = Surface.makeFromBackendRenderTarget(context, renderTarget, SurfaceOrigin.BOTTOM_LEFT, SurfaceColorFormat.RGBA_8888, ColorSpace.getDisplayP3());
Canvas canvas = surface.getCanvas();
canvas.clear(0xFFFFFFFF);
context.flush();
glCanvas.swapBuffers();

Screenshots

With Skia and GraalVM, you can do lots of things, for example:

  1. A Flash render using Skia, and a ActionScript VM on top of GraalVM.
  2. Port SWT itself to OpenGL, make it possible to write GUI for mobile, or run Eclipse without X11.

This example only demonstrate how to render SVG and play Lottie animation.

SVG on Windows 7 32
Lottie on Raspberry Pi OS 64

Native Image

Build a native iamge is very simple, for example, this is how you run java application:

java -jar aaa.jar
And to build the native image:
native-image -jar aaa.jar

Things will get bit complicate if you use reflection in java or jni. luckily, you can use GraalVM tracing agent to simplify the configuration.

Source code and binary

Source and binary for Raspberry Pi OS 64. To build source, you need:

  1. SWT 4.18 for AArch64, SWT 4.9 is the latest for Win32.
  2. GraalVM Community Edition, 20.3 or 21.0 would be fine.
  3. Skija for aarch64 or Win32, other platform
./build.sh
./run -trace
./build -native

To run the demo, you need install these packages:

sudo apt install libharfbuzz-icu0 libpng16-16 libjpeg62-turbo libexpat1 libwebpmux3 libwebpdemux2 libicu63

And the memory footprint of Java vs Native:

Java
Native

Conclusion

GraalVM native image still has long way to go, but SWT, Skija and GraalVM is great combination for build native GUI application.