// Copyright © 2019 piet-gpu developers. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! This is a Windows-specific error mechanism (adapted from piet-dx12), //! but we should adapt it to be more general. use winapi::shared::winerror; pub enum Error { Hresult(winerror::HRESULT), ExplainedHr(&'static str, winerror::HRESULT), } impl std::fmt::Debug for Error { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { match self { Error::Hresult(hr) => write!(f, "hresult {:x}", hr), Error::ExplainedHr(exp, hr) => { write!(f, "{}: ", exp)?; write_hr(f, *hr) } } } } impl std::fmt::Display for Error { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { std::fmt::Debug::fmt(self, f) } } impl std::error::Error for Error {} /// Strings for errors we're likely to see. /// /// See https://docs.microsoft.com/en-us/windows/win32/direct3ddxgi/dxgi-error fn err_str_for_hr(hr: winerror::HRESULT) -> Option<&'static str> { Some(match hr as u32 { 0x80004005 => "E_FAIL", 0x80070057 => "E_INVALIDARG", 0x887a0001 => "DXGI_ERROR_INVALID_CALL", 0x887a0002 => "DXGI_ERROR_NOT_FOUND", 0x887a0004 => "DXGI_ERROR_UNSUPPORTED", 0x887a0005 => "DXGI_ERROR_DEVICE_REMOVED", 0x887a0006 => "DXGI_ERROR_DEVICE_HUNG", _ => return None, }) } fn write_hr(f: &mut std::fmt::Formatter, hr: winerror::HRESULT) -> std::fmt::Result { if let Some(err_str) = err_str_for_hr(hr) { write!(f, "{:x} ({})", hr, err_str) } else { write!(f, "{:x}", hr) } } pub type D3DResult = (T, winerror::HRESULT); pub fn error_if_failed_else_value(result: D3DResult) -> Result { let (result_value, hresult) = result; if winerror::SUCCEEDED(hresult) { Ok(result_value) } else { Err(Error::Hresult(hresult)) } } pub fn error_if_failed_else_unit(hresult: winerror::HRESULT) -> Result<(), Error> { error_if_failed_else_value(((), hresult)) } pub fn explain_error(hresult: winerror::HRESULT, explanation: &'static str) -> Result<(), Error> { if winerror::SUCCEEDED(hresult) { Ok(()) } else { Err(Error::ExplainedHr(explanation, hresult)) } }