OpenGLのGLUT

GLUT(OpenGL Utility Toolkit)は、最近は開発が止まっていて、Fedora Core 4とかだとfreeglutがインストールされています。調べてみたのですが、MinGWで使う方法は、紹介されていました。が、プログラムをコンパイルするとSTDCALLが使われているという警告がでて、うまく解除する方法が見つかりませんでした。
それで、freeglutを試してみました。これも、コンパイルしてみるとundefined referenceというエラーが出てうまくコンパイルできません。結局、staticリンクのライブラリを作るようにして解決しました。
まず、freeglut-2.4.0を-DFREE_GLUT_STATICをつけてコンパイルします。作成したlibglut.aは、他のライブラリに合わせて、libglut32.aに名前を変えて使います。
freeglut-2.4.0$ CFLAGS="-O2 -g -DFREEGLUT_STATIC" ./configure
freeglut-2.4.0$ make -C src
freeglut-2.4.0$ mv /mingw/lib/libglut32.a /mingw/lib/libglut32.a.orig
freeglut-2.4.0$ cp src/.libs/libglut.a /mingw/lib/liblut32.a
freeglut-2.4.0$ cp include/GL/free* /mingw/include/GL
freeglut-2.4.0$ cp include/GL/glut.h /mingw/include/GL
使うときは、<GL/glut.h>の前に#define FREEGLUT_STATICを付けます。
#include <GL/gl.h>
#define FREEGLUT_STATIC
#include <GL/glut.h>
コンパイルは、次のオプションで行います。-lglut32の順序が重要で最初にないといけないみたいです。
gcc test.c -lglut32 -lglu32 -lopengl32 -lwinmm -lgdi32

PCIバスが動かない

PCIバスが動かないというメールをもらって調べてみたら、BIOSファイルを更新するのを忘れていました。すみません。
qemu-20061030-all.zipは、うまく動きませんでした。
新しいすべてのパッチをあてたバイナリはちゃんと動くと思います。
それと、libusb0.dllを同梱することにしました。USBのフィルタドライバがインストールされていなくても動くと思います。Win98/Meホストでも起動すると思うけれど、確認していません。もちろん、Win98/Meホストではドライバがインストールできないので、USBは使えませんけれど。
http://www.h6.dion.ne.jp/~kazuw/qemu-win/qemu-20061123-all.zip

OpenGLの扱い方

mrtさんに言われて考えてみたのですが、今後の方針としてWindowsホストでもOpenGLが高速化されるようにパッチの移植にトライしてみようと思います。CVSにとりこまれる実装が変わる可能性があるけれど、1度動かし方がわかれば何とかなるでしょう。
wineの完成度はどのくらいなんでしょうね。実際、どのくらいのプログラムが動くようになっているのでしょう。
まずは、OpenGLとか勉強してみて動かせそうかどうか見てみないといけないですけど。DirectDraw/Direct3Dについても調べてみる必要がありそう。
高速化を図る仕組みとしては、ライブラリのレベルで手を入れるのか、デバイスドライバ/ディスプレイアダプタのレベルにするかというのがありますね。対象にするものがOpenGLかDirectXかによっても話が違ってくるわけで、結局どうするのが一番手間がかからなくて性能がいいんだろう、とか考えてしまいました。

OpenGLのglxgears

やっとパッチを当てて動くようになりました。バグがあったのと、gccの最適化をかけるとコンパイルできなくて、試行錯誤しました。結局最適化無しでしかコンパイルできなかったです。それと、LD_LIBRARY_PATHで、用意したライブラリを設定してゲストOSでプログラムを動かす必要があるのですが、メールで説明されていた方法が間違っていました。ライブラリを直接指定するのではなく、パスを指定するのがLD_LIBRARY_PATHでした。
glxgearsというプログラムを動かしてみると、別のウィンドウが出て、そこに表示されます。アクセラレート無しで24FPSくらいなのが、170FPSくらいになりました。ホストで実行した場合は、670FPSくらいですので、実機の4分の1くらいまで加速されます。
修正したパッチはメーリングリストに送っておきました。
作り方は、まず、パッチを当てます。そして、makeすると、i386-softmmuにlibGL.soというファイルができます。
QEMUは、-enable-glオプションを付けて起動します。
ゲストOSが立ち上がったら、libGL.soを、ゲストOSにftpなどでコピーします。そして、libGL.so.1にリンクを張ります。これは、glxgearsが、libGL.so.1を必要とするからです。
guest>$ ln -s libGL.so libGL.so.1
LD_LIBRARY_PATHに、カレントディレクトリなら'.'、もしくはlibGL.so.1のあるディレクトリを指定します。
guest>$ LD_LIBRARY_PATH=. glxgears
すると、別のウィンドウが開くはずです。
こんなの作れてしまう人ってすごいなと思います。

OpenGLの高速化

ゲストOS内のOpenGLの呼び出しをホストに伝えて、OpenGLの高速化を図るパッチが登場しました。Proof of conceptと言って、アイデアの検証をしてみたとのことですが、こちらで検証しようとしてもプログラムがうまく作れなくて検証できません。
LibGL.soというライブラリ作って、ゲストOS内のOpenGLの呼び出しを横取りし、ホストOSで普通のプログラムのOpenGLの関数の呼び出しに変換して表示するという仕組みみたいです。ユーザーモードネットワークの仕組みを、グラフィックの表示でも行うみたいな感じかな。
同じような仕組みで、Direct3Dを表示することもできるんじゃないかという気がします。かなりのハックが必要になると思いますけど。
ゲストの表示速度の遅さは問題でしたので、安定して動くようになるといいのですけど。ただ、高速化の仕組みには問題があって、ゲストのメモリを直接コピーしたりしていて、i386のLinuxホスト/ゲストでしか使えません。PCIの仮想ディスプレイアダプタをアクセスしてデータをやり取りする方法がいいという意見が出てましたけれど、作れる人がいるのかな。メンテナンスする人が現れないと、このまま消えていってしまうような気がします。
まずは、自分の目で確かめたいのですが、OpenGLをよくわかってなかったりするのでした。

コマンドプロンプトをでなくするには

ここにあるNoConsoleというユーティリティを使うと、Windowsプログラムからコンソールを取り除くことができます。
http://dliboon.freeshell.org/?view=programming.bcx
DOS> noconsole qemu.exe
とやって、実行ファイルにパッチを当てます。バッチファイル内では、
start qemu.exe [options]
とします。
やっぱり、コンソールは邪魔に感じますかね。開発者の人が、QEMUはまだコンソールプログラムでGUIを持ったWindowsプログラムじゃないからといって、コンソール付のプログラムになっているのですけど。実は自分もあまりかっこよくないなと思っていたりします。少し手間はかかりますが、自分で変更してみてください。

gdbでのDLLのデバッグ

MinGWで、dllのデバッグをしようとすると、ブレークポイントを設定するのにちょっとしたコツが必要になります。
具体的には、QEMUでSDL.dllのデバッグをしようとしたのですが、まず、-gオプション付でSDLのコンパイルをします。
SDL-1.2.11>$ CFLAGS="-O0 -g" configure
SDL.dllをQEMUのある場所にコピーします。そして、gdbでのデバッグを開始します。
ここで、QEMUを走らせてからDLL内の関数を指定する方法と、走らせる前に指定する方法の2つがあります。
[その1]QEMUを走らせてから設定
いったんmain関数で実行を止めて、ブレークポイントを設定します。
$ gdb qemu
(gdb) set args -L ../pc-bios -hda ../../linux.img
(gdb) b main
(gdb) run
止まったら、調べたい関数を指定します。
(gdb) b SDL_VideoInit
(gdb) continue
これで、DLL内で止まると思います。
[その2]QEMUを走らせる前に設定
dll-symbolsでSDL.dllを指定します。
$ gdb qemu
(gdb) set args -L ../pc-bios -hda ../../linux.img
(gdb) dll-symbols SDL.dll
listで調べたい関数を表示します。
(gdb) list SDL_VideoInit
141
142 /*
143 * Initialize the video and event subsystems -- determine native pixel format
144 */
145 int SDL_VideoInit (const char *driver_name, Uint32 flags)
146 {
147 SDL_VideoDevice *video;
148 int index;
149 int i;
150 SDL_PixelFormat vformat;
表示された行番号をブレークポイントに指定します。
(gdb) break 145
(gdb) run
これで、runをすればブレークポイントで止まるはずです。ソースコードが表示されない場合、directoryでソースコードの位置を指定する必要があるかもしれません。
(gdb) directory ~/sdl-1.2.11/src/video/
なぜQEMUを実行してからでないと、ブレークポイントを設定できないかというと、SDL.dllがメモリーにロードされないとアドレスが解決できないせいだと思います。

SPARCのバイナリ

SPARCで、-nographicオプションが使いたいという人が現れた。でも、lukewarmさんに作ってもらったコンソールパッチは、かなり古くなってしまっていて、使えない。そこで、Ctrl-Alt-3のシリアルコンソールを使う方法と、-serialオプションと、ComEmulDrvドライバを使って、ハイパーターミナルからシリアルコンソールを使う方法を紹介しておいた。
Linuxのシリアルコンソールはほとんど使ったこと無いから、あまり詳しいことは言えないけれどね。
パッチを全部当ててバイナリを更新しておきました。
いろんな使い方をしている人がいるんですね。