Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

#include "pch.h"
#include "DeviceLostHelper.h"

namespace winrt::DrawingIslandComponents::implementation
{
void DeviceLostHelper::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 DeviceLostHelper::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;
m_dxgiDevice = nullptr;
}
}

void CALLBACK DeviceLostHelper::OnDeviceLost(PTP_CALLBACK_INSTANCE /* instance */, PVOID context, PTP_WAIT /* wait */, TP_WAIT_RESULT /* waitResult */)
{
// Get the DeviceLostHelper context object.
auto deviceLostHelper = reinterpret_cast<DeviceLostHelper*>(context);

// Create a local reference to the old device before releasing the helper object's reference.
auto oldDevice = deviceLostHelper->m_device;

// Stop listening for device lost events on the old device.
deviceLostHelper->StopWatchingCurrentDevice();

// Invoke the event handler.
deviceLostHelper->RaiseDeviceLostEvent(oldDevice);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

#pragma once

namespace winrt::DrawingIslandComponents::implementation
{
struct DeviceLostEventArgs
{
DeviceLostEventArgs(IDirect3DDevice const& device) : m_device(device)
{
}

IDirect3DDevice Device() { return m_device; }

private:
IDirect3DDevice m_device;
};

struct DeviceLostHelper
{
DeviceLostHelper() = default;

~DeviceLostHelper()
{
StopWatchingCurrentDevice();
}

// Not copyable or assignable.
DeviceLostHelper(DeviceLostHelper const&) = delete;
void operator=(DeviceLostHelper const&) = delete;

void WatchDevice(winrt::com_ptr<::IDXGIDevice> const& dxgiDevice);

void StopWatchingCurrentDevice();

void DeviceLost(winrt::delegate<DeviceLostHelper const*, DeviceLostEventArgs const&> const& handler)
{
m_deviceLost = handler;
}

private:
void RaiseDeviceLostEvent(IDirect3DDevice const& oldDevice)
{
m_deviceLost(this, DeviceLostEventArgs{ oldDevice });
}

static void CALLBACK OnDeviceLost(PTP_CALLBACK_INSTANCE /* instance */, PVOID context, PTP_WAIT /* wait */, TP_WAIT_RESULT /* waitResult */);

private:
winrt::delegate<DeviceLostHelper const*, DeviceLostEventArgs const&> m_deviceLost;
IDirect3DDevice m_device;
winrt::com_ptr<::IDXGIDevice> m_dxgiDevice;
PTP_WAIT m_onDeviceLostHandler{ nullptr };
winrt::handle m_eventHandle;
DWORD m_cookie{ 0 };
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ namespace winrt::DrawingIslandComponents::implementation
{
m_output.Compositor = compositor;
m_output.TextRenderer = std::make_shared<TextRenderer>(m_output.Compositor);
m_output.DeviceLostHelper.WatchDevice(m_output.TextRenderer->GetDevice());
m_output.DeviceLostHelper.DeviceLost({ this, &DrawingIsland::OnDirect3DDeviceLost });

// Create the Compositor and the Content:
// - The Bridge's connection to the Window will keep everything alive, and perform an
Expand Down Expand Up @@ -774,6 +776,25 @@ namespace winrt::DrawingIslandComponents::implementation
}


void
DrawingIsland::OnDirect3DDeviceLost(
DeviceLostHelper const* /* sender */,
DeviceLostEventArgs const& /* args */)
{
// Recreate the text renderer's D3D and D2D devices.
m_output.TextRenderer->RecreateDirect2DDevice();

// Give each item an opportunity to recreate its device-dependent resources.
for (auto& item : m_items.Items)
{
item->OnDeviceLost();
}

// Listen for device lost on the new device.
m_output.DeviceLostHelper.WatchDevice(m_output.TextRenderer->GetDevice());
}


void
DrawingIsland::Output_Initialize()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "AutomationFragmentRoot.h"
#include "AutomationPeer.h"
#include "TextRenderer.h"
#include "DeviceLostHelper.h"
#include "TextItem.h"

namespace winrt::DrawingIslandComponents::implementation
Expand Down Expand Up @@ -136,6 +137,10 @@ namespace winrt::DrawingIslandComponents::implementation

void Island_OnStateChanged();

void OnDirect3DDeviceLost(
DeviceLostHelper const* /* sender */,
DeviceLostEventArgs const& /* args */);

void Output_Initialize();

void Output_AddVisual(
Expand Down Expand Up @@ -197,6 +202,7 @@ namespace winrt::DrawingIslandComponents::implementation
winrt::ContainerVisual RootVisual{ nullptr };

std::shared_ptr<TextRenderer> TextRenderer;
DeviceLostHelper DeviceLostHelper;

float Opacity{ 0.5f };

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,9 @@
<ClInclude Include="AutomationFragmentRoot.h" />
<ClInclude Include="AutomationFragment.h" />
<ClInclude Include="AutomationPeer.h" />
<ClInclude Include="DeviceLostHelper.h" />
<ClInclude Include="IslandFragmentRoot.h" />
<ClInclude Include="NodeSimpleFragment.h" />
<ClInclude Include="pch.h" />
<ClInclude Include="DrawingIsland.h">
<DependentUpon>Components.idl</DependentUpon>
Expand All @@ -140,6 +143,9 @@
<ItemGroup>
<ClCompile Include="AutomationFragmentRoot.cpp" />
<ClCompile Include="AutomationFragment.cpp" />
<ClCompile Include="DeviceLostHelper.cpp" />
<ClCompile Include="IslandFragmentRoot.cpp" />
<ClCompile Include="NodeSimpleFragment.cpp" />
<ClCompile Include="pch.cpp">
<PrecompiledHeader>Create</PrecompiledHeader>
</ClCompile>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
<ClCompile Include="Item.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="DeviceLostHelper.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="pch.h" />
Expand All @@ -57,6 +58,9 @@
<ClInclude Include="AutomationPeer.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="DeviceLostHelper.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Midl Include="Components.idl" />
Expand Down
4 changes: 4 additions & 0 deletions Samples/Islands/DrawingIsland/DrawingIslandComponents/Item.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ namespace winrt::DrawingIslandComponents::implementation
{
}

virtual void OnDeviceLost()
{
}

winrt::SpriteVisual const& GetVisual() const noexcept
{
return m_visual;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,4 @@ namespace winrt::DrawingIslandComponents::implementation
// Render the text to the sprite visual.
m_textRenderer->Render(m_text.c_str(), m_backgroundColor, m_textColor, GetVisual());
}

void TextItem::OnDpiScaleChanged()
{
// Re-render the text using the current DPI scale.
InitializeVisual();
}
}
12 changes: 11 additions & 1 deletion Samples/Islands/DrawingIsland/DrawingIslandComponents/TextItem.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,17 @@ namespace winrt::DrawingIslandComponents::implementation
Windows::UI::Color textColor,
std::wstring const& text);

void OnDpiScaleChanged() override;
void OnDpiScaleChanged() override
{
// Re-render the text using the current DPI scale.
InitializeVisual();
}

void OnDeviceLost() override
{
// Re-render the text using the current device.
InitializeVisual();
}

private:
void InitializeVisual();
Expand Down
Loading