はじめに
Rustによる軽量GUIフレームワーク「スリント」のアドベントカレンダーもあと1週間ですね。カレンダーは予定の上では全て埋まったので、このまま頑張りましょう。
昨日は @task_jpさんによる「Slint にバグ報告をしてみました」でした。unit付きなので可読性は高いのですが、不具合でハマるケースはありそうですよね。そういえば演算子の優先順位とかどこかに定義あるのかな。そのうち調べないとなりませんね。
本日のお題
21日早朝(というか今夜深夜から)お出かけ予定が入ってしまったので、さっくり短めの記事ということで、Slintのバックグラウンドとレンダラー周りを紹介しておきます。
Slintの舞台裏
SlintはRustで書かれたGUIフレームワークです。Windows, Linux, macOS, Android, Zephyr, RedoxなどのOSの他ベアメタルでの動作も確認されています。
各種OSによりウィンドシステムなどが異なるため、それらとのやり取りをカプセル化するモジュールが必要です。それがバックエンドと呼ばれるものです。
バックエンドには主に以下の2つの役割が含まれます。
プラットフォームバックエンド
入力イベント(キーボード、マウス、タッチパネルなど)を処理するためプラットフォームに対応したモジュール。
組込バックエンドとしては以下のものが提供されています。
- android-activity
- linuxKms
- Qt
- winit
android-activity
android-activityはAndroidで利用する時に利用するクレートです。
「AndroidでSlintを動かそう」で実際に動かすところまで試しているのでそちらを参考にしてみてください。
linuxKms
Linux上でWaylandやX11などのウィンドウシステムを利用しない場合のためのバックエンドです。以下のライブラリとインターフェイスを使用して、画面に直接レンダリングし、タッチ、マウス、キーボード入力に反応します。
- kernelのKMS/DRI 経由でのOpenGL描画
- Vulkan KHR Display Extensionを使った描画
- ソフトウェアレンダリング用のDRMダムバッファ
- libinput/lubudevを使った入力イベント処理
- libseatを使った一般ユーザーアクセス(option)
このため、以下のようなパッケージ・開発パッケージが必要となります。
- gbm, libgbm-dev
- xkbcommon, libxkbdcommon-dev
- libudev, libudev-dev
- libseat, libseat-dev
レンダラーと合わせて以下のような設定が可能です。
- linuxkms-femtovg
- linuxkms-skia-opengl
- linuxkms-skia-vulkan
- linuxkms-skia-software
- linuxkms-software
Qt
Qtは、クロスプラットフォーム向けのアプリケーションフレームワークです。ウィンドウシステムの統合、レンダリング、ネイティブウィジェットのスタイル周りが使用されます。
Qtバックエンドは、macOS、Windows、Wayland と X11 を備えた Linux など、関連するオペレーティングシステムとウィンドウシステムのほとんどすべてをサポートし、KMSまたは独自のドライバを介した直接フルスクリーンレンダリングもサポートしています。現状、QtバックエンドはQtレンダラーとセットでの利用となりますが、現状はソフトウェアレンダリングのみ提供しています。
残念ですが、現状ではOSネイティブな見た目のウィジェットのためにはQtが必要になります。
コンパイル時に、qttypeクレートを使ってインストール状態が確認されます。Qtを使うつもりがないのにQtが選択されてしまう、Qtラブラリがないと怒られるといった状態になっている人は、以下の環境変数を設定しておいてください。
export SLINT_NO_QT=1
Qt backendを使う場合はQt 5.15以上のインストールが必要です。
winit
winitバックエンドは、winitクレートを使ってウィンドウシステムとやりとりをします。macOS、Windows、Wayland および X11 を搭載したLinuxなど、関連するほぼすべてのオペレーティングシステムとウィンドウシステムをサポートしています。
レンダラーと合わせて以下のような選択が可能です。
- winit-femtovg
- winit-skia
- winit-skia-software
- winit-skia-opengl
- winit-software
レンダラーを明示的に選択しない場合、バックエンドは、コンパイル時に有効ならskia レンダラーの使用を試みます。skiaはOpenGL, Metal, Direct3D, softwareのどれかを内部的に利用してレンダリングします。これが失敗した場合は、FemtoVG レンダラーにフォールバックし、これも失敗した場合は、ソフトウェアレンダラーを使用します。
なお、winitを選択した場合は以下の環境変数を使うことでフルスクリーンモードでウィンドウを起動できます。
export SLINT_FULLSCREEN=1
バックエンドの選択
バックエンドは、以下の順序選択します。
- 開発者自身でバックエンドを用意してプログラムで設定する
- 設定されていなければ、SLINT_BACKEND環境変数で決定する
- 設定されていなければ、バックエンドの優先順位に従い決定する
環境変数は、以下のようにバックエンドとレンダラーの組み合わせで指定します。
export SLINT_BACKEND=winit-software
export SLINT_BACKEND=linuxkms-skia
例えばlinuxではインストールされていれば最優先はQtで、それ以外はwinit, linuxKmsと言ったようにある程度優先順位があります。
レンダラー
レンダラーは、Slintのエレメントをピクセルに変換するためのモジュールです。バックエンドとの組み合わせがいくつかあり、アプリケーションコンパイル時に選択ルールに従って決定されます。
レンダラーには現状以下のものがあります。
- Qt
- software
- FemotoVG
- Skia
Qtレンダラー
QtレンダラーはQtバックエンド付属のもので、QPainterを利用してレンダリングを実装しています。ソフトウェアレンダリングのみとなっています。
ソフトウェアレンダラー
winitで、マイコン向けの軽量なレンダラーです。以下のような特徴があります。
- GPUアクセラレーションなし
- 部分的なレンダリングをサポート
- (Rustのみ)行単位のレンダリングをサポート(メモリが不足する環境向け)
- テキストレンダリングの漢字サポートはまだない?
- マイクロコントローラ向け
- 一部機能が未実装
- Pathがサポートできていない
- スムーズな回転やスケーリングがない
- drop-shadowに未対応
- border-radiusでclipすることができません
- 円形グラデーションがありません
- テキストのストローク・アウトラインがありません
FemtoVG レンダラー
- OpenGLによるGPUアクセラレーション必須
- テキストとパスのレンダリング品質が不十分な場合があります
Skia レンダラー
- OpenGL, Metal, Vulkan, Direct3Dによる高度なGPUアクセラレーション
- ディスクフットプリントが大きめ
組込バックエンドを使わない
ちなみに、もう一つの選択肢として、自力でバックエンドを用意するという方法もあります。マイコン上のベアメタルで動かす場合は、余計なクレート入れるといっぱいになってしまうので自前用意が必須なばあいもあります。
こちらについては、以前書いたPico2用のバックエンドを整理しつつ説明を書こうとしていたのですが、あと1時間ほどで家を出なくてはならなくて何も準備していないという状況なので諦めました。ごめんなさい、今後の課題にさせてください。
まとめ
時間があまりないので、かなり浅い記事になってしまいましたが、現状Slintが提供しているバックエンドやレンダラーの解説でした。
デスクトップ向けであれば現状ではQtを、Qtを外すならSkiaを、GPUありだけどフットプリントは小さくというのであればFemotVGを、GPUなしのロースペックハードウェアの場合はソフトウェアレンダラーを利用するという感じでしょうか。
物によってはまだ不足している部分もありますし、一長一短があるので、開発するソフトウェア、実行環境にあったバックエンドとレンダラーを採用する必要がありそうです。
中途半端な説明記事でもうしわけありませんが、明日は@task_jpさんが何か書いてくださるそうなので、そちらを期待してお待ちください。