多数の子 opengl ウィンドウを持つ wxWidgets アプリケーションがあります。wx ではなく、独自の GL キャンバス クラスを使用しています。ウィンドウは OpenGL コンテキストを共有します。それが wxwidgets であるという事実は、ここでは本当に関係がないと思います。
opengl ウィンドウは、互いに兄弟であるウィンドウの子であり、タブ コントロール内に含まれています。MDI スタイルのインターフェイスの一種ですが、MDI ウィンドウではありません。それぞれのサイズを個別に変更できます。Aero が有効になっていて、DWM がアクティブでない限り、すべてうまくいきます。
ウィンドウのサイズを変更すると (opengl のウィンドウでさえも)、すべての opengl ウィンドウがちらつき、その時点で画面に表示されていたゴミ (opengl ではない) を含む古いバッキング ストア ビューが表示されます。これは、Aero が有効になっている場合にのみ発生します。
これは、DWM が描画面のバッキング ストアに実際に opengl のコンテンツを持っておらず、ウィンドウが適切なタイミングで再描画されていないことであると確信しています。
私はこれを回避するために非常に多くのことを試みましたが、解決策はありますが、あまり良くなく、glReadPixels を使用してフレームバッファーを DIB に読み取り、それを onPaint ルーチンでペイント DC にブリットする必要があります。この回避策は、DWM がアクティブな場合にのみ有効になりますが、パフォーマンスがわずかに低下するため、これを行う必要はまったくありません (ただし、対応するシステムではそれほど悪くはありません - シーンは比較的単純な 3D グラフです)。また、GDI と opengl を混在させることはお勧めしませんが、このアプローチは驚くほど機能します。私は今のところそれと一緒に暮らすことができますが、そうする必要はありません. とにかく子ウィンドウのスクリーンショットを撮りたい場合は、WM_PRINTでこれを行う必要がありますが、それを回避する方法がわかりません。
これに対するより良い解決策を知っている人はいますか?
誰かが尋ねる前に、私は間違いなく次のことを行います。
- ウィンドウ クラスには CS_OWNDC があります
- WM_ERASEBACKGROUND は何もせず、TRUE を返します。
- ダブルバッファリングが有効になっています。
- ウィンドウには、WS_CLIPSIBLINGS および WS_CLIPCHILDREN ウィンドウ スタイルがあります。
- サイズ変更イベント ハンドラーで、すぐにウィンドウを再描画します。
私はもう試した:
- ピクセル形式記述子で PFD_SUPPORT_COMPOSITION を設定します。
- ペイント ハンドラで wxPaintDC を使用せず、代わりに ::ValidateRect(hwnd, NULL) を呼び出します。
- WM_NCPAINT の処理とクライアント領域の除外
- DWM API による NC ペイントの無効化
- ペイント イベントでクライアント領域を除外する
- バッファ スワップの前後に glFlush や glFinish を呼び出します。
- ペイント イベントごとにウィンドウを無効にする (テストとして!) - まだちらつきます!
- 共有 GL コンテキストを使用しない。
- ダブルバッファリングを無効にします。
- GL_FRONT_AND_BACK への書き込み
DWM を無効にすることはできません。
そして、私が知る限り、OpenGLで代わりに Direct3D を使用している場合、これは問題でさえありますが、これは多くの作業を表すためテストしていません。