C++ ときどき ごはん、わりとてぃーぶれいく☆

Wonder Rabbit Projectのなかのひとのブログ。主にC++。

最近のOpenGL Samples PackがLinuxでビルドできない理由とビルド&実行する方法について

最新のOpenGLサンプルと言えば、

ですが、執筆時点で最新の4.2.3.1がうちのarchlinuxちゃんでビルドできない事に気付いた。4.2.2.0まではビルドでき、4.2.2.1からはビルドできない。と、いうわけで、4.2.2.1の変更内容を確認すると、

OpenGL Samples Pack 4.2.2.1: 2012-01-24

  • Fixed bugs

( ゚д゚)…なんでバグフィックスの修正だけでビルド通らんくなっとるんや…。

で、まあサンプルのソースやシステムのGLEWヘッダーなんかを確認すると、どうやら

とゆー訳ではないか、と。`common/glf/glf.inl`だけ修正すればビルドできるかと言うと、個別のサンプルでもWGL_*系のフラグをさっくり使う様になっているので他にも幾つか修正が必要。

  • samples/oes-200-draw-elements.cpp … WGL_CONTEXT_ES2_PROFILE_BIT_EXT
  • samples/ogl-300-fbo-multisample.cpp … WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB
  • samples/ogl-330-blend-index.cpp … WGL_CONTEXT_CORE_PROFILE_BIT_ARB

…ほか多数。

失敗編(#define作戦)

`grep -nr "WGL_CONTEXT_CORE_PROFILE_BIT_ARB" ./`とかするといちいちWGL_*に対する修正をする気力とかなくなる。代わりに`common/glf/glf.hpp`の適切な位置でWGL_CONTEXT_ES2_PROFILE_BIT_EXTとWGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARBを#defineしてしまった方が手っ取り早いか、そう思った・x・

`/usr/include/GL/wglext.h`及び`/usr/include/GL/wglew.h`で各CPPが#defineされている。この値を`common/glf/glf.hpp`に#defineしてしまう。4.2.3.1時点では3つのWGL_*系フラグを拝借すれば全てのサンプルをビルド(だけは)できる。

--- common.orig/glf/glf.hpp     2012-02-04 17:53:12.000000000 +0900
+++ common/glf/glf.hpp  2012-05-27 19:05:34.649003387 +0900
@@ -15,6 +15,15 @@
 #      define GL_GLEXT_PROTOTYPES 1
 #      include <GL/gl.h>
 #      include <GL/glext.h>
+# if !defined(WGL_CONTEXT_ES2_PROFILE_BIT_EXT)
+#  define WGL_CONTEXT_ES2_PROFILE_BIT_EXT 0x00000004
+# endif
+# if !defined(WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB)
+#  define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
+# endif
+# if !defined(WGL_CONTEXT_CORE_PROFILE_BIT_ARB)
+#  define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
+# endif
 #elif defined(__APPLE__)
 #      include <OpenGL/gl.h>
 #else

これでビルドは通る。通るが動くかはまた別の話で、ogl-330/400/410/420系はsegmentation faultしてもーた・w・;

成功編(glutInitContextProfileにProfile渡すの止めましょう・w・;)

と、言う訳で、ビルドもできるしogl-420系もまともに実行可能だった4.2.2.0のソースを見ると、`common/glf/glf.inl`に実体がinline定義されているglf::runのパラメーターがそもそも1つ少ない。失敗編で#defineしたプロファイルは各サンプルの.cppの終端付近のmain関数からglf::runへ渡されていたのだが、そのプロファイルのパラメーターint Profileがそもそも4.2.2.0までは存在しなかった。

#if !defined(__APPLE__)
    glutInitContextVersion(Major, Minor);
    if(Profile == WGL_CONTEXT_ES2_PROFILE_BIT_EXT)
      glutInitContextProfile(WGL_CONTEXT_ES2_PROFILE_BIT_EXT);
    else if(glf::version(Major, Minor) >= 320)
    {
      glutInitContextProfile(Profile); // GLUT_COMPATIBILITY_PROFILE GLUT_CORE_PROFILE
      glutInitContextFlags(GLUT_FORWARD_COMPATIBLE | GLUT_DEBUG);
    }
#endif//__APPLE__

Profileは glutInitContextProfile に渡して使用している。この部分は4.2.2.0まで、

    if(glf::version(Major, Minor) >= 320)
    {
#if defined(WIN32)
      glutInitContextProfile(GLUT_CORE_PROFILE); // GLUT_COMPATIBILITY_PROFILE
#else
      glutInitContextProfile(GLUT_COMPATIBILITY_PROFILE); // GLUT_COMPATIBILITY_PROFILE
#endif
      glutInitContextFlags(GLUT_FORWARD_COMPATIBLE | GLUT_DEBUG);
    }

となっている。かといってこの様に戻しても状況は変わらず、結局glutInitContextProfileもglutInitContextFlagsも無かった事にしてビルドし、セグフォらないサンプルを実行可能となった。なお、WGL_CONTEXT_ES2_PROFILE_BIT_EXTはglutInitContextProfileに渡してもoes-200系のサンプルの実行に差支え無かった。なんだかあまり綺麗な解決じゃないのが嫌だ。

最終的なパッチ
diff common.orig/glf/glf.hpp common/glf/glf.hpp
17a18,26
> # if !defined(WGL_CONTEXT_ES2_PROFILE_BIT_EXT)
> #  define WGL_CONTEXT_ES2_PROFILE_BIT_EXT 0x00000004
> # endif
> # if !defined(WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB)
> #  define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
> # endif
> # if !defined(WGL_CONTEXT_CORE_PROFILE_BIT_ARB)
> #  define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
> # endif
diff common.orig/glf/glf.inl common/glf/glf.inl
486,487c486,487
<                       glutInitContextProfile(Profile); // GLUT_COMPATIBILITY_PROFILE GLUT_CORE_PROFILE
<                       glutInitContextFlags(GLUT_FORWARD_COMPATIBLE | GLUT_DEBUG);
---
>                       //glutInitContextProfile(Profile); // GLUT_COMPATIBILITY_PROFILE GLUT_CORE_PROFILE
>                       //glutInitContextFlags(GLUT_FORWARD_COMPATIBLE | GLUT_DEBUG);

いやはや、無駄に疲れたー・w・;

余談

ちなみにこれ、動作確認が取れるまで随分と苦労した理由にRADEONのLinuxドライバーがポンコツって事も大いに関係していると思われる。なにせ途中で何をやってもセグフォやら動作しないやらになって動いてた別のバージョンのサンプルまで動かなくなってPC再起動してビルドしなおして試して…とかやってたの…。モウネ・w・;

ちなみにGPUはRADEON HD5870。Linuxのドライバーサポートが酷すぎていますぐにでもGeForceに変えたいよ。