RunWithDeviceFlags EnsureDeviceCreated()

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;
        }