2011-06-19 19 views
8

私はlibx11でマルチスレッドのOpenGLアプリケーションを作成しようとしています。ウィンドウごとに1つのスレッドと1つのマネージャスレッドがあります。マルチスレッドX11アプリケーションとOpenGL

私はマネージャーのスレッドでイベントループを持っている:

while(true) 
    while(XQLength(mPlatformData->display)){ 
    XNextEvent(mPlatformData->display, &event); 
    std::cout << "event" << std::endl; 
    } 
} 

これは、シングルスレッドのアプリケーションのための素晴らしいイベントループですが、このマルチスレッドの設定で奇妙なことが起こります。

ウィンドウを作成しているときに、イベントキューを無効にするか、GLXMakeCurrentがハングしてスレッド全体が停止して何もしません。

マルチスレッドのX11アプリケーションに関する情報がネット上で見つからないため、イベントを別の方法で処理する必要がありますか?

+0

X11とOpenGLはスレッドが安全ではないと思います。 –

+2

GLは1つのコンテキスト/スレッドを使用するとスレッドセーフです。 X11のドキュメントによれば、XInitThreads()を最初に呼び出すと安全です。 – Dutow

答えて

2

Xlibには、同時アクセス状況で現れるいくつかの修正不可能な実行時の問題があることが知られています。私はあなたがそれらのうちの1つにぴったり合っていると推測しています。

これは、Xcbが最初に作成された理由の1つです.Xlibの問題を修正しました。 GLXはXlibに対して指定されているので、OpenGLについてはこれがショーストッパーのように見えるかもしれません。しかし、XlibはXCB周りがラップされ、1つは、安全GLXとのインターフェースと、まだプログラムの残りのためのXCBを使用するためにそれを使用することができます:http://xcb.freedesktop.org/opengl/

私は2つの解決策を参照してください。

  1. XLockDisplayを入れて/ muttexはXNextEventで、GLXはそれぞれを呼び出します。通常のOpenGLではロックする必要はありません。接頭辞はglX...です。

  2. Xcbを使用すると、ランタイムが正しく動作し、上記のリンク先のガイドに従ってOpenGL/GLXと動作させることができます。

+0

私はクイックフィックスとして最初のソリューションを実装しましたが、より良いソリューションがあることを願っています。私はもう1つ試みます。 – Dutow

1

レンダースレッドで何をしていますか?いずれの場合でも、異なるスレッド間でDisplay *接続を共有する場合は、XInitThreadsを呼び出す必要があります。

スレッドごとに1つのディスプレイ接続で良い経験をしました。メインスレッド上でイベントを取得するには、XSelectInputを使用します。ウィンドウIDは、異なるDisplay *接続間で共有可能です。

+1

OPについて:OPはXInitThreadsについて知っています。彼の質問に対する彼のコメントを参照してください。追加の 'Display *'接続を開くことはこれに対処する一つの方法です。残念ながら、それはまれなリソースを消費します。現在の形式のX11サーバーは、あまりにも少ない数の接続(クライアント)しかサポートしていません(256から1024の間のもの)。すべてのプロセスのスレッドのそれぞれが独自のディスプレイ接続を開いた場合、接続スロットが非常に速くなくなります。 – datenwolf

+1

複数のディスプレイ接続は、共有GLXContextを持つことができません - あるいは、それらを動作させることができませんでした。 – Dutow

+0

@Dutow:関連するコンテキストが間接的なレンダリングコンテキスト、すなわち直接=偽である場合にのみ、異なる接続間でGLXContextを共有できます。http://www.opengl.org/sdk/docs/man/xhtml/glXCreateContext.xmlを呼び出してください – datenwolf

2

XInitThreadsを使用していることを確認する必要があります。

アニメーションのウィンドウ描画を行うためにバックグラウンドスレッドを使用したとき、私はそれからいくつかの良い結果を得ることができました。あなたが描画コードに固執すれば、本当の問題はないようです。

これ以上のものが必要な場合や、低レベルのlibX11を使用している場合は、複数のX11接続を開いて最上位ウィンドウごとに1つの接続を使用するのが最善です。私は10年前、私がBeOSのクロスプラットフォームツールキットを開発して遊んだとき、すべてが悪い状態にあったときにそれをやっていました。

これは、イベント処理や最上位の子ウィンドウでも使用できます。しかし、これにはXEventマスクのための非常にトリッキーなコードが必要です。

+0

私はXInitThreadsを使用しています。複数のディスプレイ接続を使用することはできません。それらの間でGLXContextを共有することはできません。 – Dutow

関連する問題