Cómo representar mediante un contexto de dispositivo Direct2D
En este tema aprenderá a crear el contexto de dispositivo Direct2D en Windows 8. Esta información se aplica a usted si está desarrollando aplicaciones de la Tienda Windows o una aplicación de escritorio mediante el uso de Direct2D. Este tema describe el propósito de los objetos de contexto de dispositivo Direct2D, cómo crear ese objeto y una guía paso a paso sobre la representación y la visualización de primitivas e imágenes Direct2D. También obtendrá información sobre cómo cambiar los destinos de representación y agregar efectos a la aplicación.
- ¿Qué es un dispositivo Direct2D?
- ¿Qué es un contexto de dispositivo Direct2D?
- Representación con Direct2D en Windows 8
- ¿Por qué usar un contexto de dispositivo para la representación?
- Cómo crear un contexto de dispositivo Direct2D para la representación
- Selección de un destino
- Cómo representar y mostrar
¿Qué es un dispositivo Direct2D?
Necesita un dispositivo Direct2D y un dispositivo Direct3D para crear un contexto de dispositivo Direct2D. Un dispositivo Direct2D (expone un puntero de interfaz ID2D1Device ) representa un adaptador de pantalla. Un dispositivo Direct3D (expone un puntero de interfaz ID3D11Device ) está asociado a un dispositivo Direct2D. Cada aplicación debe tener un dispositivo Direct2D, pero puede tener más de un dispositivo.
¿Qué es un contexto de dispositivo Direct2D?
Un contexto de dispositivo Direct2D (expone un puntero de interfaz ID2D1DeviceContext) representa un conjunto de búferes de estado y comandos que se usan para representar un objetivo. Puede llamar a métodos en el contexto del dispositivo para establecer el estado de canalización y generar comandos de representación mediante los recursos propiedad de un dispositivo.
Representación con Direct2D en Windows 8
En Windows 7 y versiones anteriores, se usa un ID2D1HwndRenderTarget u otra interfaz de destino de representación para representar en una ventana o superficie. A partir de Windows 8, no se recomienda representar mediante métodos que se basan en interfaces como ID2D1HwndRenderTarget porque no funcionarán con aplicaciones de la Tienda Windows. Puede usar un contexto de dispositivo para representar en un Hwnd si desea crear una aplicación de escritorio y seguir aprovechando las características adicionales del contexto de dispositivo. Sin embargo, el contexto de dispositivo es necesario para representar contenido en aplicaciones de la Tienda Windows con Direct2D.
¿Por qué usar un contexto de dispositivo para la representación?
- Puede representar para aplicaciones de la Tienda Windows.
- Puede cambiar el destino de representación en cualquier momento antes, durante y después de la representación. El contexto de dispositivo garantiza que las llamadas a los métodos de dibujo se ejecutan en orden y las aplica al cambiar el destino de representación.
- Puede usar más de un tipo de ventana con un contexto de dispositivo. Puede usar un contexto de dispositivo y una cadena de intercambio para representar directamente en Windows::UI::Core::CoreWindow o Windows::UI::XAML::SwapChainBackgroundPanel.
- Puede usar el contexto de dispositivo Direct2D para crear efectos de Direct2D y representar la salida de un efecto de imagen o gráfico de efectos en un destino de representación.
- Puede tener varios contextos de dispositivo, lo que puede resultar útil para mejorar el rendimiento en una aplicación subprocesada. Consulte Aplicaciones multiproceso de Direct2D para obtener más información.
- El contexto de dispositivo interopera estrechamente con Direct3D, lo que proporciona más acceso a las opciones de Direct3D.
Cómo crear un contexto de dispositivo Direct2D para la representación
Este código muestra cómo crear un dispositivo Direct3D11, obtener el dispositivo DXGI asociado, crear un dispositivo Direct2D y, por último, crear el dispositivo de contexto de Direct2D para la representación.
A continuación se muestra un diagrama de las llamadas a métodos y las interfaces que utiliza este código.
Nota:
En este código se supone que ya tiene un objeto ID2D1Factory1. Para obtener más información, consulte la página de referencia de ID2D1Factory.
// This flag adds support for surfaces with a different color channel ordering than the API default.
// You need it for compatibility with Direct2D.
UINT creationFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;
// This array defines the set of DirectX hardware feature levels this app supports.
// The ordering is important and you should preserve it.
// Don't forget to declare your app's minimum required feature level in its
// description. All apps are assumed to support 9.1 unless otherwise stated.
D3D_FEATURE_LEVEL featureLevels[] =
{
D3D_FEATURE_LEVEL_11_1,
D3D_FEATURE_LEVEL_11_0,
D3D_FEATURE_LEVEL_10_1,
D3D_FEATURE_LEVEL_10_0,
D3D_FEATURE_LEVEL_9_3,
D3D_FEATURE_LEVEL_9_2,
D3D_FEATURE_LEVEL_9_1
};
// Create the DX11 API device object, and get a corresponding context.
ComPtr<ID3D11Device> device;
ComPtr<ID3D11DeviceContext> context;
DX::ThrowIfFailed(
D3D11CreateDevice(
nullptr, // specify null to use the default adapter
D3D_DRIVER_TYPE_HARDWARE,
0,
creationFlags, // optionally set debug and Direct2D compatibility flags
featureLevels, // list of feature levels this app can support
ARRAYSIZE(featureLevels), // number of possible feature levels
D3D11_SDK_VERSION,
&device, // returns the Direct3D device created
&m_featureLevel, // returns feature level of device created
&context // returns the device immediate context
)
);
ComPtr<IDXGIDevice> dxgiDevice;
// Obtain the underlying DXGI device of the Direct3D11 device.
DX::ThrowIfFailed(
device.As(&dxgiDevice)
);
// Obtain the Direct2D device for 2-D rendering.
DX::ThrowIfFailed(
m_d2dFactory->CreateDevice(dxgiDevice.Get(), &m_d2dDevice)
);
// Get Direct2D device's corresponding device context object.
DX::ThrowIfFailed(
m_d2dDevice->CreateDeviceContext(
D2D1_DEVICE_CONTEXT_OPTIONS_NONE,
&m_d2dContext
)
);
Veamos los pasos descritos en la muestra de código anterior.
Obtenga un puntero de interfaz ID3D11Device que necesitará para crear el contexto de dispositivo.
Declare las marcas de creación para configurar el dispositivo Direct3D para la compatibilidad con BGRA. Direct2D requiere el orden de color BGRA.
Declare una matriz de entradas D3D_FEATURE_LEVEL que representen el conjunto de niveles de características que admitirá la aplicación.
Nota:
Direct3D busca la lista hasta que encuentra el nivel de característica admitido por el sistema host.
Use la función D3D11CreateDevice para crear un objeto ID3D11Device; la función también devolverá un objeto ID3D11DeviceContext, pero ese objeto no es necesario para este ejemplo.
Consulte el dispositivo Direct3D 11 para conocer su interfaz de dispositivo DXGI.
Cree un objeto ID2D1Device. Para ello, llame al método ID2D1Factory::CreateDevice y pase el objeto IDXGIDevice.
Cree un puntero ID2D1DeviceContext mediante el método ID2D1Device::CreateDeviceContext.
Selección de un destino
Este código muestra cómo obtener la textura bidimensional Direct3D para el búfer de reserva de la ventana y crear un destino de mapa de bits que vincule a esta textura a la que representa el contexto del dispositivo Direct2D.
// Allocate a descriptor.
DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {0};
swapChainDesc.Width = 0; // use automatic sizing
swapChainDesc.Height = 0;
swapChainDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; // this is the most common swapchain format
swapChainDesc.Stereo = false;
swapChainDesc.SampleDesc.Count = 1; // don't use multi-sampling
swapChainDesc.SampleDesc.Quality = 0;
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swapChainDesc.BufferCount = 2; // use double buffering to enable flip
swapChainDesc.Scaling = DXGI_SCALING_NONE;
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; // all apps must use this SwapEffect
swapChainDesc.Flags = 0;
// Identify the physical adapter (GPU or card) this device is runs on.
ComPtr<IDXGIAdapter> dxgiAdapter;
DX::ThrowIfFailed(
dxgiDevice->GetAdapter(&dxgiAdapter)
);
// Get the factory object that created the DXGI device.
ComPtr<IDXGIFactory2> dxgiFactory;
DX::ThrowIfFailed(
dxgiAdapter->GetParent(IID_PPV_ARGS(&dxgiFactory))
);
// Get the final swap chain for this window from the DXGI factory.
DX::ThrowIfFailed(
dxgiFactory->CreateSwapChainForCoreWindow(
device.Get(),
reinterpret_cast<IUnknown*>(m_window),
&swapChainDesc,
nullptr, // allow on all displays
&m_swapChain
)
);
// Ensure that DXGI doesn't queue more than one frame at a time.
DX::ThrowIfFailed(
dxgiDevice->SetMaximumFrameLatency(1)
);
// Get the backbuffer for this window which is be the final 3D render target.
ComPtr<ID3D11Texture2D> backBuffer;
DX::ThrowIfFailed(
m_swapChain->GetBuffer(0, IID_PPV_ARGS(&backBuffer))
);
// Now we set up the Direct2D render target bitmap linked to the swapchain.
// Whenever we render to this bitmap, it is directly rendered to the
// swap chain associated with the window.
D2D1_BITMAP_PROPERTIES1 bitmapProperties =
BitmapProperties1(
D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW,
PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_IGNORE),
m_dpi,
m_dpi
);
// Direct2D needs the dxgi version of the backbuffer surface pointer.
ComPtr<IDXGISurface> dxgiBackBuffer;
DX::ThrowIfFailed(
m_swapChain->GetBuffer(0, IID_PPV_ARGS(&dxgiBackBuffer))
);
// Get a D2D surface from the DXGI back buffer to use as the D2D render target.
DX::ThrowIfFailed(
m_d2dContext->CreateBitmapFromDxgiSurface(
dxgiBackBuffer.Get(),
&bitmapProperties,
&m_d2dTargetBitmap
)
);
// Now we can set the Direct2D render target.
m_d2dContext->SetTarget(m_d2dTargetBitmap.Get());
Veamos los pasos descritos en el ejemplo de código anterior.
Asigne una estructura DXGI_SWAP_CHAIN_DESC1 y defina la configuración de la cadena de intercambio.
Esta configuración muestra un ejemplo de cómo crear una cadena de intercambio que puede usar una aplicación de la Tienda Windows.
Obtenga el adaptador en el que se están ejecutando el dispositivo Direct3D y el dispositivo DXGI y obtenga el objeto IDXGIFactory asociado a ellos. Debe usar esta fábrica DXGI para asegurarse de que la cadena de intercambio se cree en el mismo adaptador.
Llame al método IDXGIFactory2::CreateSwapChainForCoreWindow para crear la cadena de intercambio. Usa la clase Windows::UI::CoreWindow para la ventana principal de una aplicación de la Tienda Windows.
Asegúrese de establecer la latencia máxima de fotogramas en 1 para minimizar el consumo de energía.
Si desea representar contenido de Direct2D en una aplicación de la Tienda Windows, consulte el método CreateSwapChainForComposition.
Obtenga el búfer de reserva de la cadena de intercambio. El búfer de reserva expone una interfaz ID3D11Texture2D asignada por la cadena de intercambio
Declare una estructura D2D1_BITMAP_PROPERTIES1 y establezca los valores de propiedad. Establezca el formato de píxel en BGRA ya que es el formato que usan el dispositivo Direct3D y el dispositivo DXGI.
Obtenga el búfer de reserva como una IDXGISurface para pasar a Direct2D. Direct2D no acepta directamente una ID3D11Texture2D.
Cree un objeto ID2D1Bitmap desde el búfer de reserva mediante el método ID2D1DeviceContext::CreateBitmapFromDxgiSurface.
Ahora el mapa de bits de Direct2D está vinculado al búfer de reserva. Establezca el destino en el contexto del dispositivo Direct2D en el mapa de bits.
Cómo representar y mostrar
Ahora que tiene un mapa de bits de destino, puede dibujar primitivas, imágenes, efectos de imagen y texto en él mediante el contexto del dispositivo Direct2D. Este código muestra cómo dibujar un rectángulo.
ComPtr<ID2D1SolidColorBrush> pBlackBrush;
DX::ThrowIfFailed(
m_d2dContext->CreateSolidColorBrush(
D2D1::ColorF(D2D1::ColorF::Black),
&pBlackBrush
)
);
m_d2dContext->BeginDraw();
m_d2dContext->DrawRectangle(
D2D1::RectF(
rc.left + 100.0f,
rc.top + 100.0f,
rc.right - 100.0f,
rc.bottom - 100.0f),
pBlackBrush);
DX::ThrowIfFailed(
m_d2dContext->EndDraw()
);
DX::ThrowIfFailed(
m_swapChain->Present1(1, 0, ¶meters);
);
Veamos los pasos descritos en el ejemplo de código anterior.
- Llame a CreateSolidColorBrush para crear un pincel para pintar el rectángulo.
- Llame al método BeginDraw antes de emitir comandos de dibujo.
- Llame al método DrawRectangle en el rectángulo que se va a dibujar y el pincel.
- Llame al método EndDraw después de haber terminado de emitir comandos de dibujo.
- Muestre el resultado llamando al método IDXGISwapChain::Present.
Ahora puede utilizar el contexto del dispositivo Direct2D para dibujar primitivas, imágenes, efectos de imagen y texto en la pantalla.