『Direct3D』でフルスクリーン表示をした時に
『DirectShow』での画像が表示されない事がある…。
ウインドウでは起きない…。
『DirectShow』のエラーも出ていない…。
…
何が悪いんだろう?
ちなみに現象が起きた条件。
・C++
・DirectX8
・Direct3D
・DirectShow
・フルスクリーン表示
…
一度画像が再生されないともう再生されないかと思ったら
そうでもない。
何かがハングとかしている訳ではなさそうだ…。
取り敢えず傾向を見るために100回ぐらい
ムービー再生のテストをしてみる…。
…
どうも二分の一の確立で表示されないようだ…。
これは、どういう事だろうか?
…
ムービーが表示される画面と表示されない画面があって
その二つの画面が高速に入れ替わっているように思える…。
そのタイミングによって表示されたり表示されなかったり…。
…
多分『Direct3D』が悪さをしているんだろう…。
ありあえるのは、フリップによるフロントサーフェスと
バックサーフェスの切り換えが影響していると
当たりを付けてみる。
…
ざっくり3D出力関連をこんな感じにコメントアウトしてみる。
#if 0
Device->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_STENCIL | D3DCLEAR_ZBUFFER, 0, 1.0f, 0 )
Device->BeginScene( );
...
Device->EndScene( );
Device->Present( NULL, NULL, NULL, NULL );
#endif
…
問題無くムービーが再生される…。
…
どうやら「Clear/BeginScene/Present」のどれかが呼ばれると
フリップが起こり表示されなくなるようだ…。
…
ムービー再生中に『Present』を連続して呼び出すと再生される…。
無論、黒い画面が入ってパカル訳だが傾向は、得られたと思う。
…
結論、『Direct3D』が悪さしている!<と断定!
…
実際、ここまで来るのに数日間かけて結構試行錯誤…。(涙)
…
『DirectShow』は、ウインドウ周りでの処理で『HDC』を介して『BitBlt』
辺りでデスクトップに貼り付けているのではないだろうか?
と推測。
何らかの理由で『HDC』の出力先が切り替わっているのでは?
だったら必ず表示される方にしてムービーを再生すればOKじゃないのか?
どうやったら2つのサーフェスのどちらが表かを区別できるのだろう?
調べてみる…。
…
…
…
どうやら、そのような関数は、無いようだ…。
ヘルプには、「良い感じに切り換えている」とある…。
…
カウンターを付けてみたが単に傾向が何となく分かるだけで
間違いなくこっちと言えなさそうだ…。
…
もし、『DirectShow』が『HDC』経由で何処かに出力されているのなら
表示されなくても画像はあるだろう…。
と『HDC』経由で画像を引っ張り出してテクスチャーに張って
表示できるようにしたのだが…
メチャメチャ重い…。
それに表示されない時には、表示されない…。
まあ、何かミスってる可能性は、大だが…。
正直重過ぎて使い物にならないので没!
…
『HDC』での出力と『Direct3D』との出力で齟齬があれば
それを手掛かりに確認できるかも?
何処に出力されているのか分からないので『HDC』経由で
プット&ゲットしてみるが、同じ物が返ってくる…。
…
テストを行っていると不思議な現象を見付けた。
『HDC』経由で画面に出力したら即座に表示される時と
表示されない時がある。
もしかしたら、これが『HDC』と『Direct3D』の出力の齟齬!?
『HDC』でプットして『Direct3D』でゲットして異なれば正常とか…。
一条の希望の光を見えたような気がした…。
…
試してみた…。
『HDC』経由で画面に出力して即座に表示される時には、
『GetRenderTarget』で画像を得られない。
『HDC』経由で画面に出力しても即座に表示されない時には、
『GetRenderTarget』で画像を得られた!
これでムービーを確実に表示する方法を見付けたよ!
マジ祝杯もんス!
----------------------------------------
検証プログラムを作ろうかと思ったが…
メチャメチャ長くなるので…
チェック処理の所だけね。
説明少ないけど、足りない分は察して頂戴。
今回珍しく動作確認していなので間違いがあるかも…。(汗)
と言う訳でヒント程度に参考にして頂戴…。
処理の流れは、「WindowDC」で画像を出力し
「GetRenderTarget」で画像を取得し
比較すると言ったもの。
----------------------------------------
LPBYTE Pixel;
----------------------------------------
void RenderTargetCopy( void )
{
LPDIRECT3DSURFACE8 Render;
LPDIRECT3DSURFACE8 Bitmap;
D3DSURFACE_DESC Desc;
D3DLOCKED_RECT Rect;
Device->GetRenderTarget( &Render );
Render->GetDesc( &Desc );
Device->CreateImageSurface( Desc.Width, Desc.Height, D3DFMT_R8G8B8, &Bitmap );
D3DXLoadSurfaceFromSurface( Bitmap, NULL, NULL, Render, NULL, NULL, D3DX_FILTER_NONE, 0 );
Bitmap->LockRect( &Rect, NULL, D3DLOCK_READONLY );
memcpy( Pixel, Rect.pBits, Desc.Height * Rect.Pitch );
Bitmap->UnlockRect( );
Bitmap->Release( );
Render->Release( );
}
----------------------------------------
// フルスクリーンならフロントサーフェスが後ろに行っていたら前に出します。
if( FullScreenFlag )
{
for( i = 0 ; i < 10 ; i++ )
{
// 「BitmapDC」は、画面の大きさの真っ白な画像です。
// 「WindowDC」は、ウインドウ作成時に取得しておきます。
BitBlt( WindowDC, 0, 0, Width, Height, BitmapDC, 0, 0, SRCCOPY );
// レンダリングターゲットの画像を取り出します。
RenderTargetCopy( );
// 画像情報が一致したら脱出します。
if( ( *( LPDWORD )Pixel != 0xFFFFFFFF )
break;
// 「Direct3D」を使って画面をクリアします。
// これでフロントサーフェスがフィリップされます。
Device->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_STENCIL | D3DCLEAR_ZBUFFER, 0, 1, 0 );
Device->BeginScene( );
Device->EndScene( );
Device->Present( NULL, NULL, NULL, NULL );
}
}
// 『DirectShow』のムービー再生処理へ
----------------------------------------
PS.
『HDC』は、バックサーフェスに関連付けられ
『DirectShow』は、フロントサーフェスに関連付けられ
それらの関連付けは、固定されているようです。
従ってバックサーフェスがレンダリングサーフェスの時、
『HDC』でのプットは、画面上に表示されません。
しかしレンダリングサーフェスから画像を得られます。
逆にフロントサーフェスがレンダリングサーフェスの時、
『HDC』でのプットは、画面上に表示されますが
レンダリングサーフェスから画像を得られません。
フィリップによってフロントサーフェスが
レンダリングサーフェスの時には、
『DirectShow』の画像が表示されなくなる
という事になるらしい…。
フィリップに関係無く『HDC』と『DirectShow』は、
画面に出力されるべきじゃない?
これって『Direct3D』の不具合だろう!
…と思うのだが…。
多分『Direct3D』を使っている奴等は、
『HDC』や『DirectShow』を使わないのかもしれない…。
…多分そうに違いない…。
最近のコメント