次の方法で共有


PDD_SURFCB_LOCK コールバック関数 (ddrawint.h)

DdLock コールバック関数は、指定されたサーフェス メモリ領域をロックし、サーフェスに関連付けられているメモリ ブロックへの有効なポインターを提供します。

構文

PDD_SURFCB_LOCK PddSurfcbLock;

DWORD PddSurfcbLock(
  PDD_LOCKDATA unnamedParam1
)
{...}

パラメーター

unnamedParam1

ロックダウンの実行に必要な情報を含む DD_LOCKDATA 構造体を指します。

戻り値

DdLock は 、次のいずれかのコールバック コードを返します。

注釈

DdLock、lpLock のDD_LOCKDATA構造体の ddRVal メンバーをDDERR_WASSTILLDRAWINGに設定し、blit またはフリップが進行中の場合はDDHAL_DRIVER_HANDLEDを返す必要があります。

DD_LOCKDATAの dwFlags メンバーで特に指定されていない限り、ドライバーは、DD_LOCKDATAの lpSurfData メンバー内のサーフェスの上部へのメモリ ポインターを返すことができます。 ドライバーがサーフェスの独自のアドレスを計算する必要がある場合は、DirectDraw でアクセス可能なフレーム バッファーのユーザー モード マッピングへのプロセスごとのポインターとして、DD_LOCKDATA の fpProcess メンバーに渡されるポインターに依存できます。

ロックでは、要求されたメモリ ブロックへの排他的アクセスは提供されません。つまり、複数のスレッドが同時に同じサーフェスをロックできます。 ポインターが取得されているメモリ ブロックへのアクセスを同期するのは、アプリケーションの責任です。

NT ベースのオペレーティング システムで実行されているドライバーは、そのドライバーの DdCreateSurface 関数が以前にPLEASE_ALLOC_USERMEM フラグを持つこのようなメモリを割り当てない限り、その DdLock 関数からシステム メモリへのポインターを返す必要があります。 PLEASE_ALLOC_USERMEMを使用しなかった場合、アプリケーションは、このようなメモリにアクセスしようとするたびにエラーを受け取る可能性があります。 詳細については、「 NT カーネルの DDLOCK_NOSYSLOCK の実装 」を参照してください。

DdLock は、無効な PDEV を使用して呼び出すことができます。 PDEV は、ディスプレイ ドライバーの DrvAssertMode 関数を呼び出すことによって無効または有効になります。 詳細については、「 PDEV の管理」 を参照してください。

NT カーネルによるDDLOCK_NOSYSLOCKの実装

アプリケーションでは、DirectDraw と Direct3D のアプリケーション プログラミング インターフェイス (API) を使用して、ビデオ メモリ リソースに対する長時間のロックを取得できます。 このようなロックは、"NOSYSLOCK" ロックと呼ばれます。 これらのロックは、次の段落で説明するように、一般的なビデオ メモリ ロックとは動作が異なります。

DirectDraw ランタイムは、DD_LOCKDATAの dwFlags メンバーで指定されたDDLOCK_NOSYSLOCK フラグを使用してドライバーの DdLock 関数を呼び出した後、ランタイムはドライバーによって返されるサーフェス コンテンツへのポインターを調べます。 ドライバーから返されたポインターをアプリケーションに直接渡す代わりに、ランタイムはビデオ メモリ (ローカルと非ローカルの両方) の 2 番目のユーザー モード マッピングを作成し、そのマッピング内の同等の仮想アドレスを計算します。 この仮想アドレスは、メモリ ロックへのエイリアス ポインターと呼ばれます。 ランタイムは、この別名ロック ポインターをアプリケーションに渡します。 アプリケーションでは、この別名ロック ポインターを使用して、ビデオ メモリに直接読み取りと書き込みを行います。 アプリケーションもドライバーも、別のロックされたメモリ ポインターを使用していることを認識しません。

その後、モード切り替え時に、DirectDraw ランタイムは未処理のエイリアス ロック ポインターをメモします。 エイリアス ロック ポインターが完了するのを待つ代わりに、一般的なビデオ メモリ ロックの場合と同様に、ランタイムはビデオ メモリのユーザー モード マッピングを再マップし、モード切り替えを続行できるようにします。 ランタイムは、ユーザー モード マッピングを 1 つのダミー ページに再マップします。アプリケーションは引き続きそのダミー ページの読み取りと書き込みを行い、それ以外の場合は変更を認識しません。 ランタイムは、ドライバーの DdUnlock 関数を呼び出すことによって、エイリアス ロック ポインターをクリーンする必要があります。 アプリケーションがビデオ メモリに書き込みなくなったため、ランタイムはエイリアス ロック ポインターをクリーンできます。 このクリーンはモード切り替え時に発生するため、シーケンスの次の手順はサーフェスを失うということです。つまり、ドライバーのサーフェスごとのオブジェクトを破棄します。 言い換えると、ランタイムは、アプリケーションが引き続きロック済みと見なすサーフェスを含め、すべてのサーフェスに対してドライバーの DdDestroySurface 関数を呼び出します。 実際、アプリケーションはシステム メモリのダミー ページの読み取りと書き込みを続けます。

このプロセス全体は、 DdLock によって返されるメモリ ポインターがビデオ メモリのマッピングである場合にのみ機能します。 このビデオ メモリ マッピングは、DirectDraw カーネル モード ランタイムによって実行される非ローカル ビデオ メモリのユーザー モード マッピングか、ドライバーの DdMapMemory 関数によって提供されるマッピングのいずれかです。 メモリ ポインターをこれらのマッピングのいずれかに属性付けできない場合、ランタイムはロックを再マップしません。 モード スイッチは続行されます。つまり、ドライバーの DdUnlock 関数と DdDestroySurface 関数の呼び出しによって、ドライバーの Surface オブジェクトのロックが解除され、破棄されます。 その後、ドライバーは通常、ドライバーがロック時に割り当てたシステム メモリを解放します。 アプリケーションは引き続きこのメモリに書き込んでいるため、アクセス違反が発生します。

そのため、ドライバーは、そのドライバーの DdCreateSurface 関数が以前にPLEASE_ALLOC_USERMEM フラグを持つこのようなメモリを割り当てない限り、その DdLock 関数からシステム メモリ ポインターを返そうとしないでください。 DirectDraw ランタイムは、この方法で割り当てられたメモリを所有し、アプリケーションがメモリのロックを解除するまで、このメモリの解放を延期できます。 したがって、ドライバーの DdLock 関数は、アプリケーションをクラッシュさせるリスクなしに、この方法で割り当てられたメモリへのポインターを返すことができます。

要件

要件
対象プラットフォーム デスクトップ
Header ddrawint.h (Winddi.h を含む)

こちらもご覧ください

DD_LOCKDATA

DdMapMemory

DdUnlock