GNU Emacs 32の開発版に取り込まれたCanvasは、Emacsのバッファ内へARGB32形式の画素を表示する画像形式である。 ARGB32は1画素を32ビットで表す画素形式で、アルファ・赤・緑・青の4チャンネルをそれぞれ8ビットずつ持つ。 アルファチャンネルによって透過度を扱えるため、背景と合成しながらの描画に向いている。 HTML Canvasのような描画命令の集合ではなく、既存の画像APIから扱える画素バッファを提供する。 そのため、Canvasもほかの画像と同じように、テキストやオーバーレイのdisplayプロパティへ画像仕様を設定して表示できる。
従来の画像を動かし続けるには、画像データを文字列などのEmacs Lispオブジェクトとして繰り返し作り直す必要があり、複雑な画像や高い更新頻度では処理とガベージコレクションの負担が増える。 Canvasでは、Emacs Lispから画素のベクターまたはユニバイト文字列を渡せるだけでなく、動的モジュールがcanvas_data APIを通じて画素バッファを直接変更できる。 描画計算をCなどのモジュール側で行えば、大量の画像データをEmacs Lispへ受け渡さずに済む。
PBMのように画素データをそのまま渡せる画像形式はCanvas以前からある。違いは画素データを扱えるかどうかではなく、更新の経路にある。 既存の画像は画像仕様(image spec)というLispオブジェクトに紐づけて画像キャッシュへデコード結果を保持するため、更新のたびに新しい仕様や画素データをLispの値として用意し直す必要があり、キャッシュも作り直しになる。 Canvasでは動的モジュールがcanvas_data APIを通じて既存の画素バッファの実体を直接書き換えるため、新しいLispオブジェクトを用意する手順もキャッシュの作り直しも発生しない。
更新にはcanvas-refreshを使う。 これは通常のredisplayのように変更されたすべてのグリフを調べ直すのではなく、そのCanvasを表示しているグリフだけを描き直す。 フレームの二重バッファリングが有効な場合は、画面へ反映するためにredisplayも必要になるが、Canvas自体の更新範囲は限定されたままである。
CanvasそのものがGPUによる描画を提供するわけではない。 しかし、外部でGPUを使って画素を計算し、その結果を同じバッファへ書き込む構成は取れる。 記事ではEmacs Lispによる跳ねる球と二重振り子、Cの動的モジュールによる回転する三次元点群を例に、既存のバッファ操作と高頻度な画像更新を共存させられることを示している。
https://monadicsheep.org/blog/an-introduction-to-canvas-in-emacs.html