昨日はGtk#バージョンで上手いこと描画に起因する遅延を解決できた話を書いた。Gtk#で出来たのだから、Xwtで出来てもいいはずだ。しかしそうは簡単にはいかなかった。
まずXwtにはダブルバッファリングのための機能、昨日書いたところで言えばGdkWindowにおけるBeginPaintRect()/EndPaintRect()に相当するAPIが存在しない。仕方ないので、バックエンド側にそのような機能を追加しなければなるまいと思って、Xwt.BackendのAPIを眺め始め、ほどなく、backendのAPIを理解してダブルバッファリング処理に相当するAPIをXwtに追加してGtk/WPF/Cocoaで実装するというのは遠大な作業になりそうだ…と思い始めたところで、Gtk#のOnExposeEvent()を呼び出している部分の全ての前後にBeginPaintRect()/EndPaintRect()を追加した方が早いんじゃないか、と気付いた。検索してみるとそもそも1箇所しか無い。
そんなわけで呼び出しの追加を施してみたら、案の定パフォーマンスは多少改善された。しかしまだ重すぎて落ちまくる。ただソースを眺めていても理由がわからなかったので、うまくいっていたGtk#版とソースの差分をチェックしてみたら、どうやらXwt.TextLayoutを生成する際にFontオブジェクトをWithSize()で毎回生成している部分が怪しく見えたので、これを再利用するようにしたら、一気に改善された。
ただ、それでもかなりアグレッシブにMIDIイベントを短時間で送りまくるMIDIファイルを演奏してみると、まだ一定時間でもたつくことがあった。その挙動を見るに、おそらくGC(グラフィックスコンテキストではなくガベージコレクションのほう)の停止時間などが怪しいのではないかと思っているが、ここはまだ確認していない。
いずれにせよ、BeginPaintRect()/EndPaintRect()については、Xwtのパッチを作ってpull requestを送ったのだけど、開発者が実際に動かそうともせずに「ドキュメントにはダブルバッファリングしているって書いてある」などと主張するせいで未だに取り込まれていない。そんな死に絶えるべき状況でもsubmoduleでforkを取り込めるgitは素晴らしい。
https://github.com/mono/xwt/pull/268
とりあえずGUIまわりはこんな感じでXwtで進めているが、開発側の対応次第ではいくらでもGtk#に戻る気満々になった。