Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Důležité
Tento článek je adaptován z dokumentace UWP pro Windows App SDK/WinUI. Některé příklady kódu v tomto článku stále odkazují na rozhraní API specifická pro UWP, jako CoreWindow, CoreApplicationView a CoreDispatcher, které nejsou k dispozici ve WinUI/Windows App SDK. Ekvivalenty WinUI jsou:
-
CoreWindow→ použití AppWindow nebo třídy Okna WinUI -
CoreDispatcher→ Použít dispatcherQueue -
CoreApplicationView→ Použití okna nebo AppWindow
Rozhraní interop složení (ICompositorInterop, ICompositionDrawingSurfaceInterop atd.) fungují stejně s Microsoft.UI.Composition objekty.
Rozhraní API Microsoft.UI.Composition poskytuje rozhraní ICompositorInterop, ICompositionDrawingSurfaceInterop a ICompositionGraphicsDeviceInterop nativní interoperační rozhraní umožňující přesun obsahu přímo do compositoru.
Nativní interoperabilita je strukturovaná kolem povrchových objektů, které jsou podporovány texturami DirectX. Povrchy jsou vytvořeny z továrního objektu s názvem CompositionGraphicsDevice. Tento objekt je podporován podkladovým objektem zařízení Direct2D nebo Direct3D, který používá k přidělení paměti videa pro povrchy. Rozhraní API pro kompozici nikdy nevytváří podkladové zařízení DirectX. Je odpovědností aplikace vytvořit jeden objekt a předat ho objektu CompositionGraphicsDevice. Aplikace může současně vytvořit více objektů CompositionGraphicsDevice a může používat stejné zařízení DirectX jako vykreslovací zařízení pro více objektů CompositionGraphicsDevice .
Vytvoření povrchu
Každý CompositionGraphicsDevice slouží k vytváření povrchů. Každá plocha je vytvořena s počáteční velikostí (která může být 0,0), ale bez platných pixelů. Povrch v jeho počátečním stavu může být okamžitě spotřebován ve vizuálním stromu, například prostřednictvím CompositionSurfaceBrush a SpriteVisual, ale v počátečním stavu povrch nemá žádný vliv na výstup obrazovky. Je to pro všechny účely zcela transparentní, i když je zadaný alfa režim "neprůhledný".
V některých případech se zařízení DirectX mohou stát nepoužitelnými. K tomu může dojít mimo jiné z jiných důvodů, pokud aplikace předá některé rozhraní API DirectX neplatné argumenty nebo pokud je grafický adaptér resetován systémem nebo pokud je ovladač aktualizován. Direct3D má rozhraní API, které může aplikace použít ke zjišťování, asynchronně, pokud se zařízení z nějakého důvodu ztratí. Když dojde ke ztrátě zařízení DirectX, aplikace ji musí zahodit, vytvořit nový a předat ho všem objektům CompositionGraphicsDevice , které byly dříve přidružené k chybnému zařízení DirectX.
Načítání pixelů na povrch
Chcete-li načíst pixely do povrchu, musí aplikace volat metodu BeginDraw, která vrátí rozhraní DirectX představující texturu nebo kontext Direct2D v závislosti na tom, co aplikace požaduje. Aplikace pak musí vykreslit nebo nahrát pixely do této textury. Po dokončení úkolu v aplikaci musí metoda EndDraw být volána. Pouze v tomto okamžiku jsou nové pixely dostupné pro kompozici, ale stále se nezobrazují na obrazovce, dokud nebudou potvrzeny všechny změny ve vizuálním stromu. Pokud je strom vizuálu potvrzen před zavoláním EndDraw, aktualizace probíhající během tohoto procesu není viditelná na obrazovce a povrch bude nadále zobrazovat obsah, který měl před BeginDraw. Při volání EndDraw se textura nebo ukazatel kontextu Direct2D vrácený funkcí BeginDraw zneplatní. Aplikace by nikdy neměla tento ukazatel ukládat do mezipaměti nad rámec volání EndDraw .
Aplikace může volat BeginDraw pouze na jednom povrchu v danou chvíli, pro jakýkoli daný CompositionGraphicsDevice. Po volání BeginDraw musí aplikace volat EndDraw na této ploše před voláním BeginDraw na jiném. Vzhledem k tomu, že rozhraní API je agilní, zodpovídá aplikace za synchronizaci těchto volání, pokud chce provádět vykreslování z více pracovních vláken. Pokud aplikace chce přerušit vykreslování jedné plochy a dočasně přepnout na jinou, může aplikace použít SuspendDraw metoda. To umožňuje, aby další BeginDraw uspěl, ale neudělá první aktualizaci povrchu dostupnou pro složení na obrazovce. To aplikaci umožňuje provádět více aktualizací transakčním způsobem. Jakmile je povrch pozastaven, aplikace může pokračovat v aktualizaci voláním metody ResumeDraw, nebo může oznámit, že aktualizace byla dokončena voláním EndDraw. To znamená, že pro každou danou platformu CompositionGraphicsDevice lze aktivně aktualizovat pouze jeden povrch. Každé grafické zařízení udržuje tento stav nezávisle na ostatních zařízeních, takže aplikace se může vykreslit na dvě plochy současně, pokud patří do různých grafických zařízení. To však brání tomu, aby se paměť videa pro tyto dva povrchy spojila dohromady, a proto je méně efektivní paměť.
Metody BeginDraw, SuspendDraw, ResumeDraw a EndDraw vrátí selhání, pokud aplikace provede nesprávnou operaci (například předání neplatných argumentů nebo volání BeginDraw na povrchu před voláním EndDraw na jiném). Tyto typy selhání představují chyby aplikace a například očekávání spočívá v jejich rychlém zpracování. Funkce BeginDraw může také vrátit chybu, pokud dojde ke ztrátě základního zařízení DirectX. Toto selhání není závažné, protože aplikace může znovu vytvořit své zařízení DirectX a zkusit to znovu. Očekává se tedy, že aplikace zpracuje ztrátu zařízení tím, že jednoduše přeskočí vykreslování. Pokud BeginDraw z jakéhokoli důvodu selže, aplikace by také neměla volat EndDraw, protože začátek nikdy neuspěl na prvním místě.
Posouvání
Z důvodů výkonu, když aplikace volá BeginDraw, není zaručeno, že textura vrácená funkcí bude předchozím obsahem povrchu. Aplikace musí předpokládat, že obsah je náhodný, a proto musí zajistit, aby se všechny pixely dotýkaly, a to buď vymazáním povrchu před vykreslením, nebo vykreslením dostatečného neprůhledného obsahu pro pokrytí celého aktualizovaného obdélníku. To v kombinaci se skutečností, že ukazatel textury je platný pouze mezi volání BeginDraw a EndDraw , znemožňuje aplikaci kopírovat předchozí obsah z povrchu. Z tohoto důvodu nabízíme metodu Scroll , která aplikaci umožňuje provádět kopírování pixelů na stejné ploše.
Příklad použití C++/WinRT
Následující příklad kódu znázorňuje scénář spolupráce pro spolupráci v kontextu sady Windows App SDK. Příklad kombinuje typy z oblasti prostředí Microsoft.UI.Composition založené na prostředí Windows Runtime spolu s typy z hlaviček zprostředkovatele komunikace a kód, který vykreslí text pomocí rozhraní DirectWrite a Direct2D API založených na modelu COM. Příklad používá BeginDraw a EndDraw k zajištění bezproblémové spolupráce mezi těmito technologiemi. V příkladu se k rozložení textu používá DirectWrite a pak ho pomocí Direct2D vykresluje. Grafické zařízení pro kompozici přijímá zařízení Direct2D přímo během inicializace. To umožňuje BeginDraw vrátit ukazatel rozhraní ID2D1DeviceContext , což je výrazně efektivnější než aplikace vytvořit kontext Direct2D k zabalení vráceného rozhraní ID3D11Texture2D při každé operaci výkresu.
Pokud si chcete vyzkoušet následující příklad kódu C++/WinRT, nejprve vytvořte nový projekt aplikace WinUI v sadě Visual Studio (požadavky najdete v tématu Podpora sady Visual Studio pro C++/WinRT). Nahraďte obsah souborů zdrojového pch.hApp.cpp kódu následujícím výpisem kódu a pak sestavte a spusťte. Aplikace vykreslí řetězec "Hello, World!" v černém textu na průhledné pozadí.
// NOTE: This example uses UWP-specific APIs. For WinUI, replace CoreWindow with your app's Window handle.
// pch.h
#pragma once
#include <windows.h>
#include <D2d1_1.h>
#include <D3d11_4.h>
#include <Dwrite.h>
#include <Windows.Graphics.DirectX.Direct3D11.interop.h>
#include <Windows.ui.composition.interop.h>
#include <unknwn.h>
#include <winrt/Windows.ApplicationModel.Core.h>
#include <winrt/Windows.Foundation.h>
#include <winrt/Windows.Graphics.DirectX.h>
#include <winrt/Windows.Graphics.DirectX.Direct3D11.h>
#include <winrt/Microsoft.UI.Composition.h>
#include <winrt/Windows.UI.Core.h>
#include <winrt/Windows.UI.Input.h>
// NOTE: This example uses UWP-specific APIs. For WinUI, replace CoreWindow with your app's Window handle.
// App.cpp
//*********************************************************
//
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//*********************************************************
#include "pch.h"
using namespace winrt;
using namespace winrt::Windows::ApplicationModel::Core;
using namespace winrt::Windows::Foundation;
using namespace winrt::Windows::Foundation::Numerics;
using namespace winrt::Windows::Graphics::DirectX;
using namespace winrt::Windows::Graphics::DirectX::Direct3D11;
using namespace winrt::Windows::UI;
using namespace winrt::Microsoft::UI::Composition;
using namespace winrt::Windows::UI::Core;
namespace abi
{
using namespace ABI::Windows::Foundation;
using namespace ABI::Windows::Graphics::DirectX;
using namespace ABI::Microsoft::UI::Composition;
}
// An app-provided helper to render lines of text.
struct SampleText
{
SampleText(winrt::com_ptr<::IDWriteTextLayout> const& text, CompositionGraphicsDevice const& compositionGraphicsDevice) :
m_text(text),
m_compositionGraphicsDevice(compositionGraphicsDevice)
{
// Create the surface just big enough to hold the formatted text block.
DWRITE_TEXT_METRICS metrics;
winrt::check_hresult(m_text->GetMetrics(&metrics));
winrt::Windows::Foundation::Size surfaceSize{ metrics.width, metrics.height };
CompositionDrawingSurface drawingSurface{ m_compositionGraphicsDevice.CreateDrawingSurface(
surfaceSize,
DirectXPixelFormat::B8G8R8A8UIntNormalized,
DirectXAlphaMode::Premultiplied) };
// Cache the interop pointer, since that's what we always use.
m_drawingSurfaceInterop = drawingSurface.as<abi::ICompositionDrawingSurfaceInterop>();
// Draw the text
DrawText();
// If the rendering device is lost, the application will recreate and replace it. We then
// own redrawing our pixels.
m_deviceReplacedEventToken = m_compositionGraphicsDevice.RenderingDeviceReplaced(
[this](CompositionGraphicsDevice const&, RenderingDeviceReplacedEventArgs const&)
{
// Draw the text again.
DrawText();
return S_OK;
});
}
~SampleText()
{
m_compositionGraphicsDevice.RenderingDeviceReplaced(m_deviceReplacedEventToken);
}
// Return the underlying surface to the caller.
auto Surface()
{
// To the caller, the fact that we have a drawing surface is an implementation detail.
// Return the base interface instead.
return m_drawingSurfaceInterop.as<ICompositionSurface>();
}
private:
// The text to draw.
winrt::com_ptr<::IDWriteTextLayout> m_text;
// The composition surface that we use in the visual tree.
winrt::com_ptr<abi::ICompositionDrawingSurfaceInterop> m_drawingSurfaceInterop;
// The device that owns the surface.
CompositionGraphicsDevice m_compositionGraphicsDevice{ nullptr };
//winrt::com_ptr<abi::ICompositionGraphicsDevice> m_compositionGraphicsDevice2;
// For managing our event notifier.
winrt::event_token m_deviceReplacedEventToken;
// We may detect device loss on BeginDraw calls. This helper handles this condition or other
// errors.
bool CheckForDeviceRemoved(HRESULT hr)
{
if (hr == S_OK)
{
// Everything is fine: go ahead and draw.
return true;
}
if (hr == DXGI_ERROR_DEVICE_REMOVED)
{
// We can't draw at this time, but this failure is recoverable. Just skip drawing for
// now. We will be asked to draw again once the Direct3D device is recreated.
return false;
}
// Any other error is unexpected and, therefore, fatal.
winrt::check_hresult(hr);
return true;
}
// Renders the text into our composition surface
void DrawText()
{
// Begin our update of the surface pixels. If this is our first update, we are required
// to specify the entire surface, which nullptr is shorthand for (but, as it works out,
// any time we make an update we touch the entire surface, so we always pass nullptr).
winrt::com_ptr<::ID2D1DeviceContext> d2dDeviceContext;
POINT offset;
if (CheckForDeviceRemoved(m_drawingSurfaceInterop->BeginDraw(nullptr,
__uuidof(ID2D1DeviceContext), d2dDeviceContext.put_void(), &offset)))
{
d2dDeviceContext->Clear(D2D1::ColorF(D2D1::ColorF::Black, 0.f));
// Create a solid color brush for the text. A more sophisticated application might want
// to cache and reuse a brush across all text elements instead, taking care to recreate
// it in the event of device removed.
winrt::com_ptr<::ID2D1SolidColorBrush> brush;
winrt::check_hresult(d2dDeviceContext->CreateSolidColorBrush(
D2D1::ColorF(D2D1::ColorF::Black, 1.0f), brush.put()));
// Draw the line of text at the specified offset, which corresponds to the top-left
// corner of our drawing surface. Notice we don't call BeginDraw on the D2D device
// context; this has already been done for us by the composition API.
d2dDeviceContext->DrawTextLayout(D2D1::Point2F((float)offset.x, (float)offset.y), m_text.get(),
brush.get());
// Our update is done. EndDraw never indicates rendering device removed, so any
// failure here is unexpected and, therefore, fatal.
winrt::check_hresult(m_drawingSurfaceInterop->EndDraw());
}
}
};
struct DeviceLostEventArgs
{
DeviceLostEventArgs(IDirect3DDevice const& device) : m_device(device) {}
IDirect3DDevice Device() { return m_device; }
static DeviceLostEventArgs Create(IDirect3DDevice const& device) { return DeviceLostEventArgs{ device }; }
private:
IDirect3DDevice m_device;
};
struct DeviceLostHelper
{
DeviceLostHelper() = default;
~DeviceLostHelper()
{
StopWatchingCurrentDevice();
m_onDeviceLostHandler = nullptr;
}
IDirect3DDevice CurrentlyWatchedDevice() { return m_device; }
void WatchDevice(winrt::com_ptr<::IDXGIDevice> const& dxgiDevice)
{
// If we're currently listening to a device, then stop.
StopWatchingCurrentDevice();
// Set the current device to the new device.
m_device = nullptr;
winrt::check_hresult(::CreateDirect3D11DeviceFromDXGIDevice(dxgiDevice.get(), reinterpret_cast<::IInspectable**>(winrt::put_abi(m_device))));
// Get the DXGI Device.
m_dxgiDevice = dxgiDevice;
// QI For the ID3D11Device4 interface.
winrt::com_ptr<::ID3D11Device4> d3dDevice{ m_dxgiDevice.as<::ID3D11Device4>() };
// Create a wait struct.
m_onDeviceLostHandler = nullptr;
m_onDeviceLostHandler = ::CreateThreadpoolWait(DeviceLostHelper::OnDeviceLost, (PVOID)this, nullptr);
// Create a handle and a cookie.
m_eventHandle.attach(::CreateEvent(nullptr, false, false, nullptr));
winrt::check_bool(bool{ m_eventHandle });
m_cookie = 0;
// Register for device lost.
::SetThreadpoolWait(m_onDeviceLostHandler, m_eventHandle.get(), nullptr);
winrt::check_hresult(d3dDevice->RegisterDeviceRemovedEvent(m_eventHandle.get(), &m_cookie));
}
void StopWatchingCurrentDevice()
{
if (m_dxgiDevice)
{
// QI For the ID3D11Device4 interface.
auto d3dDevice{ m_dxgiDevice.as<::ID3D11Device4>() };
// Unregister from the device lost event.
::CloseThreadpoolWait(m_onDeviceLostHandler);
d3dDevice->UnregisterDeviceRemoved(m_cookie);
// Clear member variables.
m_onDeviceLostHandler = nullptr;
m_eventHandle.close();
m_cookie = 0;
m_device = nullptr;
}
}
void DeviceLost(winrt::delegate<DeviceLostHelper const*, DeviceLostEventArgs const&> const& handler)
{
m_deviceLost = handler;
}
winrt::delegate<DeviceLostHelper const*, DeviceLostEventArgs const&> m_deviceLost;
private:
void RaiseDeviceLostEvent(IDirect3DDevice const& oldDevice)
{
m_deviceLost(this, DeviceLostEventArgs::Create(oldDevice));
}
static void CALLBACK OnDeviceLost(PTP_CALLBACK_INSTANCE /* instance */, PVOID context, PTP_WAIT /* wait */, TP_WAIT_RESULT /* waitResult */)
{
auto deviceLostHelper = reinterpret_cast<DeviceLostHelper*>(context);
auto oldDevice = deviceLostHelper->m_device;
deviceLostHelper->StopWatchingCurrentDevice();
deviceLostHelper->RaiseDeviceLostEvent(oldDevice);
}
private:
IDirect3DDevice m_device;
winrt::com_ptr<::IDXGIDevice> m_dxgiDevice;
PTP_WAIT m_onDeviceLostHandler{ nullptr };
winrt::handle m_eventHandle;
DWORD m_cookie{ 0 };
};
struct SampleApp : implements<SampleApp, IFrameworkViewSource, IFrameworkView>
{
IFrameworkView CreateView()
{
return *this;
}
void Initialize(CoreApplicationView const&)
{
}
// Run once when the application starts up
void Initialize()
{
// Create a Direct2D device.
CreateDirect2DDevice();
// To create a composition graphics device, we need to QI for another interface
winrt::com_ptr<abi::ICompositorInterop> compositorInterop{ m_compositor.as<abi::ICompositorInterop>() };
// Create a graphics device backed by our D3D device
winrt::com_ptr<abi::ICompositionGraphicsDevice> compositionGraphicsDeviceIface;
winrt::check_hresult(compositorInterop->CreateGraphicsDevice(
m_d2dDevice.get(),
compositionGraphicsDeviceIface.put()));
m_compositionGraphicsDevice = compositionGraphicsDeviceIface.as<CompositionGraphicsDevice>();
}
void Load(hstring const&)
{
}
void Uninitialize()
{
}
void Run()
{
CoreWindow window = CoreWindow::GetForCurrentThread();
window.Activate();
CoreDispatcher dispatcher = window.Dispatcher();
dispatcher.ProcessEvents(CoreProcessEventsOption::ProcessUntilQuit);
}
void SetWindow(CoreWindow const& window)
{
m_compositor = Compositor{};
m_target = m_compositor.CreateTargetForCurrentView();
ContainerVisual root = m_compositor.CreateContainerVisual();
m_target.Root(root);
Initialize();
winrt::check_hresult(
::DWriteCreateFactory(
DWRITE_FACTORY_TYPE_SHARED,
__uuidof(m_dWriteFactory),
reinterpret_cast<::IUnknown**>(m_dWriteFactory.put())
)
);
winrt::check_hresult(
m_dWriteFactory->CreateTextFormat(
L"Segoe UI",
nullptr,
DWRITE_FONT_WEIGHT_REGULAR,
DWRITE_FONT_STYLE_NORMAL,
DWRITE_FONT_STRETCH_NORMAL,
36.f,
L"en-US",
m_textFormat.put()
)
);
Rect windowBounds{ window.Bounds() };
std::wstring text{ L"Hello, World!" };
winrt::check_hresult(
m_dWriteFactory->CreateTextLayout(
text.c_str(),
(uint32_t)text.size(),
m_textFormat.get(),
windowBounds.Width,
windowBounds.Height,
m_textLayout.put()
)
);
Visual textVisual{ CreateVisualFromTextLayout(m_textLayout) };
textVisual.Size({ windowBounds.Width, windowBounds.Height });
root.Children().InsertAtTop(textVisual);
}
// Called when Direct3D signals the device lost event.
void OnDirect3DDeviceLost(DeviceLostHelper const* /* sender */, DeviceLostEventArgs const& /* args */)
{
// Create a new Direct2D device.
CreateDirect2DDevice();
// Restore our composition graphics device to good health.
winrt::com_ptr<abi::ICompositionGraphicsDeviceInterop> compositionGraphicsDeviceInterop{ m_compositionGraphicsDevice.as<abi::ICompositionGraphicsDeviceInterop>() };
winrt::check_hresult(compositionGraphicsDeviceInterop->SetRenderingDevice(m_d2dDevice.get()));
}
// Create a surface that is asynchronously filled with an image
ICompositionSurface CreateSurfaceFromTextLayout(winrt::com_ptr<::IDWriteTextLayout> const& text)
{
// Create our wrapper object that will handle downloading and decoding the image (assume
// throwing new here).
SampleText textSurface{ text, m_compositionGraphicsDevice };
// The caller is only interested in the underlying surface.
return textSurface.Surface();
}
// Create a visual that holds an image.
Visual CreateVisualFromTextLayout(winrt::com_ptr<::IDWriteTextLayout> const& text)
{
// Create a sprite visual
SpriteVisual spriteVisual{ m_compositor.CreateSpriteVisual() };
// The sprite visual needs a brush to hold the image.
CompositionSurfaceBrush surfaceBrush{
m_compositor.CreateSurfaceBrush(CreateSurfaceFromTextLayout(text))
};
// Associate the brush with the visual.
CompositionBrush brush{ surfaceBrush.as<CompositionBrush>() };
spriteVisual.Brush(brush);
// Return the visual to the caller as an IVisual.
return spriteVisual;
}
private:
CompositionTarget m_target{ nullptr };
Compositor m_compositor{ nullptr };
winrt::com_ptr<::ID2D1Device> m_d2dDevice;
winrt::com_ptr<::IDXGIDevice> m_dxgiDevice;
//winrt::com_ptr<abi::ICompositionGraphicsDevice> m_compositionGraphicsDevice;
CompositionGraphicsDevice m_compositionGraphicsDevice{ nullptr };
std::vector<SampleText> m_textSurfaces;
DeviceLostHelper m_deviceLostHelper;
winrt::com_ptr<::IDWriteFactory> m_dWriteFactory;
winrt::com_ptr<::IDWriteTextFormat> m_textFormat;
winrt::com_ptr<::IDWriteTextLayout> m_textLayout;
// This helper creates a Direct2D device, and registers for a device loss
// notification on the underlying Direct3D device. When that notification is
// raised, the OnDirect3DDeviceLost method is called.
void CreateDirect2DDevice()
{
uint32_t createDeviceFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;
// Array with DirectX hardware feature levels in order of preference.
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 Direct3D 11 API device object and a corresponding context.
winrt::com_ptr<::ID3D11Device> d3DDevice;
winrt::com_ptr<::ID3D11DeviceContext> d3DImmediateContext;
D3D_FEATURE_LEVEL d3dFeatureLevel{ D3D_FEATURE_LEVEL_9_1 };
winrt::check_hresult(
::D3D11CreateDevice(
nullptr, // Default adapter.
D3D_DRIVER_TYPE_HARDWARE,
0, // Not asking for a software driver, so not passing a module to one.
createDeviceFlags, // Set debug and Direct2D compatibility flags.
featureLevels,
ARRAYSIZE(featureLevels),
D3D11_SDK_VERSION,
d3DDevice.put(),
&d3dFeatureLevel,
d3DImmediateContext.put()
)
);
// Initialize Direct2D resources.
D2D1_FACTORY_OPTIONS d2d1FactoryOptions{ D2D1_DEBUG_LEVEL_NONE };
// Initialize the Direct2D Factory.
winrt::com_ptr<::ID2D1Factory1> d2D1Factory;
winrt::check_hresult(
::D2D1CreateFactory(
D2D1_FACTORY_TYPE_SINGLE_THREADED,
__uuidof(d2D1Factory),
&d2d1FactoryOptions,
d2D1Factory.put_void()
)
);
// Create the Direct2D device object.
// Obtain the underlying DXGI device of the Direct3D device.
m_dxgiDevice = d3DDevice.as<::IDXGIDevice>();
m_d2dDevice = nullptr;
winrt::check_hresult(
d2D1Factory->CreateDevice(m_dxgiDevice.get(), m_d2dDevice.put())
);
m_deviceLostHelper.WatchDevice(m_dxgiDevice);
m_deviceLostHelper.DeviceLost({ this, &SampleApp::OnDirect3DDeviceLost });
}
};
int __stdcall wWinMain(HINSTANCE, HINSTANCE, PWSTR, int)
{
CoreApplication::Run(winrt::make<SampleApp>());
}
Windows developer