本編と動画で描画経路が分かれていた
Artemis Engine系の32bitタイトルで、本編は正常に描画できる一方、起動ロゴとオープニング動画だけが白くなった。動画終了後は本編へ戻るため、停止ではなく動画表示経路に限定された問題だった。
本編の描画そのものは正常
起動ロゴとオープニングがともに白い
動画フレームは前面描画まで到達する
通常の表示更新は0回
検証した修正案
前面描画の実経路、実行スレッド、swapの副作用を順に確認し、3案を棄却した。
動画のフレーム更新を、描画の"通常の更新"経路でフックする棄却
既存のfront-buffer更新フックを利用する案を試した。
swapchain_frontbuffer_updatedを通らず、DirectDraw側で直接前面へ描いていた。今アクティブな描画の窓口から、隠れたビューを取得する棄却
呼び出しスレッドのOpenGL contextから対象ビューを取得する案を試した。
ctx=0x0だった。DirectDrawのblitはwined3dのワーカースレッドで動き、そこにcurrent contextはなかった。素直に、通常の更新と同じ「表示入れ替え」を動画側からも呼ぶ棄却
動画更新後に通常と同じswapを呼ぶ案を検討した。
ウィンドウそのものから隠れたビューを辿り、入れ替えなしで表に出すだけ確定
DirectDrawから渡したウィンドウハンドル(HWND)を使い、winemac側で対象のOpenGL子ビューを解決する。
swapの有無で表示結果を比較する
動画フレームは既にfront bufferへ描画されている。必要なのはbufferの入れ替えではなく、隠れているOpenGL子ビューの表示だった。
起動ロゴの黒画面を分けて修正する
オープニングを表示できた後も、起動直後のロゴ動画は黒くなった。これは表示契機ではなく、OpenGL drawableの準備前に最初のフレームを描いていた別問題だった。
OpenGL子ビューはhiddenで生成され、画面上へ出るまでdrawable surfaceを持たない。ロゴの初期化待ちを省く設定では、surfaceの準備前に描画が始まり、FBO incompleteが発生していた。そこでopenGLTargetViewの生成時に子ビューを先に表示し、レンダー前にsurfaceを準備した。
調査手順
実際の起動条件を再現し、経路、スレッド、配備物、ログなしの最終結果を順に確認した。
本番と同じ起動条件でトレースを取る
launcherの設定を再現したハーネスを使い、動画フレーム更新と表示更新の回数を同じrunで記録した。
未発火のフックから実経路を絞る
既存フックが0回だったため、wined3dのswapchainではなくDirectDrawのfront-buffer更新へ観測点を移した。
修正案ごとに副作用を確認する
swapを追加する前に前面/背面bufferの状態を確認し、描画済みフレームを消す案を棄却した。
実際にロードされるruntimeを照合する
ソース、ビルド出力、app bundleは別物として扱い、ロード先のwinemac/ddrawをハッシュで照合した。
診断ログを外して再検証する
ログがタイミングへ影響することを確認したため、最終buildでは診断出力を除き、ロゴとオープニングを取り直した。
観測結果
観測 A ── トレースの集計
動画のフレーム更新 ── 150 回(フルラン) 可視領域への描画情報 ── 300 回(非空) 通常の表示更新(swap) ── 0 回 ────────────────────── ∴ フレームは画面に届いているのに、 表示更新の合図が一度も出ていない
動画フレームと描画領域は存在する一方、通常のswapは発生していなかった。
観測 B ── スレッドの診断
案2の実装で仕込んだ診断ログ: note_frontbuffer_flush #1 ctx=0x0 note_frontbuffer_flush #2 ctx=0x0 ... #3〜#8 すべて ctx=0x0 → 描画の窓口は、動画を更新している スレッドにはカレントでない
動画更新スレッドにcurrent contextはなく、HWNDを基点にした解決が必要だった。
観測 C ── 修正前後の実機結果
修正前: オープニング動画 ── 真っ白 起動ロゴ動画 ── 真っ白 修正後(一次): オープニング動画 ── ✅ 表示 起動ロゴ動画 ── 黒に反転 修正後(最終・ログ無し): オープニング動画 ── ✅ 起動ロゴ動画 ── ✅ 効果音の乱れ ── ✅ 解消 セーブ/ロード等 ── ✅ 異常なし
overlay表示とsurface早期準備を分けて適用し、ログなしの実機runでロゴとオープニングを確認した。
再利用できる知見
実際に発火する経路を測る
既存フックが論理上近くても、0回なら実経路ではない。回数計測から観測点を移す。
実行スレッドのcontextに依存しない
描画処理と更新通知が別スレッドなら、共有できるHWNDなどの識別子から対象を解決する。
表示済みbufferへswapを重ねない
front bufferへ直接描く経路では、通常のswapが描画済みフレームを消す可能性がある。
ログなしの最終条件を確認する
診断出力は競合や初期化待ちの時間を変える。観測buildと受入buildを分ける。
ソースではなくロード実体を照合する
修正の到達は、実際にロードされるwinemac/ddrawのハッシュで確認する。
現在の状態と適用範囲
- 対象はArtemis 32bitで、本編がDXVK/Metal、動画がVMR-7→DirectDraw→wined3d/OpenGLの構成。
- 2026-07-01の実機確認で、起動ロゴ、オープニング動画、効果音を確認した。
- 再ビルドで修正を失わないよう、ddrawとwinemacの採用バイナリを再現性台帳で管理している。
- 動画白画面をすべて同じ原因へ一般化しない。GStreamer環境、registry、renderer、音声初期化には別の原因がある。
- Metalビューを使わない構成では早期表示処理は構造上no-opだが、全エンジンの実機非回帰を完了したという意味ではない。
- SEノイズの再発はmovie修正ではなく、別のdsound artifactの配備漏れだった。