基本的な概念
Note
Windows 10上のアプリの場合は、DirectComposition ではなく Windows.UI.Composition API を使用することをお勧めします。 詳細については、「 Visual レイヤーを使用してデスクトップ アプリをモダン化する」を参照してください。
このトピックでは、Microsoft DirectComposition の基本的な概念の概要について説明します。 次のセクションが含まれます。
コンポジション
DirectComposition は、さまざまな変換、効果、アニメーションを適用して組み合わせて操作されるビットマップのコレクションとして コンポジション を定義し、アプリケーション UI で視覚的な結果を生成します。 DirectComposition はビットマップ コンテンツでのみ機能します。ベクターまたはテキストはサポートされていません。 DirectComposition では、ビットマップ コンテンツは提供されません。 代わりに、ユーザーが D2D、DXGI を使用して描画したり、独自のテクスチャ コンテンツをアップロードしたりできるインターフェイスが提供されます。
DirectComposition アプリケーションは、シーンを構成する 2 つのオブジェクト セット (一緒に構成されるビットマップと、ビットマップ間の空間リレーションシップを定義するビジュアル) を作成します。 DirectComposition でサポートされるビットマップ オブジェクトの詳細については、「 Bitmap オブジェクト」を参照してください。
ビジュアル
ビジュアル (または ビジュアル オブジェクト) は、DirectComposition の基本的な要素です。 これらは、アプリケーション UI でコンポジションとアニメーションを作成するために使用する基本的な構成要素です。
プログラミング用語では、ビジュアルは一連のプロパティを持つオブジェクトであり、プロパティの値を設定するために使用するインターフェイスを公開します。 ビジュアルの Content プロパティは、特定のビットマップをビジュアルに関連付けますが、他のプロパティは、DirectComposition が画面にレンダリングされるときにビジュアルを配置および操作する方法を制御します。
詳細については、「 ビジュアルのプロパティ」を参照してください。
ビジュアル ツリー
DirectComposition は、 ビジュアル ツリーと呼ばれるビジュアル オブジェクトの階層コレクションからコンポジションを作成します。 ツリーのルートにあるビジュアルは ルート ビジュアル と呼ばれ、1 つ以上 の子ビジュアルを 関連付けることができます。 子ビジュアルには、それ自体の 1 つ以上の子ビジュアルを含めることができます。 子ビジュアルが関連付けられているビジュアルはすべて 親ビジュアルと呼ばれ、同じ親を共有するすべての子 ビジュアルは兄弟ビジュアルと呼ばれます。 特定のビジュアルとそのすべての子ビジュアルと子孫ビジュアルは、 ビジュアル サブツリーと呼ばれます。
ツリー内のビジュアルの位置は、コンポジション内の他のビジュアルとの相対的な画面位置と z オーダーを決定するのに役立ちます。 ルート ビジュアルは、コンポジションがレンダリングされるターゲット ウィンドウのクライアント領域の左上隅を基準にして配置されます。 すべての子ビジュアルは、親ビジュアルの左上隅 (または TransformParent プロパティで指定されたビジュアル) を基準にして配置され、常に親の前に z オーダーで表示されます。
次の図は、ビジュアルの構成と、コンポジションの生成に使用されるビジュアル ツリーの構造を示しています。 Visual 1 はルート ビジュアルであり、兄弟ビジュアルである子ビジュアル 2 と 3 の親でもあります。 Visual 3 には、独自の 2 つの子ビジュアル (Visuals 4 と 5) があります。 ビジュアル 3 から 5 が一緒にビジュアル サブツリーを構成します。
親ビジュアルは、その子ビジュアルの順序付きリストを保持します。 兄弟ビジュアルが互いに重なるように配置されている場合、DirectComposition は、親ビジュアルの子リストに表示される順序に基づいて兄弟の z オーダーを設定します。 リストの後に表示される兄弟は、リストの前に表示されるすべての兄弟の前に配置されます。 次の図は、重複する子ビジュアルの z オーダーを示しています。
ビジュアル オブジェクトのプロパティ
ビジュアル オブジェクトは、ビジュアルのビットマップ コンテンツを設定したり、DirectComposition がビジュアル コンテンツを配置および操作する方法を制御したりできるプロパティのセットを公開します。 次のセクションでは、各プロパティについて詳しく説明します。
- コンテンツのプロパティ
- Clip プロパティ
- BorderMode プロパティ
- BitmapInterpolationMode プロパティ
- CompositeMode プロパティ
- OffsetX プロパティと OffsetY プロパティ
- Effect プロパティ
- Transform プロパティ
- TransformParent プロパティ
コンテンツのプロパティ
ビジュアルの Content プロパティは、ビジュアルに関連付けられているビットマップ コンテンツを指定します。 これは、コンポジションにビジュアルを含めるときに DirectComposition が使用するビットマップです。
IDCompositionVisual::SetContent メソッドを呼び出して、ビジュアルの Content プロパティを設定します。
DirectComposition でサポートされるビットマップ コンテンツの種類の詳細については、「 Bitmap オブジェクト」を参照してください。
Clip プロパティ
ビジュアルの Clip プロパティは、クリッピング領域 (またはクリップ四角形) と呼ばれる四角形の領域を指定します。 ビジュアルがレンダリングされると、クリッピング領域の内側にあるビジュアルの部分のみが表示され、クリッピング領域の外側に広がるコンテンツはすべてクリップされます (つまり、表示されません)。 DirectComposition では、角が丸い領域または四角形の領域がサポートされています。
ビジュアルの Clip プロパティを設定するには、 IDCompositionVisual::SetClip メソッドを呼び出します。
詳細については、「 クリッピング」を参照してください。
BorderMode プロパティ
BorderMode プロパティは、このビジュアルに関連付けられたビットマップとクリップ、またはこのビジュアルにルート化されたサブツリー内のビジュアルのエッジを作成する方法を指定します。
境界線モードは、ビットマップの変換時にビットマップのエッジがどのように構成されるかに影響し、エッジが整数座標で軸揃えされないようにします。 また、角が丸いクリップのコーナー、およびエッジが整数座標で軸揃えされないように変換されたクリップの端でコンテンツをクリップする方法にも影響します。
詳細については、「 IDCompositionVisual::SetBorderMode」を参照してください。
BitmapInterpolationMode プロパティ
BitmapInterpolationMode プロパティは、ビットマップ内のピクセルと画面上のピクセルの間に一対一の対応が存在しないよう、変換時にビットマップを作成する方法を DirectComposition に指示します。
IDCompositionVisual::SetBitmapInterpolationMode メソッドを呼び出して、ビジュアルの BitmapInterpolationMode プロパティを設定します。
CompositeMode プロパティ
CompositeMode プロパティは、ビジュアルのビットマップ コンテンツをレンダー ターゲットとブレンドする方法を DirectComposition に指示します。 サポートされている複合モードの詳細については、「 DCOMPOSITION_COMPOSITE_MODE」を参照してください。
ビジュアルの CompositeMode プロパティを設定する場合は、 IDCompositionVisual::SetCompositeMode メソッドを呼び出します。
OffsetX プロパティと OffsetY プロパティ
OffsetX プロパティと OffsetY プロパティは、ビジュアルを水平方向および垂直方向に配置する場所を DirectComposition に指示します。 これらは、ビジュアルのすべての変換と効果の計算元となる 2 次元の固定位置を定義します。
ルート ビジュアルの場合、OffsetX プロパティと OffsetY プロパティは、ビジュアルをホストするウィンドウの左上隅を基準にして、ポイントの x 座標と y 座標を定義します。 子ビジュアルの場合、座標は親の左上隅を基準にするか、 TransformParent プロパティ が指定されている場合は、指定したビジュアルの左上隅を基準とします。 ビジュアルがレンダリングされると、ビジュアルの左上隅が指定した座標と一致するように配置されます。
IDCompositionVisual::SetOffsetX メソッドと SetOffsetY メソッドを呼び出して、ビジュアルの OffsetX プロパティと OffsetY プロパティを設定します。
Effect プロパティ
Effect プロパティを使用すると、ビジュアルとそのサブツリーの構成方法を変更する効果 (効果のグループ) を指定できます。 たとえば、ビジュアルの不透明度を制御する効果を指定したり、ビジュアルと別のビットマップをさまざまな方法でブレンドしたり、パースペクティブ変換をビジュアルに適用したりできます。
IDCompositionVisual::SetEffect メソッドを呼び出して、ビジュアルの Effect プロパティを設定します。
詳細については、「Effects」 (エフェクト) を参照してください。
Transform プロパティ
Transform プロパティは、DirectComposition がビジュアルに対して実行する 2 次元 (2D) 変換または 2D 変換のグループを指定します。 変換 (または変換) は、ビジュアルの座標系を親に対して、または TransformParent プロパティで指定されたビジュアルに対して相対的に変更する操作です。 変換を使用すると、ビジュアルを別の場所 (平行移動) に移動し、拡大または縮小 (拡大縮小)、回転 (回転)、図形の歪み (歪み) などを行うことで、ビジュアルの位置、サイズ、または性質を変更できます。
IDCompositionVisual::SetTransform メソッドを呼び出して、ビジュアルの Transform プロパティを設定します。
詳細については、「MSBuild 変換」をご覧ください。
TransformParent プロパティ
ビジュアルの座標系は、OffsetX、OffsetY、および Transform プロパティによって変更されます。 通常、これらのプロパティは、ビジュアルの直接の親に対する相対座標系を定義します。 子ビジュアルの座標系の基礎として親以外のビジュアルを使用するには、TransformParent プロパティを使用して、変換の目的で別のビジュアルを "親" として指定します。
IDCompositionVisual::SetTransformParent メソッドを呼び出して、ビジュアルの TransformParent プロパティを設定します。
デバイス オブジェクト
DirectComposition を使用するには、さまざまなコンポーネント オブジェクト モデル (COM) オブジェクトを作成して操作する必要があります。 最初に作成する必要があるオブジェクトは DirectComposition デバイス オブジェクト です。これは、コンポジションで使用される他のすべてのオブジェクトを作成するためのファクトリとして機能するためです。
デバイス オブジェクトを作成するには、IDCompositionDevice インターフェイス ポインターを返す DCompositionCreateDevice 関数を呼び出します。 このインターフェイスは、ビジュアル オブジェクト、クリップ オブジェクト、アニメーション オブジェクト、変換オブジェクト、効果オブジェクトなどを作成するために使用する一連のメソッドを公開します。
device オブジェクトは、他のオブジェクトを作成するためのファクトリである以外に、もう 1 つの目的を果たします。 Commit という名前 のメソッドを公開し、処理のためにビジュアル ツリーを DirectComposition に渡します。 詳細については、「 トランザクションコンポジション」を参照してください。
アプリケーションでデバイス オブジェクトの複数のインスタンスを作成できますが、特定のコンポジションで使用するすべてのオブジェクトは、同じデバイス オブジェクトによって作成する必要があります。ただし、1 つの例外として、同じビジュアル ツリー内の異なるデバイス オブジェクトのビジュアル オブジェクトを組み合わせることができます。 これを行うと、DirectComposition はビジュアル ツリーを通常と同じように扱います。ただし、ツリー内の特定のビジュアル オブジェクトに対する変更は、ビジュアル オブジェクトを作成したデバイス オブジェクトで Commit メソッドが呼び出された場合にのみ有効になります。
同じビジュアル ツリー内の異なるデバイスのビジュアルを使用する機能により、複数のスレッドで 1 つのビジュアル ツリーを作成および操作しながら、非同期的に変更をコミットするために使用できる 2 つの独立したデバイスを維持できます。 詳細については、「 クロスデバイス ビジュアル ツリー」を参照してください。
コンポジションターゲットウィンドウ
ツリーのビジュアルを画面に表示するには、ビジュアル ツリーをウィンドウにバインドする必要があります。 コンポジション ターゲット ウィンドウと呼ばれるウィンドウには、最上位のウィンドウまたは子ウィンドウを指定できます。 また、コンポジションターゲットウィンドウはレイヤードウィンドウにすることができます。つまり、 WS_EX_LAYERED ウィンドウ スタイルを使用できます。
DirectComposition を使用すると、アプリケーションは最大 2 つのビジュアル ツリーを各ウィンドウにバインドできます。 ビジュアル ツリーには、ウィンドウ自体の上に構成されるツリーが含まれますが、ウィンドウのすべての子ウィンドウの背後に、もう 1 つはウィンドウの上部と子ウィンドウの上に構成されます。 つまり、各ウィンドウには 4 つの概念レイヤーがあり、すべてのレイヤーがターゲット ウィンドウの表示領域にクリップされます。 次の図は、ウィンドウの 4 つの概念レイヤーを示しています。
トランザクションコンポジション
DirectComposition はトランザクション モデルを使用します。このモデルでは、ビジュアルに対してバッチ処理された一連の変更を作成し、そのセットを DirectComposition に "コミット" して一度に処理します。 同じ DirectComposition ビジュアル オブジェクトを変更し、変更を何度でもコミットできます。 デスクトップ ウィンドウ マネージャー (DWM) がバッチを取得すると、保留中のすべてのバッチが取得され、コミットされた順序で次のフレームに適用されます。
1 つのコミット内のすべての変更は、1 つのフレームに適用することが保証されます。 DWM はフレームごとに 1 回バッチを収集するため、特定のオブジェクトはフレームごとに 1 回だけ変更できます。 異なるオブジェクトを変更する後続のコミットも現在のフレームに適用される可能性がありますが、DirectComposition は変更が同じフレームで発生することを保証しません。
IDCompositionSurface::BeginDraw メソッドと IDCompositionSurface::EndDraw メソッドを使用すると、レンダリングの更新をビジュアル更新プログラムと同期できます。 たとえば、 IDCompositionSurface::BeginDraw を呼び出し、ビジュアルの OffsetX プロパティと Clip プロパティを更新し、 IDCompositionDevice::Commit を呼び出し、Microsoft DirectX でコンテンツを描画してから 、IDCompositionSurface::EndDraw を呼び出すことができます。 この場合、Microsoft DirectComposition では、ビットマップ コンテンツとビジュアル プロパティが同時に更新されます。
バッチ処理
同じビジュアルに対して複数の変更をコミットすることも、同じフレーム内で複数の変更を異なるビジュアルにコミットすることもできます。 同じフレーム内で同じビジュアルに複数の変更を加える場合は、次の点に注意してください。
ビジュアルの同じプロパティに複数の変更を加えた場合、最後の変更のみが適用されます。 たとえば、不透明度を 0、0.5、最後に 1.0 に設定した場合、ビジュアルには不透明度 1.0 のみが適用されます。
同じビジュアルの複数のプロパティを変更した場合、DirectComposition は最初に変更をビジュアルに適用し、次に子ビジュアルに適用します。 プロパティは、指定した順序に関係なく、次の順序で適用されます。
- Offset
- 変換
- [クリップ]
- 効果
次の図は、4 つのプロパティすべてをビジュアルに適用した結果を示しています。
すべての変更は、同じフレームのコンテキスト内で一度にビジュアルに適用されます。 つまり、ユーザーの観点から見ると、ビジュアルに対する変更は瞬時に行われます。
Transform プロパティでは、 IDCompositionDevice::CreateTransformGroup を使用して、ビジュアルに一度に適用する変換のグループを作成できます。 DirectComposition は、指定した順序で変換を適用します。
Effect プロパティでは、 IDCompositionEffectGroup を使用して効果のグループを適用できます。 DirectComposition は、指定した順序で効果を適用します。 さらに、3D パースペクティブ変換では、現在のビジュアル内のすべての 3D 変換が適用された後、ビジュアル ツリーがフラット化されます。 これにより、結果のビジュアルが可能な限り 3D に近い状態に見えるようになります。
Synchronization
アプリケーションでは、複数のスレッドから DirectComposition を同時に呼び出すことができます。 順次呼び出しでは実行順序が保証されますが、同時呼び出しでは保証されません。 たとえば、スレッド A がビジュアルを変更し、スレッド B がバッチを同時にコミットする場合、そのビジュアル変更がコミットされたバッチに含まれるか、新しいバッチを開始するのかは定義されません。 一方、アプリケーションで他の同期メカニズムを使用して、一方のメソッドがもう一方の前に確実に呼び出されるようにする場合、DirectComposition は呼び出し順序を受け入れ、両方の呼び出しが 1 つのスレッドからその順序で発行されたかのように処理します。
クロスデバイス ビジュアル ツリー
DirectComposition オブジェクトはスレッド バインドされていません。複数のスレッドを使用して、同じオブジェクト のセットを変更できます。 ただし、同じデバイス オブジェクトを共有する場合は、次の問題に注意してください。
- どちらのスレッドも IDCompositionDevice::Commit を呼び出すことができる必要があります。 いずれかのスレッドだけが IDCompositionDevice::Commit を呼び出す場合、もう一方のスレッドは DirectComposition に対する変更をコミットできません。
- あるスレッドが IDCompositionDevice::Commit を呼び出し、もう一方のスレッドが同じトランザクションの一部であることを意図した変更を行っている間に、トランザクション動作が失われる可能性があります。
複数の同時トランザクションを DirectComposition にコミットする必要がある場合は、複数のスレッドから複数のデバイス オブジェクトを使用する必要があります。 このシナリオでは、同じビジュアル ツリーが両方のデバイス オブジェクトで共有され、各デバイス オブジェクトが独自のトランザクションをコミットします。
次の図は、2 つのデバイス オブジェクトで共有されるビジュアル ツリーを示しています。 ビジュアル 1、2、4、5 は 1 つのデバイスまたは他のデバイスによって所有されていますが、ビジュアル 3 は両方のデバイスで共有されるため、2 つのサブツリーを 1 つの大きなビジュアル ツリーに接続するために使用できます。 ビジュアル ツリーを共有すると、2 つのデバイスを 2 つの異なるスレッドから非同期的に操作できます。
2 つのデバイス間でビジュアル ツリーを共有することの有用性を示すために、低待機時間のタッチ入力を可能にするアーキテクチャを検討してください。 このアーキテクチャでは、ほとんどの UI タスクを処理する 2 つのスレッドと、タッチ入力イベントの処理専用の 2 つのスレッドを使用できます。 タッチ スレッドは、ユーザー入力ジェスチャに基づいて特定のビジュアルの変換を更新します。 変換を更新することで、タッチ スレッドは、そのビジュアルの下のサブツリー全体をユーザーの指に従わせ、ユーザーがマルチタッチ ジェスチャを実行する際にスケールアップまたはスケールダウンすることができます。 UI スレッドは、ほとんどのコンポジション ツリーの所有権を保持し、タッチ スレッドは、非同期タッチ応答用にタグ付けされた少数のビジュアルのみを所有します。 次の図は、このようなコンポジション ツリーの簡略化されたバージョンを示しています。
通常、UI スレッドは、それが排他的に所有するビジュアルのみを変更し、タッチ スレッドは共有ビジュアルのみを変更します。 唯一の例外は、タッチ対応サブツリーを作成または破棄するときに発生します。
関連トピック