in winrt/lib/xaml/RecreatableDeviceManager.impl.h [270:388]
RunWithDeviceFlags EnsureDeviceCreated(Sender* sender, DeviceCreationOptions deviceCreationOptions)
{
std::unique_lock<std::recursive_mutex> lock(m_currentOperationMutex);
RunWithDeviceFlags flags{};
//
// If we are requesting a device that's shared, when it previously
// wasn't or vice versa- or, a different device type (hardware
// versus software), the device needs to be cleared and re-created.
//
if (m_device && m_deviceCreationOptions != deviceCreationOptions)
{
m_device.Reset();
m_committedDevice->MarkAsUnusable();
}
//
// If we've never created a device, or we've seen a device lost
// error for the one we have, then we'll need to create a new
// device.
//
if (!m_device)
{
if (deviceCreationOptions.CustomDevice)
{
//
// We only commit non-lost custom devices.
//
if (!IsDeviceLost(deviceCreationOptions.CustomDevice.Get()))
{
m_device = deviceCreationOptions.CustomDevice;
}
}
else if (!deviceCreationOptions.CustomDevice)
{
m_device = CreateDevice(deviceCreationOptions);
}
m_deviceCreationOptions = deviceCreationOptions;
flags = RunWithDeviceFlags::NewlyCreatedDevice;
}
//
// While there's an operation pending we can't use any new device we
// created.
//
if (m_currentOperationIsPending)
return flags | RunWithDeviceFlags::ResourcesNotCreated;
if (m_currentOperation)
{
try
{
ProcessCurrentOperationResult();
}
catch (DeviceLostException const& e)
{
HandleDeviceLostException(e.GetHr());
// If it was just the committed device that was lost,
// m_device might still be valid, but if it isn't we can't
// continue.
if (!m_device)
throw;
}
}
//
// From this point on we know that there are no outstanding
// CreateResources operations.
//
// If we haven't already, we can commit to the new device.
//
if (!m_committedDevice || m_committedDevice->IsUnusable())
{
auto reason = !m_committedDevice ? CanvasCreateResourcesReason::FirstTime :
CanvasCreateResourcesReason::NewDevice;
m_committedDevice = std::make_unique<CommittedDevice>(m_device, reason);
}
assert(m_committedDevice->GetDevice() == m_device);
//
// If the DPI has changed, tell the device that it needs to reload resources.
//
if (m_dpiChanged)
{
m_committedDevice->SetDpiChanged();
m_dpiChanged = false;
}
//
// Raise the CreateResources event if we haven't managed to
// successfully CreateResources since we committed to the new
// device, or if the DPI has changed.
//
if (m_committedDevice->NeedsCreateResources())
{
auto eventArgs = MakeEventArgs(m_committedDevice->GetCreateResourcesReason());
ThrowIfFailed(m_createResourcesEventSource.InvokeAll(sender, eventArgs.Get()));
//
// One of the CreateResources handlers might have registered an
// operation for us to track.
//
if (m_currentOperationIsPending)
flags = flags | RunWithDeviceFlags::ResourcesNotCreated;
else
m_committedDevice->SetResourcesCreated();
}
return flags;
}