IDXGIOutputDuplication
COM公式ドキュメント
IDXGIOutputDuplication インターフェイスは、複製されたデスクトップイメージにアクセスして操作します。
解説(Remarks)
コラボレーションアプリケーションは、IDXGIOutputDuplication を使用してデスクトップイメージにアクセスできます。IDXGIOutputDuplication は、8bpp 以外の DirectX 全画面モードおよび 8bpp 以外の OpenGL 全画面モードにおいて、デスクトップ ウィンドウ マネージャー (DWM) でサポートされます。16 ビットまたは 32 ビットの GDI による非 DWM デスクトップモードはサポートされません。
アプリケーションは、別のスレッドで IDXGIOutputDuplication を使用してデスクトップイメージを受け取り、それを独自の画像処理パイプラインに渡すことができます。アプリケーションは IDXGIOutputDuplication を使用して、次の操作を実行します。
- 次のデスクトップイメージを取得します。
- イメージを記述する情報を取得します。
- イメージに対して操作を実行します。この操作は、アプリケーションがイメージのピクセルデータを読み取れるように、イメージをステージングバッファーにコピーするだけの単純なものにすることもできます。アプリケーションは、IDXGISurface::Map を呼び出した後にピクセルデータを読み取ります。あるいは、この操作をより複雑なものにすることもできます。たとえば、アプリケーションはイメージの更新された領域に対していくつかのピクセルシェーダーを実行し、それらの領域をクライアントへの送信用にエンコードできます。
- アプリケーションは各デスクトップイメージの処理を終えると、そのイメージを解放し、手順 1 に戻ってこれらの手順を繰り返します。アプリケーションは、デスクトップイメージの処理が完了するまでこれらの手順を繰り返します。
- デスクトップイメージを合成する DWM
- 全画面の DirectX または OpenGL アプリケーション
- 別のデスクトップ (たとえば、ログイン画面の表示に使用されるセキュアデスクトップ) への切り替えを行うアプリケーション
IDXGIOutputDuplication が無効になる状況の例を次に示します。
- デスクトップの切り替え
- モード変更
- DWM のオン/オフの切り替え、または他の全画面アプリケーションへの切り替え
アプリケーションが各デスクトップイメージを処理している間、オペレーティングシステムはすべてのデスクトップイメージの更新を 1 つの更新にまとめて蓄積します。デスクトップの更新の詳細については、「デスクトップイメージデータの更新」を参照してください。
デスクトップイメージは常に DXGI_FORMAT_B8G8R8A8_UNORM 形式です。
IDXGIOutputDuplication インターフェイスは、Windows ストアアプリには存在しません。
メソッド 8
vtbl = vtable インデックス(0始まり)。HSP等からCOMメソッドをインデックス指定で呼ぶ際に使用します。0〜2 は IUnknown。
複製された出力 (アウトプット) の記述を取得します。この記述は、デスクトップイメージを格納するサーフェスの寸法を指定します。
| pDesc | DXGI_OUTDUPL_DESC* | out | 複製された出力 (アウトプット) を記述する DXGI_OUTDUPL_DESC 構造体へのポインター。このパラメーターを NULL にすることはできません。 |
解説(Remarks)
アプリケーションは IDXGIOutputDuplication インターフェイスを作成した後、GetDesc を呼び出して、デスクトップイメージを格納するサーフェスの寸法を取得します。デスクトップイメージの形式は常に DXGI_FORMAT_B8G8R8A8_UNORM です。
アプリケーションが次のデスクトップイメージを処理する準備ができたことを示します。
| TimeoutInMilliseconds | DWORD | in | タイムアウト間隔 (ミリ秒単位)。この間隔は、このメソッドが呼び出し元に制御を返す前に新しいフレームを待機する時間を指定します。この間隔が経過しても新しいデスクトップイメージが利用できない場合、このメソッドは制御を返します。 タイムアウト間隔の詳細については、「解説」を参照してください。 |
| pFrameInfo | DXGI_OUTDUPL_FRAME_INFO* | out | フレームのタイミングおよび表示 (プレゼント) 統計を記述する DXGI_OUTDUPL_FRAME_INFO 構造体を受け取るメモリ位置へのポインター。 |
| ppDesktopResource | IDXGIResource** | out | デスクトップビットマップを格納するサーフェスの IDXGIResource インターフェイスを受け取る変数へのポインター。 |
戻り値
AcquireNextFrame は次の値を返します。
- 次のデスクトップイメージを正常に受信した場合は S_OK。
- デスクトップ複製インターフェイスが無効な場合は DXGI_ERROR_ACCESS_LOST。デスクトップ複製インターフェイスは、通常、別の種類のイメージがデスクトップに表示されると無効になります。この状況の例を次に示します。
- デスクトップの切り替え
- モード変更
- DWM のオン/オフの切り替え、または他の全画面アプリケーションへの切り替え
- 次のデスクトップフレームが利用可能になる前にタイムアウト間隔が経過した場合は DXGI_ERROR_WAIT_TIMEOUT。
- アプリケーションが前のフレームを解放せずに AcquireNextFrame を呼び出した場合は DXGI_ERROR_INVALID_CALL。
- AcquireNextFrame のいずれかのパラメーターが正しくない場合 (たとえば pFrameInfo が NULL の場合) は E_INVALIDARG。
- その他、DXGI_ERROR トピックで説明されているエラーコードが返される場合があります。
解説(Remarks)
AcquireNextFrame が正常に返ると、呼び出し元のアプリケーションは、AcquireNextFrame が ppDesktopResource の変数に返すデスクトップイメージにアクセスできます。 呼び出し元が TimeoutInMilliseconds パラメーターにゼロのタイムアウト間隔を指定した場合、AcquireNextFrame は新しいデスクトップイメージが利用可能かどうかを確認し、直ちに制御を返して、その結果を戻り値で示します。呼び出し元が TimeoutInMilliseconds パラメーターに INFINITE のタイムアウト間隔を指定した場合、タイムアウト間隔は決して経過しません。
現在のデスクトップフレームのダーティ矩形に関する情報を取得します。
| DirtyRectsBufferSize | DWORD | in | 呼び出し元が pDirtyRectsBuffer パラメーターに渡したバッファーのサイズ (バイト単位)。 |
| pDirtyRectsBuffer | RECT* | out | デスクトップフレームのダーティ矩形領域を識別する RECT 構造体の配列へのポインター。 |
| pDirtyRectsBufferSizeRequired | DWORD* | out | GetFrameDirtyRects が pDirtyRectsBuffer のバッファーにダーティ領域に関する情報を格納するために必要なバイト数を受け取る変数へのポインター。 必要なバッファーサイズの返し方の詳細については、「解説」を参照してください。 |
戻り値
GetFrameDirtyRects は次の値を返します。
- ダーティ矩形に関する情報を正常に取得した場合は S_OK。
- デスクトップ複製インターフェイスが無効な場合は DXGI_ERROR_ACCESS_LOST。デスクトップ複製インターフェイスは、通常、別の種類のイメージがデスクトップに表示されると無効になります。この状況の例を次に示します。
- デスクトップの切り替え
- モード変更
- DWM のオン/オフの切り替え、または他の全画面アプリケーションへの切り替え
- 呼び出し元のアプリケーションが指定したバッファーが十分な大きさでなかった場合は DXGI_ERROR_MORE_DATA。
- アプリケーションがデスクトップイメージを所有せずに GetFrameDirtyRects を呼び出した場合は DXGI_ERROR_INVALID_CALL。
- GetFrameDirtyRects のいずれかのパラメーターが正しくない場合 (たとえば pDirtyRectsBuffer が NULL の場合) は E_INVALIDARG。
- その他、DXGI_ERROR トピックで説明されているエラーコードが返される場合があります。
解説(Remarks)
GetFrameDirtyRects は、pDirtyRectsBufferSizeRequired の変数にサイズ値を格納します。この値は、GetFrameDirtyRects がダーティ領域に関する情報を格納するために必要なバイト数を指定します。この値は、pDirtyRectsBuffer に渡す今後のバッファーに割り当てるメモリ量を決定するために、次の状況で使用できます。
- GetFrameDirtyRects がバッファーの大きさが十分でないために DXGI_ERROR_MORE_DATA で失敗する場合。
- GetFrameDirtyRects に必要以上に大きなバッファーを渡した場合。pDirtyRectsBufferSizeRequired に返されるサイズ値は、呼び出し元が割り当てて DirtyRectsBufferSize パラメーターに指定したバッファー領域に対して、実際に使用されたバッファー領域の大きさを呼び出し元に通知します。
バッファーには、現在のフレームのダーティ RECT のリストが含まれます。
現在のデスクトップフレームの移動された矩形に関する情報を取得します。
| MoveRectsBufferSize | DWORD | in | 呼び出し元が pMoveRectBuffer パラメーターに渡したバッファーのサイズ (バイト単位)。 |
| pMoveRectBuffer | DXGI_OUTDUPL_MOVE_RECT* | out | デスクトップフレームの移動された矩形領域を識別する DXGI_OUTDUPL_MOVE_RECT 構造体の配列へのポインター。 |
| pMoveRectsBufferSizeRequired | DWORD* | out | GetFrameMoveRects が pMoveRectBuffer のバッファーに移動された領域に関する情報を格納するために必要なバイト数を受け取る変数へのポインター。 必要なバッファーサイズの返し方の詳細については、「解説」を参照してください。 |
戻り値
GetFrameMoveRects は次の値を返します。
- 移動された矩形に関する情報を正常に取得した場合は S_OK。
- デスクトップ複製インターフェイスが無効な場合は DXGI_ERROR_ACCESS_LOST。デスクトップ複製インターフェイスは、通常、別の種類のイメージがデスクトップに表示されると無効になります。この状況の例を次に示します。
- デスクトップの切り替え
- モード変更
- DWM のオン/オフの切り替え、または他の全画面アプリケーションへの切り替え
- 呼び出し元のアプリケーションが指定したバッファーが十分な大きさでない場合は DXGI_ERROR_MORE_DATA。
- アプリケーションがデスクトップイメージを所有せずに GetFrameMoveRects を呼び出した場合は DXGI_ERROR_INVALID_CALL。
- GetFrameMoveRects のいずれかのパラメーターが正しくない場合 (たとえば pMoveRectBuffer が NULL の場合) は E_INVALIDARG。
- その他、DXGI_ERROR トピックで説明されているエラーコードが返される場合があります。
解説(Remarks)
GetFrameMoveRects は、pMoveRectsBufferSizeRequired の変数にサイズ値を格納します。この値は、GetFrameMoveRects が移動された領域に関する情報を格納するために必要なバイト数を指定します。この値は、pMoveRectBuffer に渡す今後のバッファーに割り当てるメモリ量を決定するために、次の状況で使用できます。
- GetFrameMoveRects がバッファーの大きさが十分でないために DXGI_ERROR_MORE_DATA で失敗する場合。
- GetFrameMoveRects に必要以上に大きなバッファーを渡した場合。pMoveRectsBufferSizeRequired に返されるサイズ値は、呼び出し元が割り当てて MoveRectsBufferSize パラメーターに指定したバッファー領域に対して、実際に使用されたバッファー領域の大きさを呼び出し元に通知します。
バッファーには、現在のフレームの移動 RECT のリストが含まれます。
現在のデスクトップフレームの新しいポインター形状に関する情報を取得します。
| PointerShapeBufferSize | DWORD | in | 呼び出し元が pPointerShapeBuffer パラメーターに渡したバッファーのサイズ (バイト単位)。 |
| pPointerShapeBuffer | void* | out | GetFramePointerShape が新しいポインター形状のピクセルデータをコピーして返すバッファーへのポインター。 |
| pPointerShapeBufferSizeRequired | DWORD* | out | GetFramePointerShape が pPointerShapeBuffer のバッファーに新しいポインター形状のピクセルデータを格納するために必要なバイト数を受け取る変数へのポインター。 必要なバッファーサイズの返し方の詳細については、「解説」を参照してください。 |
| pPointerShapeInfo | DXGI_OUTDUPL_POINTER_SHAPE_INFO* | out | ポインター形状情報を受け取る DXGI_OUTDUPL_POINTER_SHAPE_INFO 構造体へのポインター。 |
戻り値
GetFramePointerShape は次の値を返します。
- 新しいポインター形状に関する情報を正常に取得した場合は S_OK。
- デスクトップ複製インターフェイスが無効な場合は DXGI_ERROR_ACCESS_LOST。デスクトップ複製インターフェイスは、通常、別の種類のイメージがデスクトップに表示されると無効になります。この状況の例を次に示します。
- デスクトップの切り替え
- モード変更
- DWM のオン/オフの切り替え、または他の全画面アプリケーションへの切り替え
- 呼び出し元のアプリケーションが指定したバッファーが十分な大きさでなかった場合は DXGI_ERROR_MORE_DATA。
- アプリケーションがデスクトップイメージを所有せずに GetFramePointerShape を呼び出した場合は DXGI_ERROR_INVALID_CALL。
- GetFramePointerShape のいずれかのパラメーターが正しくない場合 (たとえば pPointerShapeInfo が NULL の場合) は E_INVALIDARG。
- その他、DXGI_ERROR トピックで説明されているエラーコードが返される場合があります。
解説(Remarks)
GetFramePointerShape は、pPointerShapeBufferSizeRequired の変数にサイズ値を格納します。この値は、pPointerShapeBufferSizeRequired が新しいポインター形状のピクセルデータを格納するために必要なバイト数を指定します。この値は、pPointerShapeBuffer に渡す今後のバッファーに割り当てるメモリ量を決定するために、次の状況で使用できます。
- GetFramePointerShape がバッファーの大きさが十分でないために DXGI_ERROR_MORE_DATA で失敗する場合。
- GetFramePointerShape に必要以上に大きなバッファーを渡した場合。pPointerShapeBufferSizeRequired に返されるサイズ値は、呼び出し元が割り当てて PointerShapeBufferSize パラメーターに指定したバッファー領域に対して、実際に使用されたバッファー領域の大きさを呼び出し元に通知します。
デスクトップイメージが既にシステムメモリ内にある場合に、そのデスクトップイメージへの効率的なアクセスを CPU に提供します。
| pLockedRect | DXGI_MAPPED_RECT* | out | CPU がサーフェスデータに直接アクセスするために必要なサーフェスデータを受け取る DXGI_MAPPED_RECT 構造体へのポインター。 |
戻り値
MapDesktopSurface は次の値を返します。
- サーフェスデータを正常に取得した場合は S_OK。
- デスクトップ複製インターフェイスが無効な場合は DXGI_ERROR_ACCESS_LOST。デスクトップ複製インターフェイスは、通常、別の種類のイメージがデスクトップに表示されると無効になります。この状況の例を次に示します。
- デスクトップの切り替え
- モード変更
- DWM のオン/オフの切り替え、または他の全画面アプリケーションへの切り替え
- アプリケーションがデスクトップイメージに対して未解決のマップを既に持っている場合は DXGI_ERROR_INVALID_CALL。アプリケーションは、MapDesktopSurface を再度呼び出す前に UnMapDesktopSurface を呼び出す必要があります。また、MapDesktopSurface を呼び出したときにアプリケーションがデスクトップイメージを所有していなかった場合も DXGI_ERROR_INVALID_CALL が返されます。
- デスクトップイメージがシステムメモリ内にない場合は DXGI_ERROR_UNSUPPORTED。この状況では、アプリケーションはまずイメージをステージングサーフェスに転送し、その後 IDXGISurface::Map メソッドを呼び出してイメージをロックする必要があります。
- pLockedRect パラメーターが正しくない場合 (たとえば pLockedRect が NULL の場合) は E_INVALIDARG。
- その他、DXGI_ERROR トピックで説明されているエラーコードが返される場合があります。
解説(Remarks)
DXGI_OUTDUPL_DESC 構造体の DesktopImageInSystemMemory メンバーが TRUE に設定されている場合、MapDesktopSurface を正常に呼び出すことができます。DesktopImageInSystemMemory が FALSE の場合、MapDesktopSurface は DXGI_ERROR_UNSUPPORTED を返します。DXGI_OUTDUPL_DESC 構造体を取得するには、IDXGIOutputDuplication::GetDesc を呼び出します。
IDXGIOutputDuplication::MapDesktopSurface を使用して取得したデスクトップイメージへのポインターを無効化します。
戻り値
UnMapDesktopSurface は次の値を返します。
- 正常に完了した場合は S_OK。
- アプリケーションが IDXGIOutputDuplication::MapDesktopSurface を呼び出してデスクトップサーフェスをマップしていなかった場合は DXGI_ERROR_INVALID_CALL。
- その他、DXGI_ERROR トピックで説明されているエラーコードが返される場合があります。
アプリケーションがフレームの処理を終了したことを示します。
戻り値
ReleaseFrame は次の値を返します。
- 正常に完了した場合は S_OK。
- アプリケーションが既にフレームを解放している場合は DXGI_ERROR_INVALID_CALL。
- デスクトップ複製インターフェイスが無効な場合は DXGI_ERROR_ACCESS_LOST。デスクトップ複製インターフェイスは、通常、別の種類のイメージがデスクトップに表示されると無効になります。この状況の例を次に示します。
- デスクトップの切り替え
- モード変更
- DWM のオン/オフの切り替え、または他の全画面アプリケーションへの切り替え
- その他、DXGI_ERROR トピックで説明されているエラーコードが返される場合があります。
解説(Remarks)
アプリケーションは、次のフレームを取得する前に、フレームを解放する必要があります。フレームを解放すると、デスクトップビットマップを格納するサーフェスは無効になり、そのサーフェスを DirectX グラフィックス操作で使用できなくなります。
パフォーマンス上の理由から、次のフレームを取得する IDXGIOutputDuplication::AcquireNextFrame メソッドを呼び出す直前にフレームを解放することをお勧めします。クライアントがフレームを所有していない場合、オペレーティングシステムはすべてのデスクトップの更新をサーフェスにコピーします。これにより、オペレーティングシステムが発生する各フレームで同じ領域を更新すると、GPU サイクルが無駄になる可能性があります。クライアントがフレームを取得すると、クライアントはこの領域に対する最終的な更新のみを認識します。そのため、以前のフレームでの重複する更新はすべて無駄になります。クライアントがフレームを取得すると、クライアントはサーフェスを所有するため、オペレーティングシステムは更新された領域のみを追跡でき、デスクトップの更新をサーフェスにコピーできません。この動作のため、現在のフレームを解放する呼び出しと次のフレームを取得する呼び出しの間の時間を最小限に抑えることをお勧めします。
Microsoft 公式リファレンス: 英語 (en-us) · 日本語 (ja-jp) · 原文ソース (GitHub)
HSP用 COM定義
#usecom / #comfunc によるHSPのCOM呼び出し定義。数字は vtbl インデックス(0始まり)。クラスIDが無い場合 #usecom の末尾は "{}"、ある場合は "{CLSID}"。
#define global IID_IDXGIOutputDuplication "{191CFAC3-A341-470D-B26E-A864F428319C}" #usecom global IDXGIOutputDuplication IID_IDXGIOutputDuplication "{}" #comfunc global IDXGIOutputDuplication_GetDesc 7 var #comfunc global IDXGIOutputDuplication_AcquireNextFrame 8 int,var,sptr #comfunc global IDXGIOutputDuplication_GetFrameDirtyRects 9 int,var,var #comfunc global IDXGIOutputDuplication_GetFrameMoveRects 10 int,var,var #comfunc global IDXGIOutputDuplication_GetFramePointerShape 11 int,sptr,var,var #comfunc global IDXGIOutputDuplication_MapDesktopSurface 12 var #comfunc global IDXGIOutputDuplication_UnMapDesktopSurface 13 #comfunc global IDXGIOutputDuplication_ReleaseFrame 14 ; ※数字は vtbl インデックス(0始まり)。0/1/2 は IUnknown(QueryInterface/AddRef/Release)。 ; ※このインターフェースは直接 CoCreateInstance するクラスIDが無いため "{}"(他メソッド/アクティベーションで取得)。 ; ※出力/バッファ引数は var(変数直渡し)。varptr 方式にも切替可。 ; ※ハンドル/void*等の不透明ポインタは IronHSP では intptr 指定が可能。#define global IID_IDXGIOutputDuplication "{191CFAC3-A341-470D-B26E-A864F428319C}" #usecom global IDXGIOutputDuplication IID_IDXGIOutputDuplication "{}" #comfunc global IDXGIOutputDuplication_GetDesc 7 sptr #comfunc global IDXGIOutputDuplication_AcquireNextFrame 8 int,sptr,sptr #comfunc global IDXGIOutputDuplication_GetFrameDirtyRects 9 int,sptr,sptr #comfunc global IDXGIOutputDuplication_GetFrameMoveRects 10 int,sptr,sptr #comfunc global IDXGIOutputDuplication_GetFramePointerShape 11 int,sptr,sptr,sptr #comfunc global IDXGIOutputDuplication_MapDesktopSurface 12 sptr #comfunc global IDXGIOutputDuplication_UnMapDesktopSurface 13 #comfunc global IDXGIOutputDuplication_ReleaseFrame 14 ; ※数字は vtbl インデックス(0始まり)。0/1/2 は IUnknown(QueryInterface/AddRef/Release)。 ; ※このインターフェースは直接 CoCreateInstance するクラスIDが無いため "{}"(他メソッド/アクティベーションで取得)。 ; ※出力/バッファ引数はポインタ方式(token=sptr / 呼び出しは varptr(変数))。 ; ※ハンドル/void*等の不透明ポインタは IronHSP では intptr 指定が可能。