slint のデモを動かす

# はじめに

普段は Qt を使っているのですが、LCD をつけるのが当たり前になってきた組込み CPU にそのまま使えないのが最近不満でした。  
そこを解消するべく slint というツールキットを見つけたので使ってみます。

C++もサポートしていますが、Rust で進めます。

# 開発環境

* 開発ホスト
  * Ubuntu 22.04.1 LTS
  * Visual Studio Code
* ターゲット
  * [RaspberryPi Pico H](https://www.switch-science.com/collections/raspberry-pi/products/8170)
    * ノーマルの Pico でもOK
  * [2.8インチ タッチディスプレイ 320×240](https://www.switch-science.com/products/7331)
    * 解像度 : 320 × 240ピクセル
    * インターフェース : SPI
    * ドライバ : ST7789
    * [本家販売ページ](https://www.waveshare.com/pico-restouch-lcd-2.8.htm)

# Rust の準備

rustup で導入。

```bash
$ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
```

組込みクロス開発向けの下準備。
```bash
## nightly を使えるようにしておきます
$ rustup toolchain install nightly --allow-downgrade
## RaspberryPiPico をターゲットにできるようにしておきます
$ rustup target add thumbv6m-none-eabi
$ rustup +nightly target add thumbv6m-none-eabi
```

環境はこんな感じ
```bash
$ rustup show
Default host: x86_64-unknown-linux-gnu
rustup home:  /home/tkhshmsy/.rustup

installed toolchains
--------------------

stable-x86_64-unknown-linux-gnu (default)
nightly-x86_64-unknown-linux-gnu

installed targets for active toolchain
--------------------------------------

thumbv6m-none-eabi
x86_64-unknown-linux-gnu

active toolchain
----------------

stable-x86_64-unknown-linux-gnu (default)
rustc 1.65.0 (897e37553 2022-11-02)
```

# Slint のデモを動かす

Slint 公式
* https://slint-ui.com/
* https://github.com/slint-ui/slint

## Slint の準備

ここを参考に下準備。  
* https://github.com/slint-ui/slint/blob/master/docs/building.md

```bash
$ sudo apt install libfontconfig-dev libxcb-shape0-dev libxcb-xfixes0-dev libxkbcommon-dev libglu1-mesa-dev libudev-dev
```

slint-ui/slint を DL してテストをやっておきます。

```bash
## DL してリリース固定
$ git clone https://github.com/slint-ui/slint.git
$ cd slint
$ git checkout release/0.3
## Build
$ cargo build
## Test
$ cargo test
```

## printerdemo on Ubuntu/Linux

ではドキュメントに沿ってサンプルコードを動かしていきましょう。  
まずはデスクトップで普通に動かします。
* https://github.com/slint-ui/slint/tree/master/examples/printerdemo

```bash
$ cargo run --release --bin printerdemo
```

./target/release/ 以下に実行ファイルができています。

![printerdemo-desktop.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/432395/a777660b-2d5e-8fe7-04b1-07fd2ea846cb.png)


## printerdemo_mcu on simulator

printerdemo を MCU 向けに修正したものが printerdemo_mcu ですね。  
まずはシミュレータ動作させてみましょう。
* https://github.com/slint-ui/slint/tree/master/examples/printerdemo_mcu
* https://github.com/slint-ui/slint/tree/master/examples/mcu-board-support#the-simulator

```bash
$ cargo run -p printerdemo_mcu --features=simulator --release
```

ビルドがずっこけました。OpenGLContextが見えてない？  
```bash
error[E0433]: failed to resolve: could not find `OpenGLContext` in the crate root
  --> internal/backends/winit/renderer/sw.rs:22:37
   |
22 |         let opengl_context = crate::OpenGLContext::new_context(window_builder);
   |                                     ^^^^^^^^^^^^^ could not find `OpenGLContext` in the crate root

error[E0412]: cannot find type `OpenGLContext` in the crate root
   --> internal/backends/winit/renderer/sw.rs:106:28
    |
106 |     opengl_context: crate::OpenGLContext,
    |                            ^^^^^^^^^^^^^ not found in the crate root
```

とりあえず応急的に修正します(設定の問題ぽいのであとでちゃんと治そう)。
```diff
--- a/internal/backends/winit/lib.rs
+++ b/internal/backends/winit/lib.rs
@@ -13,9 +13,9 @@
 
 mod glwindow;
 use glwindow::*;
-#[cfg(any(feature = "renderer-winit-femtovg", skia_backend_opengl))]
+//#[cfg(any(feature = "renderer-winit-femtovg", skia_backend_opengl))]
 mod glcontext;
-#[cfg(any(feature = "renderer-winit-femtovg", skia_backend_opengl))]
+//#[cfg(any(feature = "renderer-winit-femtovg", skia_backend_opengl))]
 use glcontext::*;
 pub(crate) mod event_loop;
 mod renderer {
```

無事動きました。

![printerdemo_mcu-simulator.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/432395/1dc15803-d0f5-5718-ce33-499e620ff5b4.png)

## printerdemo_mcu on RaspberryPiPico

では本番。  
armv6 向けにビルドして、RaspberryPiPico 上で動作させます。
* https://github.com/slint-ui/slint/tree/master/examples/mcu-board-support#on-the-raspberry-pi-pico

```bash
## ビルド
$ cargo +nightly build -p printerdemo_mcu --no-default-features --features=mcu-board-support/pico-st7789 --target=thumbv6m-none-eabi --release

## BOOTSEL を押しながら Pico を USB 接続するとマウントされる
## できてないなら以下でマウント実行
$ udisksctl mount -b /dev/sda1

## uploader をインストール
$ cargo install elf2uf2-rs
## upload 実行
$ elf2uf2-rs -d target/thumbv6m-none-eabi/release/printerdemo_mcu
```

I got it !  めっちゃ速い！
タッチパネルもちゃんと反応します。動きは[公式の動画](https://www.youtube.com/watch?v=dkBwNocItGs)をどうぞ

![printerdemo_mcu-pico.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/432395/3b891c9d-fb3b-bb73-2acf-563e253b8c84.png)