試験運用中なLinux備忘録・旧記事

はてなダイアリーで公開していた2007年5月-2015年3月の記事を保存しています。

『試験運用中なLinux備忘録』のBloggerへの移行とタイトル一部変更に関するお知らせ

ウェブログ運営上の事情により、この『試験運用中なLinux備忘録』はこれまで利用してきたはてなダイアリーからBloggerへと移行することになりました。*1

移行先のウェブログは『kakurasanのLinux備忘録』です。既に最初の記事が公開されているので、ぜひご覧ください。

2015年3月時点ではページレイアウトや一部外観の調整が今後頻繁に行われる可能性があります。

今後の新規記事の追加先について

新しい記事は今後はてなダイアリーで公開されることはありません。Bloggerの新ウェブログ上でのみ公開されます。

過去の記事について

過去の記事をすぐに削除する予定はありませんが、記事によっては段階的に新ウェブログ側へ移す計画です。
諸事情により、現時点では2015/9/27(日)頃までには、はてなダイアリーからは記事を全て無くす*2方向で考えています。ただし、新ウェブログの状況によってはこの時期が延期される可能性があります。
(2015/8/22)はてなダイアリーからの記事の削除は延期します。削除時期の予定は未定です。

過去にアップロードした画像について

過去にはてなフォトライフへアップロードしたスクリーンショットなどの画像についてはそのまま残します。はてなフォトライフのサービスが継続している限りはこれらの画像は今後も参照可能で、削除予定はありません。

*1:ポジティブな移行理由はなく、特にリニューアル要素もありません。不本意な移転理由によるものですが、ここで詳細を述べることには意味を見出せないため、それには触れません。

*2:削除かウェブログ非公開への設定変更のいずれか

WOLF RPG エディター 2.10作品が3Dモード時にWineで文字化けする問題の邪道な対処

(2015/12/28)本記事は「WineでWOLF RPG エディター 2.10作品が3Dモード時に文字化けする問題と対処」へ移動した。

WOLF RPG エディターのバージョン2.10で作成された作品をWineで3Dモードで動かしたときに文字描画が崩れる現象について(2014年2月末時点)」のその後として、3Dモード時に発生する文字化けの対処についてを扱う。

  1. 問題のおさらい
  2. 修正の要領
  3. パッチ
  4. パッチ適用済みのバイナリ
  5. 設定方法

問題のおさらい

  • Sagawa氏曰く、IDirect3DDevice9::UpdateTexture()Wine(wined3d)における実装では、(バージョン1.7系時点では)「ダーティ領域」として記録された領域だけでなくテクスチャの全体がコピーされる処理になっている
  • 同氏曰く、バージョン3.11dより古い幾つかのバージョンのDXライブラリには、IDirect3DTexture9::LockRect()で矩形範囲をロック処理*1した後でIDirect3DDevice9::UpdateTexture()を呼び出した際に、先ほどロックした領域=ダーティ領域のみがコピーされるという動作を期待した処理がフォントキャッシュの扱いの中で存在し、Wineの実装では上の挙動の関係で特定の流れによってキャッシュの破損が確実に起こり、文字化けの原因となる
  • WOLF RPG エディター (ウディタ)バージョン2.10に含まれるGame.exeはこの現象が発生するバージョン(3.10f)のDXライブラリを組み込んでいる(静的リンクしている)ため影響を受ける
  • 上記動作に依存した部分は同ライブラリのバージョン3.11d以上では改善されて文字化けは起こらないが、その新しいバージョンのDXライブラリを組み込んだWOLF RPG エディターの新しいバージョンは2015年1月末時点では公開されておらず、それで既存のGame.exeを置き換えるという形の対処はまだ行えず、できるようになっても文字化けしない以外にバージョン2.10のGame.exeと完全に同じ動作になるかは不明
  • WineのBugzillaで2013年の年末にバグ報告をしたが、その後DXライブラリ側が修正されたことは分かったものの、Wine側の変更による対処には前向きではなく、パッチも提供されていない
  • 2014年2月にWOLF RPG エディターのバグ報告の掲示板にこの件についてを書いたものの、新しいバージョンが(ベータ版含め)出ていないどころか、作者によるコメントも(2013年8月より後はずっと)見られない
  • Wineのバージョン1.7.34*2時点では改善はされておらず、最近はMacユーザによる文字化け事例も複数見られるようになっている

修正の要領

WOLF RPG エディターのバージョン2.10で作成された作品をWineで3Dモードで動かしたときに文字描画が崩れる現象について(2014年2月末時点)」でも書いたような、レジストリ設定によって切り替え可能(他のプログラムの実行に影響しない形)な回避策がWine側の変更によって実現できないか試してみたところ、最終的にそのような形で動作するものが作成できた。
修正の要領としては以下のようになる。Wineのバージョンが変わって一部の修正の仕方が変わることがあっても考え方は同じ。

  • IDirect3DTexture9::LockRect()Wine実装からはテクスチャのサブリソースであるサーフェイス*3の処理としてIDirect3DSurface9::LockRect()Wine実装が中で呼ばれるが、この中において、ロックされた領域を示すRECT構造体(左/上/右/下の4つの座標の値から成る)を、サーフェイスの構造体内に別途追加した別のRECT型のメンバにコピーしておく
  • IDirect3DDevice9::UpdateTexture()*4Wine実装からはサブリソースの処理としてIDirect3DDevice9::UpdateSurface()Wine実装が中で呼ばれるが、2Dテクスチャを扱う場合の呼び出しについて、転送元サーフェイスの構造体のメンバを参照して、過去にロックされたことのあるものについては先ほどコピーした座標情報を利用して、その範囲のみが転送先サーフェイスの同一座標(左上基準・つまりコピー先のRECT構造体の左と上の座標値をPOINT構造体で用いる)へコピーされるように引数を指定する
  • 常にこの挙動で動作するようにすると他のプログラムで意図しない動作をする恐れがあるため、Wineにあるレジストリ設定の仕組みを利用して設定項目を追加(設定保持用構造体のメンバ追加と初期値指定,レジストリ設定取得処理の追加)*5し、上2つの動作はこの独自動作(以下hack)の有効時にのみ行われるようにする

というものとなった。
本来はサーフェイスの構造体内にダーティ領域を示す構造体のメンバを用意して、ダーティ領域を変化させる操作(ロック以外に複数存在する)それぞれについて扱いを正しく記述してIDirect3DDevice9::UpdateTexture()側でそれを用いてコピー範囲を決める必要がある*6のだが、WineDirect3Dでダーティ領域の情報が内部的にどのように管理されているのかがよく分からず、処理によっては関数から関数へと指定領域が引数で渡されているにも関わらず関数内でそれが一切使われていないところもあったため、結局は該当するバージョンのDXライブラリで正しく動くことだけを優先して「レジストリにより切り替え可能なhack」という形で実装した。
将来のバージョンでこのあたりの動作が改善されて特に何もせずに正しく動作するようになる可能性もなくはないが、あまり期待はできない。

パッチ

パブリックドメインとして公開する。
1.6.2向け: wine-1.6.2-dxlib-font-hack.patch
1.7.34向け*7: wine-1.7.34-dxlib-font-hack.patch
(2015/2/5)hack無効時の一部の不必要な条件分岐を省くように修正

手動でビルド*8する場合、ソースとバージョンが同一な(32bitの)ディストリのバイナリパッケージがあれば、dlls/wined3d/内のビルドが終わった後はビルドを中止して(32bitの)wined3d.dll.soのみを既存のファイル([32bitライブラリのディレクトリ]/wine/wined3d.dll.so)に対して管理者権限で上書きするだけで済む。

パッチ適用済みのバイナリ

ppa:kakurasan/unstable」のPPAリポジトリで公開した(Ubuntu 14.10向け)。バージョンは安定版系統の1.6.2のみ用意した。
PPAリポジトリの追加手順については以前AMDのlegacy版グラフィックドライバのインストールに関して書いた記事(内容自体は古いので注意)を参照。パッケージ情報の再読み込み後は「wine1.6」パッケージをインストール(インストール済みの場合はアップグレード)する。
他のディストリなどでは別途バージョン1.6.2のバイナリをインストールした上でwine1.6-i386_[バージョン]_i386.debのみ上のページから手動でダウンロードして展開し、wined3d.dll.soのみを既存のファイルに対して管理者権限で上書きする方法もあるが、正しく動作する保証はない。

設定方法

文字化け回避のモードで動かす(hackを有効にする)にはレジストリの設定が必要。
全てのプログラムに対してこのhackを有効にする場合レジストリのキー(フォルダ)「HKEY_CURRENT_USER\Software\Wine\Direct3D」の中に「DxLibFontHack」という名前の文字列を作成して値を「enabled」とする。
下はレジストリファイルとして取り込む場合の内容。
[任意]ファイル名: enable-dxlib-font-hack.reg

REGEDIT4

[HKEY_CURRENT_USER\Software\Wine\Direct3D]
"DxLibFontHack"="enabled"

無効化するファイルは「enabled」部分を他の「disabled」などの文字列に変更して別名で保存すると作れる。
特定のファイル名のプログラムに対してこのhackを有効にする*9場合は「HKEY_CURRENT_USER\Software\Wine\AppDefaults\[ファイル名]\Direct3D」の中に同様の項目を作成する。
下はGame.exeというファイル名でのみ有効になるような設定。
[任意]ファイル名: enable-dxlib-font-hack-game.reg

REGEDIT4

[HKEY_CURRENT_USER\Software\Wine\AppDefaults\Game.exe\Direct3D]
"DxLibFontHack"="enabled"

上はWOLF RPG エディター作品の動作に便利だが、より確実にWOLF RPG エディター作品だけを自動的にhackの対象にするには上記設定のファイル名部分と実際のファイル名の両方をWolfRpgGame.exeなど他とかぶりにくい名前にして使うとよい。
下は設定を自動で有効化するスクリプト例。環境に応じて一部変更して用いる。これはGame.exeWolfRpgGame.exeに名前変更して使う場合の例で、他のプログラムを動かす際にレジストリ設定の切り替えを行う場面はほとんどなくなる。
無効化するスクリプトは「enabled」部分を他の「disabled」などの文字列に変更して別名で保存すると作れる。
[任意]ファイル名: enable-dxlib-font-hack-wolfrpggame.sh

#! /bin/sh

### 標準ではない場所にWineを配置している場合
### libwine.so*のあるディレクトリを指定
#export LD_LIBRARY_PATH=/opt/wine-1.6.2/lib/i386-linux-gnu

### 標準ではない場所のWine環境を使用している場合に指定
#export WINEPREFIX=/home/user/dotwine-wolf

### wineコマンドの場所
#WINE=/opt/wine-1.6.2/bin/wine
WINE=wine

cat <<EOF | ${WINE} regedit -
REGEDIT4

[HKEY_CURRENT_USER\Software\Wine\AppDefaults\WolfRpgGame.exe\Direct3D]
"DxLibFontHack"="enabled"
EOF

使用したバージョン:

  • Wine 1.6.2, 1.7.34

*1:仕様上はここで同領域が「ダーティ領域」として記録される

*2:1.7.35については実際の動作は未確認だが、ソースの該当箇所を見る限りは同様

*3:少なくともWineDirect3Dではテクスチャという型はサーフェイス(画像データを保持するメモリ領域)という型を中に含む形になり、テクスチャからサーフェイスはサブリソースとして参照する・IDirect3DDevice9::UpdateTexture()についても、中でサブリソースのサーフェイスに対するIDirect3DDevice9::UpdateSurface()に相当する内部処理が呼ばれる形の実装になっている

*4:説明として「テクスチャのダーティー部分を更新する。」とあり、「転送元テクスチャにダーティー領域がある場合は、コピーをその領域だけに限定することで、コピー処理を最適化できる。」とも書かれているが「ダーティーとしてマークされているバイトだけがコピーされるという保証はない。」ともある

*5:これらは既存の設定項目に関係した記述を参考にしてコードを追加することで簡単に実装できる

*6:本家のソースツリーに対する修正としてはその形が望ましく、今回のような形の修正は取り込まれるべきではないと考える

*7:1.7.35については、パッチが正常に当たることは確認したが動作は未確認

*8:32bit向け・基本的には32bit環境や32bitのchroot環境でビルドする

*9:指定した以外のファイル名のプログラムでは無効になり、設定の切り替え機会を少なくできる

GNU/LinuxネイティブのDirect3D 9を使えるようにするgallium nineと関連メモ(CSMT,Wine Staging)跡地

(2019/9/29)本記事は「GNU/LinuxネイティブのDirect3D 9を実装したGallium Nineとその使い方」へ移動した。

以下、以前の内容となる。

「gallium nine」と呼ばれるソフトウェアが一部で注目されている。

gallium nineについて

これはGNU/Linuxで自由なソフトウェアのグラフィックドライバ使用時にDirect3D 9がOSネイティブな描画APIとしてWine上のWindowsアプリケーションなどのDirect3D 9を利用するプログラムから利用できるようにするもの。
自由なソフトウェアのグラフィックドライバではGallium3D(もしくはGallium)と呼ばれる3Dグラフィックの枠組みが用いられるが、「gallium nine」はこの中の「state tracker」と呼ばれる種類のモジュールとしてGallium使用時にDirect3D 9を描画APIとして用いることを可能にする。
ファイルとしては「d3dadapter9」と呼ばれるライブラリの形をとり、これをWineなどのソフトウェアから利用するためのヘッダファイル群*1と、state trackerとして(libdrmやLLVMなどのライブラリを用いて)Direct3D 9の機能を提供する共有オブジェクト(d3dadapter9.so.[数字])*2から成る。

gallium nineの利点と欠点

利点
Wineは既にDirectX 9cを実装しているが、Direct3DについてはOpenGLを用いて実装されており、Direct3Dの描画命令を実行するためには処理コストが余計にかかる。
gallium nineは、WineDirect3D 9(OpenGLを用いた実装)と比べるとOpenGLを経由しない分処理コストが少ない関係で高速に動作する場合が多い。
どの程度高速化されるかはグラフィックドライバ(Galliumのドライバ部分,libdrm,カーネルDRMモジュールといったプログラム)やGPUによるが、特に、高性能なGPUの使用時には大きな差が出るようだ。Windows上より速くなるかどうかはそれぞれのOSのグラフィックドライバなどによる。
動作速度があまり向上しないケースでもCPUの処理量が減るのは間違いないため、CPU使用率が減ってわずかに省電力になる場合もある。
下はDirect3D 9の描画処理の大まかな流れを比較した図。

(WineでDirect3D 9アプリケーションを動かす際の描画処理の流れ)
Wine/d3d9 -[Direct3D 9命令]-> Wine/wined3d(OpenGLを用いてその都度実行) -[OpenGL命令]-> libGL -> Galliumドライバ -> 低レベルドライバ(libdrmやDRMカーネルモジュール) -> GPU

(gallium nineを用いた際の描画処理の流れ)
Wine/d3d9(命令をそのまま渡す) -[Direct3D 9命令]-> d3dadapter9 -> Galliumドライバ -> 低レベルドライバ(libdrmやDRMカーネルモジュール) -> GPU

シェーダ処理については、WineDirect3D(wined3d)では

  • GLSL(既定値)
  • OpenGL拡張のARB_vertex_program/ARB_fragment_program(GLSL無効時・非推奨)

のいずれかを用いる形で実装されているが、これらは自由なソフトウェアのグラフィックドライバ使用時は一旦GalliumのTGSI(TG Shader Infrastructure)と呼ばれる抽象化された表現に変換されてから(各GPU向けのGalliumドライバを経由して)実行される。gallium nineからシェーダを用いる際には上記のいずれかを経由せずに直接TGSIへ変換されるため、それよりも処理コストが削減される。

(WineでDirect3D 9アプリケーションを動かす際のシェーダ処理の流れ)
Wine/d3d9 -[Direct3D 9命令]-> Wine/wined3d(GLSL or GL拡張としてその都度実行) -[GLSL or GL拡張]-> libGL(TGSIに変換) -[TGSI]-> Galliumドライバ -> 低レベルドライバ(libdrmやDRMカーネルモジュール) -> GPU

(gallium nineを用いた際のシェーダ処理の流れ)
Wine/d3d9 -[Direct3D 9命令]-> d3dadapter9(TGSIに変換) -[TGSI]-> Galliumドライバ -> 低レベルドライバ(libdrmやDRMカーネルモジュール) -> GPU

欠点

  • 2015年1月時点ではDirect3D 9専用・ただし、プロジェクトのサイトによると別のバージョンに向けた対応の可能性もあり、特にDirect3D 8は将来対応する可能性が高い*3
  • 2015年1月時点のプロプライエタリなグラフィックドライバ(GPUメーカー提供の、自由でないドライバ)はGalliumの構造に合っていないため、プロプライエタリドライバでは利用できない
  • 2015年1月時点ではまだ完成度が低く、動作するプログラムは非常に良好に動作する一方で、まともに動作しないプログラムも多い
  • Wineで利用するためにはWineへの修正が必要で、2015年1月時点では公式のWineでは未対応*4・更に、古い安定版のWineでは利用できない(バージョン1.8が出れば安定版で利用できる)

これまでの開発

最初に話題になったのは2013年夏、Mesaのメーリングリストへの投稿のときだった。
2014年春まではこのときの開発リポジトリで開発が続いていたが、その後は新しい派生リポジトリに移って活発に開発が行われるようになった。

更に、Mesaの公式のソースツリーに取り込んでもらうよう働きかける動きも進んで、バージョン10.4では初めて公式のリリースの中に含まれることになった。
ビルドの際にconfigureスクリプトへオプション--enable-nineを付けることで比較的簡単に導入できるようになっているが、ディストリによってはMesa 10.4のパッケージでgallium nineは無効(既定値)のままとなっていて利用できない。
Mesa 10.4のgallium nineもまだ完成度は低く、開発が続けられる一方で、Mesa 10.4が出た後の修正についても公式のソースツリーに取り込んでもらう動きが続いており、2015/1/23(GMT表記では22日となる時刻)には50ものパッチが新しく取り込まれた。Mesa 10.5ではその改善も入る見通し。*5
Wineへの修正については、公式のソースツリーへの取り込みはまだ行われておらず、見通しについても不明*6

導入

プロジェクトサイトのインストールに関するページでディストリごとの導入について書かれている。詳しくはここでは扱わない。
「DRI2よりもDRI3を用いたほうが高速に動作する」とされているが、DRI3の使用は必須ではなく、DRI2環境でもWineでgallium nineが使えるようになっている(「DRI2 fallback」という機能)。*7
2015年1月時点では、X11で「xf86-video-ati」ドライバ*8を使用している場合、DRI3を用いるには同プロジェクトが提供する「xf86-video-ati」パッケージが必要。gallium nineの動作テストと不具合報告を行う目的で使う場合は、これは用いずにDRI2環境を用いたほうがよい(不具合原因の切り分けの都合)。

有効化/無効化の設定

以前はレジストリの値を手動で設定する必要があったが、2015年1月時点(バージョン1.7.34)の修正済みのWineではGUIツールwinecfgで「画面」タブに設定項目があり、チェックを入れた状態でDirect3D 9アプリケーションを使用したときにgallium nineが使われる(チェックを外すと従来のOpenGLを用いた実装で動作する)。

動作テスト

テストにはWindowsDirectX 診断ツール(dxdiag)が便利で、winetricksの「dxdiag」パッケージをインストールするのが楽。
インストールしたら、Wine内の「dxdiag」コマンドを実行する。

(テスト時にフルスクリーンで動作)
$ WINEPREFIX=[Wine環境の場所] wine dxdiag

(1024x768の仮想デスクトップのウィンドウ内で動作・テスト時にはウィンドウサイズが変わる)
$ WINEPREFIX=[Wine環境の場所] wine explorer /desktop=dxdiag,1024x768 dxdiag

「ディスプレイ」タブの「Direct3D のテスト」を押すと3つ目のテストでDirect3D 9が使われるので、ここで前述のチェックが入っているとGNU/LinuxネイティブのDirect3D 9が使われる。回転する立方体の描画だけを見ても違いは分からないが、GNU/LinuxネイティブのDirect3D 9が使われているときには端末には色の付いたメッセージが表示される(プログラム起動時など、描画処理以外で表示される場面もある)。
ここまでに問題がなければ導入に成功していることになる。

関連:Wine上のDirect3DやDirectDrawのCSMTによる高速化

gallium nineとは別に「CSMT (Commandstream multithreading)*9」と呼ばれる手法(OpenGL命令の実行の別スレッド化)によりWineDirect3D(Wineが対応する全てのバージョン)やDirectDrawの動作が高速化する場合があり、プロプライエタリドライバでも恩恵が受けられる*10こちらも、2015年1月時点ではまだ公式のWineのソースツリーには入っていない*11が、まだ公式のソースツリーに取り込まれていない修正(実験的なものを含む)を適用したバージョンを多くのディストリ向けに提供することでテスト・評価などを行いやすくして、これらを取り入れてもらう流れやコードの品質をよりよくする目的で運用されている「Wine Staging」プロジェクト(www.wine-staging.com)*12が提供しているパッケージを導入することで試すことができる。
CSMTの有効/無効の切り替えについてもwinecfgで可能となっており、バージョン1.7.34の時点では「Staging」タブのCSMTに関する設定項目にチェックを入れることで有効にできる。

*1:修正されたWineなど、これを利用する側のソフトウェアのビルド時に使用

*2:利用する側のソフトウェアのビルド時と実行時の両方で使用

*3:Direct3D 10以上は過去にstate trackerとしての実装が存在した時期があり(ただし実用的ではなくライブラリもなく、実際はほとんど使われなかった)、2015年1月時点では消えているものの、将来需要が高まれば、また別の新しいstate trackerとしての実装が登場する可能性はある

*4:UbuntuのPPAで公開している人がいるため、導入自体は楽にできる

*5:その内の大部分は10.4系にも適用され、バージョン10.4.3で利用できる

*6:こちらも適用済みバージョンをUbuntuのPPAで公開している人がいるため、導入自体は楽にできる

*7:以前はDRI2かDRI3の片方にしか対応できず、注意が必要だった

*8:Device Dependent X (DDX) driverという類のX11用ドライバ

*9:「d3dstream」と呼ばれることもある

*10:また、有効にすることで描画の不具合が出る場合や、逆に既存の描画の不具合の回避になる場合もあるようだ

*11:将来的には確実に取り込まれる見通し

*12:Silverlight(DRM有りの動画の視聴含む)やUnity3DなどのWindows向けブラウザプラグインGNU/LinuxWebブラウザで動かすPipelightからも使われる・Pipelightについては機会があれば記事として詳しく扱う