Kommentar
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Viktigt!
Den här artikeln anpassas från UWP-dokumentationen för Windows App SDK/WinUI. Vissa kodexempel i den här artikeln refererar fortfarande till UWP-specifika API:er, till exempel CoreWindow, CoreApplicationViewoch CoreDispatcher, som inte är tillgängliga i WinUI/Windows App SDK. WinUI-motsvarigheterna är:
-
CoreWindow→ Använda AppWindow eller klassen WinUI-fönster -
CoreDispatcher→ Använda DispatcherQueue -
CoreApplicationView→ Använd fönster eller AppWindow
Interop-gränssnitten för sammansättning (ICompositorInterop, ICompositionDrawingSurfaceInterop osv.) fungerar på samma sätt med Microsoft.UI.Composition objekt.
API:et Microsoft.UI.Composition tillhandahåller gränssnitten ICompositorInterop, ICompositionDrawingSurfaceInterop och ICompositionGraphicsDeviceInterop som gör att innehåll kan flyttas direkt till compositorn.
Intern samverkan är strukturerad kring ytobjekt som backas upp av DirectX-texturer. Ytorna skapas från ett fabriksobjekt med namnet CompositionGraphicsDevice. Det här objektet backas upp av ett underliggande Direct2D- eller Direct3D-enhetsobjekt som används för att allokera videominne för ytor. API:et för sammansättning skapar aldrig den underliggande DirectX-enheten. Det är programmets ansvar att skapa en och skicka den till objektet CompositionGraphicsDevice . Ett program kan skapa fler än ett CompositionGraphicsDevice-objekt i taget, och det kan använda samma DirectX-enhet som återgivningsenheten för flera CompositionGraphicsDevice-objekt .
Skapa en yta
Varje CompositionGraphicsDevice fungerar som en ytfabrik. Varje yta skapas med en initial storlek (som kan vara 0,0), men inga giltiga bildpunkter. En yta i sitt ursprungliga tillstånd kan omedelbart förbrukas i ett visuellt träd, till exempel via en CompositionSurfaceBrush och en SpriteVisual, men i sitt ursprungliga tillstånd har ytan ingen effekt på skärmutdata. Det är för alla ändamål helt transparent, även om det angivna alfaläget är "ogenomskinligt".
Ibland kan DirectX-enheter göras oanvändbara. Detta kan bland annat inträffa om programmet skickar ogiltiga argument till vissa DirectX-API:er, eller om grafikkortet återställs av systemet eller om drivrutinen uppdateras. Direct3D har ett API som ett program kan använda för att identifiera, asynkront, om enheten går förlorad av någon anledning. När en DirectX-enhet går förlorad måste programmet ta bort den, skapa en ny och skicka den till eventuella CompositionGraphicsDevice-objekt som tidigare var associerade med den felaktiga DirectX-enheten.
Läsa in bildpunkter i en yta
Om du vill läsa in pixlar i ytan måste programmet anropa metoden BeginDraw , som returnerar ett DirectX-gränssnitt som representerar en struktur eller Direct2D-kontext, beroende på vad programmet begär. Programmet måste sedan återge eller ladda upp bildpunkter till den strukturen. När programmet är klart måste det anropa metoden EndDraw . Endast vid den tidpunkten är de nya pixlarna tillgängliga för komposition, men de visas fortfarande inte på skärmen förrän vid nästa tillfälle när alla ändringar i det visuella trädet har bekräftats. Om det visuella trädet checkas in innan EndDraw anropas visas inte uppdateringen som pågår på skärmen och ytan fortsätter att visa innehållet som den hade före BeginDraw. När EndDraw anropas ogiltigförklaras textur- eller Direct2D-kontextpekaren som returneras av BeginDraw. Ett program ska aldrig cachelagra pekaren utanför EndDraw-anropet .
Programmet kan bara anropa BeginDraw på en yta i taget för en viss CompositionGraphicsDevice. När du har anropat BeginDraw måste programmet anropa EndDraw på den ytan innan det anropar BeginDraw på en annan. Eftersom API:et är agilt ansvarar programmet för att synkronisera dessa anrop om det vill utföra rendering från flera arbetstrådar. Om ett program vill avbryta återgivningen av en yta och tillfälligt växla till en annan kan programmet använda metoden SuspendDraw . Detta gör att en annan BeginDraw kan lyckas, men gör inte den första ytuppdateringen tillgänglig för komposition på skärmen. På så sätt kan programmet utföra flera uppdateringar på ett transaktionellt sätt. När en yta har pausats kan programmet fortsätta uppdateringen genom att anropa metoden ResumeDraw eller deklarera att uppdateringen görs genom att anropa EndDraw. Det innebär att endast en yta kan uppdateras aktivt åt gången för en viss CompositionGraphicsDevice. Varje grafikenhet behåller det här tillståndet oberoende av de andra, så ett program kan återges till två ytor samtidigt om de tillhör olika grafikenheter. Detta hindrar dock videominnet för dessa två ytor från att poolas tillsammans och är därför mindre minneseffektivt.
Metoderna BeginDraw, SuspendDraw, ResumeDraw och EndDraw returnerar fel om programmet utför en felaktig åtgärd (till exempel att skicka ogiltiga argument eller anropa BeginDraw på en yta innan EndDraw anropas på en annan). De här typerna av fel representerar programbuggar och därför är förväntningarna att de hanteras med ett fel snabbt. BeginDraw kan också returnera ett fel om den underliggande DirectX-enheten går förlorad. Det här felet är inte allvarligt eftersom programmet kan återskapa sin DirectX-enhet och försöka igen. Därför förväntas programmet hantera enhetsförlust genom att helt enkelt hoppa över renderingen. Om BeginDraw misslyckas av någon anledning ska programmet inte heller anropa EndDraw, eftersom det aldrig lyckades från början.
Rullning
När ett program anropar BeginDraw av prestandaskäl garanteras inte innehållet i den returnerade strukturen vara det tidigare innehållet på ytan. Programmet måste anta att innehållet är slumpmässigt och därför måste programmet se till att alla bildpunkter berörs, antingen genom att rensa ytan innan återgivningen eller genom att rita tillräckligt med ogenomskinliga innehåll för att täcka hela den uppdaterade rektangeln. Detta, kombinerat med det faktum att texturpekaren endast är giltig mellan BeginDraw - och EndDraw-anrop , gör det omöjligt för programmet att kopiera tidigare innehåll från ytan. Därför erbjuder vi en rullningsmetod som gör att programmet kan utföra en bildpunktskopia på samma yta.
Exempel på C++/WinRT-användning
I följande kodexempel visas ett interoperationsscenario för kompositionsinterop i en Windows App SDK-kontext. Exemplet kombinerar typer från den Windows Runtime-baserade ytan i Microsoft.UI.Composition, tillsammans med typer från interop-rubrikerna och kod som renderar text med hjälp av COM-baserade DirectWrite- och Direct2D-API:er. I exemplet används BeginDraw och EndDraw för att göra det smidigt att samverka mellan dessa tekniker. I exemplet används DirectWrite för att lägga ut texten och sedan använder den Direct2D för att återge den. Enheten för kompositionsgrafik accepterar Direct2D-enheten direkt vid initieringstillfället. På så sätt kan BeginDraw returnera en ID2D1DeviceContext-gränssnittspekare , vilket är betydligt effektivare än att programmet skapar en Direct2D-kontext för att omsluta ett returnerat ID3D11Texture2D-gränssnitt vid varje ritningsåtgärd.
Om du vill prova C++/WinRT-kodexemplet nedan skapar du först ett nytt WinUI-appprojekt i Visual Studio (för krav finns i Visual Studio-stöd för C++/WinRT). Ersätt innehållet i dina pch.hApp.cpp och källkodsfilerna med kodlistorna nedan och skapa och kör sedan. Programmet renderar strängen "Hello, World!" i svart text på en transparent bakgrund.
// 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