diff --git a/DDSTextureLoader/DDSTextureLoader.cpp b/DDSTextureLoader/DDSTextureLoader.cpp index dc0a2e2..9a2bdb3 100644 --- a/DDSTextureLoader/DDSTextureLoader.cpp +++ b/DDSTextureLoader/DDSTextureLoader.cpp @@ -18,12 +18,12 @@ // http://go.microsoft.com/fwlink/?LinkId=248929 //-------------------------------------------------------------------------------------- +#include "DDSTextureLoader.h" + #include #include #include -#include "DDSTextureLoader.h" - #if !defined(NO_D3D11_DEBUG_NAME) && ( defined(_DEBUG) || defined(PROFILE) ) #pragma comment(lib,"dxguid.lib") #endif diff --git a/DDSTextureLoader/DDSTextureLoader12.cpp b/DDSTextureLoader/DDSTextureLoader12.cpp index 2888bfe..00d802e 100644 --- a/DDSTextureLoader/DDSTextureLoader12.cpp +++ b/DDSTextureLoader/DDSTextureLoader12.cpp @@ -18,12 +18,12 @@ // http://go.microsoft.com/fwlink/?LinkID=615561 //-------------------------------------------------------------------------------------- +#include "DDSTextureLoader12.h" + #include #include #include -#include "DDSTextureLoader12.h" - #include using namespace DirectX; diff --git a/WICTextureLoader/WICTextureLoader.cpp b/WICTextureLoader/WICTextureLoader.cpp index ec65980..6b1bbb1 100644 --- a/WICTextureLoader/WICTextureLoader.cpp +++ b/WICTextureLoader/WICTextureLoader.cpp @@ -28,6 +28,8 @@ // We could load multi-frame images (TIFF/GIF) into a texture array. // For now, we just load the first frame (note: DirectXTex supports multi-frame images) +#include "WICTextureLoader.h" + #include #include @@ -37,159 +39,172 @@ #include -#include "WICTextureLoader.h" - #if !defined(NO_D3D11_DEBUG_NAME) && ( defined(_DEBUG) || defined(PROFILE) ) #pragma comment(lib,"dxguid.lib") #endif using Microsoft::WRL::ComPtr; -//-------------------------------------------------------------------------------------- - -template -inline void SetDebugObjectName(_In_ ID3D11DeviceChild* resource, _In_ const char (&name)[TNameLength]) +namespace { -#if !defined(NO_D3D11_DEBUG_NAME) && ( defined(_DEBUG) || defined(PROFILE) ) - resource->SetPrivateData(WKPDID_D3DDebugObjectName, TNameLength - 1, name); -#else - UNREFERENCED_PARAMETER(resource); - UNREFERENCED_PARAMETER(name); -#endif -} + //-------------------------------------------------------------------------------------- + template + inline void SetDebugObjectName(_In_ ID3D11DeviceChild* resource, _In_ const char (&name)[TNameLength]) + { + #if !defined(NO_D3D11_DEBUG_NAME) && ( defined(_DEBUG) || defined(PROFILE) ) + resource->SetPrivateData(WKPDID_D3DDebugObjectName, TNameLength - 1, name); + #else + UNREFERENCED_PARAMETER(resource); + UNREFERENCED_PARAMETER(name); + #endif + } -//------------------------------------------------------------------------------------- -// WIC Pixel Format Translation Data -//------------------------------------------------------------------------------------- -struct WICTranslate -{ - GUID wic; - DXGI_FORMAT format; -}; + //------------------------------------------------------------------------------------- + // WIC Pixel Format Translation Data + //------------------------------------------------------------------------------------- + struct WICTranslate + { + GUID wic; + DXGI_FORMAT format; + }; -static WICTranslate g_WICFormats[] = -{ - { GUID_WICPixelFormat128bppRGBAFloat, DXGI_FORMAT_R32G32B32A32_FLOAT }, + WICTranslate g_WICFormats[] = + { + { GUID_WICPixelFormat128bppRGBAFloat, DXGI_FORMAT_R32G32B32A32_FLOAT }, - { GUID_WICPixelFormat64bppRGBAHalf, DXGI_FORMAT_R16G16B16A16_FLOAT }, - { GUID_WICPixelFormat64bppRGBA, DXGI_FORMAT_R16G16B16A16_UNORM }, + { GUID_WICPixelFormat64bppRGBAHalf, DXGI_FORMAT_R16G16B16A16_FLOAT }, + { GUID_WICPixelFormat64bppRGBA, DXGI_FORMAT_R16G16B16A16_UNORM }, - { GUID_WICPixelFormat32bppRGBA, DXGI_FORMAT_R8G8B8A8_UNORM }, - { GUID_WICPixelFormat32bppBGRA, DXGI_FORMAT_B8G8R8A8_UNORM }, // DXGI 1.1 - { GUID_WICPixelFormat32bppBGR, DXGI_FORMAT_B8G8R8X8_UNORM }, // DXGI 1.1 + { GUID_WICPixelFormat32bppRGBA, DXGI_FORMAT_R8G8B8A8_UNORM }, + { GUID_WICPixelFormat32bppBGRA, DXGI_FORMAT_B8G8R8A8_UNORM }, // DXGI 1.1 + { GUID_WICPixelFormat32bppBGR, DXGI_FORMAT_B8G8R8X8_UNORM }, // DXGI 1.1 - { GUID_WICPixelFormat32bppRGBA1010102XR, DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM }, // DXGI 1.1 - { GUID_WICPixelFormat32bppRGBA1010102, DXGI_FORMAT_R10G10B10A2_UNORM }, + { GUID_WICPixelFormat32bppRGBA1010102XR, DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM }, // DXGI 1.1 + { GUID_WICPixelFormat32bppRGBA1010102, DXGI_FORMAT_R10G10B10A2_UNORM }, - { GUID_WICPixelFormat16bppBGRA5551, DXGI_FORMAT_B5G5R5A1_UNORM }, - { GUID_WICPixelFormat16bppBGR565, DXGI_FORMAT_B5G6R5_UNORM }, + { GUID_WICPixelFormat16bppBGRA5551, DXGI_FORMAT_B5G5R5A1_UNORM }, + { GUID_WICPixelFormat16bppBGR565, DXGI_FORMAT_B5G6R5_UNORM }, - { GUID_WICPixelFormat32bppGrayFloat, DXGI_FORMAT_R32_FLOAT }, - { GUID_WICPixelFormat16bppGrayHalf, DXGI_FORMAT_R16_FLOAT }, - { GUID_WICPixelFormat16bppGray, DXGI_FORMAT_R16_UNORM }, - { GUID_WICPixelFormat8bppGray, DXGI_FORMAT_R8_UNORM }, + { GUID_WICPixelFormat32bppGrayFloat, DXGI_FORMAT_R32_FLOAT }, + { GUID_WICPixelFormat16bppGrayHalf, DXGI_FORMAT_R16_FLOAT }, + { GUID_WICPixelFormat16bppGray, DXGI_FORMAT_R16_UNORM }, + { GUID_WICPixelFormat8bppGray, DXGI_FORMAT_R8_UNORM }, - { GUID_WICPixelFormat8bppAlpha, DXGI_FORMAT_A8_UNORM }, -}; + { GUID_WICPixelFormat8bppAlpha, DXGI_FORMAT_A8_UNORM }, + }; -//------------------------------------------------------------------------------------- -// WIC Pixel Format nearest conversion table -//------------------------------------------------------------------------------------- + //------------------------------------------------------------------------------------- + // WIC Pixel Format nearest conversion table + //------------------------------------------------------------------------------------- -struct WICConvert -{ - GUID source; - GUID target; -}; + struct WICConvert + { + GUID source; + GUID target; + }; -static WICConvert g_WICConvert[] = -{ - // Note target GUID in this conversion table must be one of those directly supported formats (above). + WICConvert g_WICConvert[] = + { + // Note target GUID in this conversion table must be one of those directly supported formats (above). - { GUID_WICPixelFormatBlackWhite, GUID_WICPixelFormat8bppGray }, // DXGI_FORMAT_R8_UNORM + { GUID_WICPixelFormatBlackWhite, GUID_WICPixelFormat8bppGray }, // DXGI_FORMAT_R8_UNORM - { GUID_WICPixelFormat1bppIndexed, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM - { GUID_WICPixelFormat2bppIndexed, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM - { GUID_WICPixelFormat4bppIndexed, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM - { GUID_WICPixelFormat8bppIndexed, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM + { GUID_WICPixelFormat1bppIndexed, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM + { GUID_WICPixelFormat2bppIndexed, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM + { GUID_WICPixelFormat4bppIndexed, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM + { GUID_WICPixelFormat8bppIndexed, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM - { GUID_WICPixelFormat2bppGray, GUID_WICPixelFormat8bppGray }, // DXGI_FORMAT_R8_UNORM - { GUID_WICPixelFormat4bppGray, GUID_WICPixelFormat8bppGray }, // DXGI_FORMAT_R8_UNORM + { GUID_WICPixelFormat2bppGray, GUID_WICPixelFormat8bppGray }, // DXGI_FORMAT_R8_UNORM + { GUID_WICPixelFormat4bppGray, GUID_WICPixelFormat8bppGray }, // DXGI_FORMAT_R8_UNORM - { GUID_WICPixelFormat16bppGrayFixedPoint, GUID_WICPixelFormat16bppGrayHalf }, // DXGI_FORMAT_R16_FLOAT - { GUID_WICPixelFormat32bppGrayFixedPoint, GUID_WICPixelFormat32bppGrayFloat }, // DXGI_FORMAT_R32_FLOAT + { GUID_WICPixelFormat16bppGrayFixedPoint, GUID_WICPixelFormat16bppGrayHalf }, // DXGI_FORMAT_R16_FLOAT + { GUID_WICPixelFormat32bppGrayFixedPoint, GUID_WICPixelFormat32bppGrayFloat }, // DXGI_FORMAT_R32_FLOAT - { GUID_WICPixelFormat16bppBGR555, GUID_WICPixelFormat16bppBGRA5551 }, // DXGI_FORMAT_B5G5R5A1_UNORM + { GUID_WICPixelFormat16bppBGR555, GUID_WICPixelFormat16bppBGRA5551 }, // DXGI_FORMAT_B5G5R5A1_UNORM - { GUID_WICPixelFormat32bppBGR101010, GUID_WICPixelFormat32bppRGBA1010102 }, // DXGI_FORMAT_R10G10B10A2_UNORM + { GUID_WICPixelFormat32bppBGR101010, GUID_WICPixelFormat32bppRGBA1010102 }, // DXGI_FORMAT_R10G10B10A2_UNORM - { GUID_WICPixelFormat24bppBGR, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM - { GUID_WICPixelFormat24bppRGB, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM - { GUID_WICPixelFormat32bppPBGRA, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM - { GUID_WICPixelFormat32bppPRGBA, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM + { GUID_WICPixelFormat24bppBGR, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM + { GUID_WICPixelFormat24bppRGB, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM + { GUID_WICPixelFormat32bppPBGRA, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM + { GUID_WICPixelFormat32bppPRGBA, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM - { GUID_WICPixelFormat48bppRGB, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM - { GUID_WICPixelFormat48bppBGR, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM - { GUID_WICPixelFormat64bppBGRA, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM - { GUID_WICPixelFormat64bppPRGBA, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM - { GUID_WICPixelFormat64bppPBGRA, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM + { GUID_WICPixelFormat48bppRGB, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM + { GUID_WICPixelFormat48bppBGR, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM + { GUID_WICPixelFormat64bppBGRA, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM + { GUID_WICPixelFormat64bppPRGBA, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM + { GUID_WICPixelFormat64bppPBGRA, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM - { GUID_WICPixelFormat48bppRGBFixedPoint, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT - { GUID_WICPixelFormat48bppBGRFixedPoint, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT - { GUID_WICPixelFormat64bppRGBAFixedPoint, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT - { GUID_WICPixelFormat64bppBGRAFixedPoint, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT - { GUID_WICPixelFormat64bppRGBFixedPoint, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT - { GUID_WICPixelFormat64bppRGBHalf, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT - { GUID_WICPixelFormat48bppRGBHalf, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT + { GUID_WICPixelFormat48bppRGBFixedPoint, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT + { GUID_WICPixelFormat48bppBGRFixedPoint, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT + { GUID_WICPixelFormat64bppRGBAFixedPoint, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT + { GUID_WICPixelFormat64bppBGRAFixedPoint, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT + { GUID_WICPixelFormat64bppRGBFixedPoint, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT + { GUID_WICPixelFormat64bppRGBHalf, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT + { GUID_WICPixelFormat48bppRGBHalf, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT - { GUID_WICPixelFormat128bppPRGBAFloat, GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT - { GUID_WICPixelFormat128bppRGBFloat, GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT - { GUID_WICPixelFormat128bppRGBAFixedPoint, GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT - { GUID_WICPixelFormat128bppRGBFixedPoint, GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT - { GUID_WICPixelFormat32bppRGBE, GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT + { GUID_WICPixelFormat128bppPRGBAFloat, GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT + { GUID_WICPixelFormat128bppRGBFloat, GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT + { GUID_WICPixelFormat128bppRGBAFixedPoint, GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT + { GUID_WICPixelFormat128bppRGBFixedPoint, GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT + { GUID_WICPixelFormat32bppRGBE, GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT - { GUID_WICPixelFormat32bppCMYK, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM - { GUID_WICPixelFormat64bppCMYK, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM - { GUID_WICPixelFormat40bppCMYKAlpha, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM - { GUID_WICPixelFormat80bppCMYKAlpha, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM + { GUID_WICPixelFormat32bppCMYK, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM + { GUID_WICPixelFormat64bppCMYK, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM + { GUID_WICPixelFormat40bppCMYKAlpha, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM + { GUID_WICPixelFormat80bppCMYKAlpha, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM #if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) || defined(_WIN7_PLATFORM_UPDATE) - { GUID_WICPixelFormat32bppRGB, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM - { GUID_WICPixelFormat64bppRGB, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM - { GUID_WICPixelFormat64bppPRGBAHalf, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT + { GUID_WICPixelFormat32bppRGB, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM + { GUID_WICPixelFormat64bppRGB, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM + { GUID_WICPixelFormat64bppPRGBAHalf, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT #endif - // We don't support n-channel formats -}; + // We don't support n-channel formats + }; -static bool g_WIC2 = false; + bool g_WIC2 = false; -//-------------------------------------------------------------------------------------- -static IWICImagingFactory* _GetWIC() -{ - static IWICImagingFactory* s_Factory = nullptr; + //-------------------------------------------------------------------------------------- + IWICImagingFactory* _GetWIC() + { + static IWICImagingFactory* s_Factory = nullptr; - if ( s_Factory ) - return s_Factory; + if ( s_Factory ) + return s_Factory; #if(_WIN32_WINNT >= _WIN32_WINNT_WIN8) || defined(_WIN7_PLATFORM_UPDATE) - HRESULT hr = CoCreateInstance( - CLSID_WICImagingFactory2, - nullptr, - CLSCTX_INPROC_SERVER, - __uuidof(IWICImagingFactory2), - (LPVOID*)&s_Factory - ); + HRESULT hr = CoCreateInstance( + CLSID_WICImagingFactory2, + nullptr, + CLSCTX_INPROC_SERVER, + __uuidof(IWICImagingFactory2), + (LPVOID*)&s_Factory + ); - if ( SUCCEEDED(hr) ) - { - // WIC2 is available on Windows 8 and Windows 7 SP1 with KB 2670838 installed - g_WIC2 = true; - } - else - { - hr = CoCreateInstance( - CLSID_WICImagingFactory1, + if ( SUCCEEDED(hr) ) + { + // WIC2 is available on Windows 8 and Windows 7 SP1 with KB 2670838 installed + g_WIC2 = true; + } + else + { + hr = CoCreateInstance( + CLSID_WICImagingFactory1, + nullptr, + CLSCTX_INPROC_SERVER, + IID_PPV_ARGS(&s_Factory) + ); + + if ( FAILED(hr) ) + { + s_Factory = nullptr; + return nullptr; + } + } +#else + HRESULT hr = CoCreateInstance( + CLSID_WICImagingFactory, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&s_Factory) @@ -200,364 +215,379 @@ static IWICImagingFactory* _GetWIC() s_Factory = nullptr; return nullptr; } - } -#else - HRESULT hr = CoCreateInstance( - CLSID_WICImagingFactory, - nullptr, - CLSCTX_INPROC_SERVER, - IID_PPV_ARGS(&s_Factory) - ); - - if ( FAILED(hr) ) - { - s_Factory = nullptr; - return nullptr; - } #endif - return s_Factory; -} - -//--------------------------------------------------------------------------------- -static DXGI_FORMAT _WICToDXGI( const GUID& guid ) -{ - for( size_t i=0; i < _countof(g_WICFormats); ++i ) - { - if ( memcmp( &g_WICFormats[i].wic, &guid, sizeof(GUID) ) == 0 ) - return g_WICFormats[i].format; + return s_Factory; } + //--------------------------------------------------------------------------------- + DXGI_FORMAT _WICToDXGI( const GUID& guid ) + { + for( size_t i=0; i < _countof(g_WICFormats); ++i ) + { + if ( memcmp( &g_WICFormats[i].wic, &guid, sizeof(GUID) ) == 0 ) + return g_WICFormats[i].format; + } + #if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) || defined(_WIN7_PLATFORM_UPDATE) - if ( g_WIC2 ) - { - if ( memcmp( &GUID_WICPixelFormat96bppRGBFloat, &guid, sizeof(GUID) ) == 0 ) - return DXGI_FORMAT_R32G32B32_FLOAT; - } + if ( g_WIC2 ) + { + if ( memcmp( &GUID_WICPixelFormat96bppRGBFloat, &guid, sizeof(GUID) ) == 0 ) + return DXGI_FORMAT_R32G32B32_FLOAT; + } #endif - return DXGI_FORMAT_UNKNOWN; -} + return DXGI_FORMAT_UNKNOWN; + } -//--------------------------------------------------------------------------------- -static size_t _WICBitsPerPixel( REFGUID targetGuid ) -{ - IWICImagingFactory* pWIC = _GetWIC(); - if ( !pWIC ) - return 0; + //--------------------------------------------------------------------------------- + size_t _WICBitsPerPixel( REFGUID targetGuid ) + { + IWICImagingFactory* pWIC = _GetWIC(); + if ( !pWIC ) + return 0; - ComPtr cinfo; - if ( FAILED( pWIC->CreateComponentInfo( targetGuid, cinfo.GetAddressOf() ) ) ) - return 0; + ComPtr cinfo; + if ( FAILED( pWIC->CreateComponentInfo( targetGuid, cinfo.GetAddressOf() ) ) ) + return 0; - WICComponentType type; - if ( FAILED( cinfo->GetComponentType( &type ) ) ) - return 0; + WICComponentType type; + if ( FAILED( cinfo->GetComponentType( &type ) ) ) + return 0; - if ( type != WICPixelFormat ) - return 0; + if ( type != WICPixelFormat ) + return 0; - ComPtr pfinfo; - if ( FAILED( cinfo.As( &pfinfo ) ) ) - return 0; + ComPtr pfinfo; + if ( FAILED( cinfo.As( &pfinfo ) ) ) + return 0; - UINT bpp; - if ( FAILED( pfinfo->GetBitsPerPixel( &bpp ) ) ) - return 0; + UINT bpp; + if ( FAILED( pfinfo->GetBitsPerPixel( &bpp ) ) ) + return 0; - return bpp; -} - - -//-------------------------------------------------------------------------------------- -static DXGI_FORMAT MakeSRGB( _In_ DXGI_FORMAT format ) -{ - switch( format ) - { - case DXGI_FORMAT_R8G8B8A8_UNORM: - return DXGI_FORMAT_R8G8B8A8_UNORM_SRGB; - - case DXGI_FORMAT_BC1_UNORM: - return DXGI_FORMAT_BC1_UNORM_SRGB; - - case DXGI_FORMAT_BC2_UNORM: - return DXGI_FORMAT_BC2_UNORM_SRGB; - - case DXGI_FORMAT_BC3_UNORM: - return DXGI_FORMAT_BC3_UNORM_SRGB; - - case DXGI_FORMAT_B8G8R8A8_UNORM: - return DXGI_FORMAT_B8G8R8A8_UNORM_SRGB; - - case DXGI_FORMAT_B8G8R8X8_UNORM: - return DXGI_FORMAT_B8G8R8X8_UNORM_SRGB; - - case DXGI_FORMAT_BC7_UNORM: - return DXGI_FORMAT_BC7_UNORM_SRGB; - - default: - return format; + return bpp; } -} -//--------------------------------------------------------------------------------- -static HRESULT CreateTextureFromWIC( _In_ ID3D11Device* d3dDevice, - _In_opt_ ID3D11DeviceContext* d3dContext, - _In_ IWICBitmapFrameDecode *frame, - _In_ size_t maxsize, - _In_ D3D11_USAGE usage, - _In_ unsigned int bindFlags, - _In_ unsigned int cpuAccessFlags, - _In_ unsigned int miscFlags, - _In_ bool forceSRGB, - _Out_opt_ ID3D11Resource** texture, - _Out_opt_ ID3D11ShaderResourceView** textureView ) -{ - UINT width, height; - HRESULT hr = frame->GetSize( &width, &height ); - if ( FAILED(hr) ) - return hr; - - assert( width > 0 && height > 0 ); - - if ( !maxsize ) + //-------------------------------------------------------------------------------------- + DXGI_FORMAT MakeSRGB( _In_ DXGI_FORMAT format ) { - // This is a bit conservative because the hardware could support larger textures than - // the Feature Level defined minimums, but doing it this way is much easier and more - // performant for WIC than the 'fail and retry' model used by DDSTextureLoader - - switch( d3dDevice->GetFeatureLevel() ) + switch( format ) { - case D3D_FEATURE_LEVEL_9_1: - case D3D_FEATURE_LEVEL_9_2: - maxsize = 2048 /*D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION*/; - break; + case DXGI_FORMAT_R8G8B8A8_UNORM: + return DXGI_FORMAT_R8G8B8A8_UNORM_SRGB; - case D3D_FEATURE_LEVEL_9_3: - maxsize = 4096 /*D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION*/; - break; + case DXGI_FORMAT_BC1_UNORM: + return DXGI_FORMAT_BC1_UNORM_SRGB; - case D3D_FEATURE_LEVEL_10_0: - case D3D_FEATURE_LEVEL_10_1: - maxsize = 8192 /*D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION*/; - break; + case DXGI_FORMAT_BC2_UNORM: + return DXGI_FORMAT_BC2_UNORM_SRGB; - default: - maxsize = D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; - break; + case DXGI_FORMAT_BC3_UNORM: + return DXGI_FORMAT_BC3_UNORM_SRGB; + + case DXGI_FORMAT_B8G8R8A8_UNORM: + return DXGI_FORMAT_B8G8R8A8_UNORM_SRGB; + + case DXGI_FORMAT_B8G8R8X8_UNORM: + return DXGI_FORMAT_B8G8R8X8_UNORM_SRGB; + + case DXGI_FORMAT_BC7_UNORM: + return DXGI_FORMAT_BC7_UNORM_SRGB; + + default: + return format; } } - assert( maxsize > 0 ); - UINT twidth, theight; - if ( width > maxsize || height > maxsize ) + //--------------------------------------------------------------------------------- + HRESULT CreateTextureFromWIC( + _In_ ID3D11Device* d3dDevice, + _In_opt_ ID3D11DeviceContext* d3dContext, + _In_ IWICBitmapFrameDecode *frame, + _In_ size_t maxsize, + _In_ D3D11_USAGE usage, + _In_ unsigned int bindFlags, + _In_ unsigned int cpuAccessFlags, + _In_ unsigned int miscFlags, + _In_ bool forceSRGB, + _Out_opt_ ID3D11Resource** texture, + _Out_opt_ ID3D11ShaderResourceView** textureView ) { - float ar = static_cast(height) / static_cast(width); - if ( width > height ) + UINT width, height; + HRESULT hr = frame->GetSize( &width, &height ); + if ( FAILED(hr) ) + return hr; + + assert( width > 0 && height > 0 ); + + if ( !maxsize ) { - twidth = static_cast( maxsize ); - theight = static_cast( static_cast(maxsize) * ar ); - } - else - { - theight = static_cast( maxsize ); - twidth = static_cast( static_cast(maxsize) / ar ); - } - assert( twidth <= maxsize && theight <= maxsize ); - } - else - { - twidth = width; - theight = height; - } + // This is a bit conservative because the hardware could support larger textures than + // the Feature Level defined minimums, but doing it this way is much easier and more + // performant for WIC than the 'fail and retry' model used by DDSTextureLoader - // Determine format - WICPixelFormatGUID pixelFormat; - hr = frame->GetPixelFormat( &pixelFormat ); - if ( FAILED(hr) ) - return hr; - - WICPixelFormatGUID convertGUID; - memcpy( &convertGUID, &pixelFormat, sizeof(WICPixelFormatGUID) ); - - size_t bpp = 0; - - DXGI_FORMAT format = _WICToDXGI( pixelFormat ); - if ( format == DXGI_FORMAT_UNKNOWN ) - { - if ( memcmp( &GUID_WICPixelFormat96bppRGBFixedPoint, &pixelFormat, sizeof(WICPixelFormatGUID) ) == 0 ) - { -#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) || defined(_WIN7_PLATFORM_UPDATE) - if ( g_WIC2 ) + switch( d3dDevice->GetFeatureLevel() ) { - memcpy( &convertGUID, &GUID_WICPixelFormat96bppRGBFloat, sizeof(WICPixelFormatGUID) ); - format = DXGI_FORMAT_R32G32B32_FLOAT; + case D3D_FEATURE_LEVEL_9_1: + case D3D_FEATURE_LEVEL_9_2: + maxsize = 2048 /*D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION*/; + break; + + case D3D_FEATURE_LEVEL_9_3: + maxsize = 4096 /*D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION*/; + break; + + case D3D_FEATURE_LEVEL_10_0: + case D3D_FEATURE_LEVEL_10_1: + maxsize = 8192 /*D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION*/; + break; + + default: + maxsize = D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; + break; + } + } + + assert( maxsize > 0 ); + + UINT twidth, theight; + if ( width > maxsize || height > maxsize ) + { + float ar = static_cast(height) / static_cast(width); + if ( width > height ) + { + twidth = static_cast( maxsize ); + theight = static_cast( static_cast(maxsize) * ar ); } else -#endif { - memcpy( &convertGUID, &GUID_WICPixelFormat128bppRGBAFloat, sizeof(WICPixelFormatGUID) ); - format = DXGI_FORMAT_R32G32B32A32_FLOAT; + theight = static_cast( maxsize ); + twidth = static_cast( static_cast(maxsize) / ar ); } + assert( twidth <= maxsize && theight <= maxsize ); } else { - for( size_t i=0; i < _countof(g_WICConvert); ++i ) - { - if ( memcmp( &g_WICConvert[i].source, &pixelFormat, sizeof(WICPixelFormatGUID) ) == 0 ) - { - memcpy( &convertGUID, &g_WICConvert[i].target, sizeof(WICPixelFormatGUID) ); + twidth = width; + theight = height; + } - format = _WICToDXGI( g_WICConvert[i].target ); - assert( format != DXGI_FORMAT_UNKNOWN ); - bpp = _WICBitsPerPixel( convertGUID ); - break; + // Determine format + WICPixelFormatGUID pixelFormat; + hr = frame->GetPixelFormat( &pixelFormat ); + if ( FAILED(hr) ) + return hr; + + WICPixelFormatGUID convertGUID; + memcpy( &convertGUID, &pixelFormat, sizeof(WICPixelFormatGUID) ); + + size_t bpp = 0; + + DXGI_FORMAT format = _WICToDXGI( pixelFormat ); + if ( format == DXGI_FORMAT_UNKNOWN ) + { + if ( memcmp( &GUID_WICPixelFormat96bppRGBFixedPoint, &pixelFormat, sizeof(WICPixelFormatGUID) ) == 0 ) + { +#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) || defined(_WIN7_PLATFORM_UPDATE) + if ( g_WIC2 ) + { + memcpy( &convertGUID, &GUID_WICPixelFormat96bppRGBFloat, sizeof(WICPixelFormatGUID) ); + format = DXGI_FORMAT_R32G32B32_FLOAT; + } + else +#endif + { + memcpy( &convertGUID, &GUID_WICPixelFormat128bppRGBAFloat, sizeof(WICPixelFormatGUID) ); + format = DXGI_FORMAT_R32G32B32A32_FLOAT; } } - } + else + { + for( size_t i=0; i < _countof(g_WICConvert); ++i ) + { + if ( memcmp( &g_WICConvert[i].source, &pixelFormat, sizeof(WICPixelFormatGUID) ) == 0 ) + { + memcpy( &convertGUID, &g_WICConvert[i].target, sizeof(WICPixelFormatGUID) ); - if ( format == DXGI_FORMAT_UNKNOWN ) - return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED ); - } - else - { - bpp = _WICBitsPerPixel( pixelFormat ); - } + format = _WICToDXGI( g_WICConvert[i].target ); + assert( format != DXGI_FORMAT_UNKNOWN ); + bpp = _WICBitsPerPixel( convertGUID ); + break; + } + } + } + + if ( format == DXGI_FORMAT_UNKNOWN ) + return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED ); + } + else + { + bpp = _WICBitsPerPixel( pixelFormat ); + } #if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) || defined(_WIN7_PLATFORM_UPDATE) - if ( (format == DXGI_FORMAT_R32G32B32_FLOAT) && d3dContext != 0 && textureView != 0 ) - { - // Special case test for optional device support for autogen mipchains for R32G32B32_FLOAT - UINT fmtSupport = 0; - hr = d3dDevice->CheckFormatSupport( DXGI_FORMAT_R32G32B32_FLOAT, &fmtSupport ); - if ( FAILED(hr) || !( fmtSupport & D3D11_FORMAT_SUPPORT_MIP_AUTOGEN ) ) + if ( (format == DXGI_FORMAT_R32G32B32_FLOAT) && d3dContext != 0 && textureView != 0 ) { - // Use R32G32B32A32_FLOAT instead which is required for Feature Level 10.0 and up - memcpy( &convertGUID, &GUID_WICPixelFormat128bppRGBAFloat, sizeof(WICPixelFormatGUID) ); - format = DXGI_FORMAT_R32G32B32A32_FLOAT; - bpp = 128; + // Special case test for optional device support for autogen mipchains for R32G32B32_FLOAT + UINT fmtSupport = 0; + hr = d3dDevice->CheckFormatSupport( DXGI_FORMAT_R32G32B32_FLOAT, &fmtSupport ); + if ( FAILED(hr) || !( fmtSupport & D3D11_FORMAT_SUPPORT_MIP_AUTOGEN ) ) + { + // Use R32G32B32A32_FLOAT instead which is required for Feature Level 10.0 and up + memcpy( &convertGUID, &GUID_WICPixelFormat128bppRGBAFloat, sizeof(WICPixelFormatGUID) ); + format = DXGI_FORMAT_R32G32B32A32_FLOAT; + bpp = 128; + } } - } #endif - if ( !bpp ) - return E_FAIL; + if ( !bpp ) + return E_FAIL; - // Handle sRGB formats - if ( forceSRGB ) - { - format = MakeSRGB( format ); - } - else - { - ComPtr metareader; - if ( SUCCEEDED( frame->GetMetadataQueryReader( metareader.GetAddressOf() ) ) ) + // Handle sRGB formats + if ( forceSRGB ) { - GUID containerFormat; - if ( SUCCEEDED( metareader->GetContainerFormat( &containerFormat ) ) ) + format = MakeSRGB( format ); + } + else + { + ComPtr metareader; + if ( SUCCEEDED( frame->GetMetadataQueryReader( metareader.GetAddressOf() ) ) ) { - // Check for sRGB colorspace metadata - bool sRGB = false; - - PROPVARIANT value; - PropVariantInit( &value ); - - if ( memcmp( &containerFormat, &GUID_ContainerFormatPng, sizeof(GUID) ) == 0 ) + GUID containerFormat; + if ( SUCCEEDED( metareader->GetContainerFormat( &containerFormat ) ) ) { - // Check for sRGB chunk - if ( SUCCEEDED( metareader->GetMetadataByName( L"/sRGB/RenderingIntent", &value ) ) && value.vt == VT_UI1 ) + // Check for sRGB colorspace metadata + bool sRGB = false; + + PROPVARIANT value; + PropVariantInit( &value ); + + if ( memcmp( &containerFormat, &GUID_ContainerFormatPng, sizeof(GUID) ) == 0 ) + { + // Check for sRGB chunk + if ( SUCCEEDED( metareader->GetMetadataByName( L"/sRGB/RenderingIntent", &value ) ) && value.vt == VT_UI1 ) + { + sRGB = true; + } + } + else if ( SUCCEEDED( metareader->GetMetadataByName( L"System.Image.ColorSpace", &value ) ) && value.vt == VT_UI2 && value.uiVal == 1 ) { sRGB = true; } - } - else if ( SUCCEEDED( metareader->GetMetadataByName( L"System.Image.ColorSpace", &value ) ) && value.vt == VT_UI2 && value.uiVal == 1 ) - { - sRGB = true; - } - PropVariantClear( &value ); + PropVariantClear( &value ); - if ( sRGB ) - format = MakeSRGB( format ); + if ( sRGB ) + format = MakeSRGB( format ); + } } } - } - // Verify our target format is supported by the current device - // (handles WDDM 1.0 or WDDM 1.1 device driver cases as well as DirectX 11.0 Runtime without 16bpp format support) - UINT support = 0; - hr = d3dDevice->CheckFormatSupport( format, &support ); - if ( FAILED(hr) || !(support & D3D11_FORMAT_SUPPORT_TEXTURE2D) ) - { - // Fallback to RGBA 32-bit format which is supported by all devices - memcpy( &convertGUID, &GUID_WICPixelFormat32bppRGBA, sizeof(WICPixelFormatGUID) ); - format = DXGI_FORMAT_R8G8B8A8_UNORM; - bpp = 32; - } - - // Allocate temporary memory for image - size_t rowPitch = ( twidth * bpp + 7 ) / 8; - size_t imageSize = rowPitch * theight; - - std::unique_ptr temp( new (std::nothrow) uint8_t[ imageSize ] ); - if (!temp) - return E_OUTOFMEMORY; - - // Load image data - if ( memcmp( &convertGUID, &pixelFormat, sizeof(GUID) ) == 0 - && twidth == width - && theight == height ) - { - // No format conversion or resize needed - hr = frame->CopyPixels( 0, static_cast( rowPitch ), static_cast( imageSize ), temp.get() ); - if ( FAILED(hr) ) - return hr; - } - else if ( twidth != width || theight != height ) - { - // Resize - IWICImagingFactory* pWIC = _GetWIC(); - if ( !pWIC ) - return E_NOINTERFACE; - - ComPtr scaler; - hr = pWIC->CreateBitmapScaler( scaler.GetAddressOf() ); - if ( FAILED(hr) ) - return hr; - - hr = scaler->Initialize( frame, twidth, theight, WICBitmapInterpolationModeFant ); - if ( FAILED(hr) ) - return hr; - - WICPixelFormatGUID pfScaler; - hr = scaler->GetPixelFormat( &pfScaler ); - if ( FAILED(hr) ) - return hr; - - if ( memcmp( &convertGUID, &pfScaler, sizeof(GUID) ) == 0 ) + // Verify our target format is supported by the current device + // (handles WDDM 1.0 or WDDM 1.1 device driver cases as well as DirectX 11.0 Runtime without 16bpp format support) + UINT support = 0; + hr = d3dDevice->CheckFormatSupport( format, &support ); + if ( FAILED(hr) || !(support & D3D11_FORMAT_SUPPORT_TEXTURE2D) ) { - // No format conversion needed - hr = scaler->CopyPixels( 0, static_cast( rowPitch ), static_cast( imageSize ), temp.get() ); + // Fallback to RGBA 32-bit format which is supported by all devices + memcpy( &convertGUID, &GUID_WICPixelFormat32bppRGBA, sizeof(WICPixelFormatGUID) ); + format = DXGI_FORMAT_R8G8B8A8_UNORM; + bpp = 32; + } + + // Allocate temporary memory for image + size_t rowPitch = ( twidth * bpp + 7 ) / 8; + size_t imageSize = rowPitch * theight; + + std::unique_ptr temp( new (std::nothrow) uint8_t[ imageSize ] ); + if (!temp) + return E_OUTOFMEMORY; + + // Load image data + if ( memcmp( &convertGUID, &pixelFormat, sizeof(GUID) ) == 0 + && twidth == width + && theight == height ) + { + // No format conversion or resize needed + hr = frame->CopyPixels( 0, static_cast( rowPitch ), static_cast( imageSize ), temp.get() ); if ( FAILED(hr) ) return hr; } + else if ( twidth != width || theight != height ) + { + // Resize + IWICImagingFactory* pWIC = _GetWIC(); + if ( !pWIC ) + return E_NOINTERFACE; + + ComPtr scaler; + hr = pWIC->CreateBitmapScaler( scaler.GetAddressOf() ); + if ( FAILED(hr) ) + return hr; + + hr = scaler->Initialize( frame, twidth, theight, WICBitmapInterpolationModeFant ); + if ( FAILED(hr) ) + return hr; + + WICPixelFormatGUID pfScaler; + hr = scaler->GetPixelFormat( &pfScaler ); + if ( FAILED(hr) ) + return hr; + + if ( memcmp( &convertGUID, &pfScaler, sizeof(GUID) ) == 0 ) + { + // No format conversion needed + hr = scaler->CopyPixels( 0, static_cast( rowPitch ), static_cast( imageSize ), temp.get() ); + if ( FAILED(hr) ) + return hr; + } + else + { + ComPtr FC; + hr = pWIC->CreateFormatConverter( FC.GetAddressOf() ); + if ( FAILED(hr) ) + return hr; + + BOOL canConvert = FALSE; + hr = FC->CanConvert( pfScaler, convertGUID, &canConvert ); + if ( FAILED(hr) || !canConvert ) + { + return E_UNEXPECTED; + } + + hr = FC->Initialize( scaler.Get(), convertGUID, WICBitmapDitherTypeErrorDiffusion, 0, 0, WICBitmapPaletteTypeCustom ); + if ( FAILED(hr) ) + return hr; + + hr = FC->CopyPixels( 0, static_cast( rowPitch ), static_cast( imageSize ), temp.get() ); + if ( FAILED(hr) ) + return hr; + } + } else { + // Format conversion but no resize + IWICImagingFactory* pWIC = _GetWIC(); + if ( !pWIC ) + return E_NOINTERFACE; + ComPtr FC; hr = pWIC->CreateFormatConverter( FC.GetAddressOf() ); if ( FAILED(hr) ) return hr; BOOL canConvert = FALSE; - hr = FC->CanConvert( pfScaler, convertGUID, &canConvert ); + hr = FC->CanConvert( pixelFormat, convertGUID, &canConvert ); if ( FAILED(hr) || !canConvert ) { return E_UNEXPECTED; } - hr = FC->Initialize( scaler.Get(), convertGUID, WICBitmapDitherTypeErrorDiffusion, 0, 0, WICBitmapPaletteTypeCustom ); + hr = FC->Initialize( frame, convertGUID, WICBitmapDitherTypeErrorDiffusion, 0, 0, WICBitmapPaletteTypeCustom ); if ( FAILED(hr) ) return hr; @@ -565,115 +595,88 @@ static HRESULT CreateTextureFromWIC( _In_ ID3D11Device* d3dDevice, if ( FAILED(hr) ) return hr; } - } - else - { - // Format conversion but no resize - IWICImagingFactory* pWIC = _GetWIC(); - if ( !pWIC ) - return E_NOINTERFACE; - ComPtr FC; - hr = pWIC->CreateFormatConverter( FC.GetAddressOf() ); - if ( FAILED(hr) ) - return hr; - - BOOL canConvert = FALSE; - hr = FC->CanConvert( pixelFormat, convertGUID, &canConvert ); - if ( FAILED(hr) || !canConvert ) + // See if format is supported for auto-gen mipmaps (varies by feature level) + bool autogen = false; + if ( d3dContext != 0 && textureView != 0 ) // Must have context and shader-view to auto generate mipmaps { - return E_UNEXPECTED; - } - - hr = FC->Initialize( frame, convertGUID, WICBitmapDitherTypeErrorDiffusion, 0, 0, WICBitmapPaletteTypeCustom ); - if ( FAILED(hr) ) - return hr; - - hr = FC->CopyPixels( 0, static_cast( rowPitch ), static_cast( imageSize ), temp.get() ); - if ( FAILED(hr) ) - return hr; - } - - // See if format is supported for auto-gen mipmaps (varies by feature level) - bool autogen = false; - if ( d3dContext != 0 && textureView != 0 ) // Must have context and shader-view to auto generate mipmaps - { - UINT fmtSupport = 0; - hr = d3dDevice->CheckFormatSupport( format, &fmtSupport ); - if ( SUCCEEDED(hr) && ( fmtSupport & D3D11_FORMAT_SUPPORT_MIP_AUTOGEN ) ) - { - autogen = true; - } - } - - // Create texture - D3D11_TEXTURE2D_DESC desc; - desc.Width = twidth; - desc.Height = theight; - desc.MipLevels = (autogen) ? 0 : 1; - desc.ArraySize = 1; - desc.Format = format; - desc.SampleDesc.Count = 1; - desc.SampleDesc.Quality = 0; - desc.Usage = usage; - desc.CPUAccessFlags = cpuAccessFlags; - - if ( autogen ) - { - desc.BindFlags = bindFlags | D3D11_BIND_RENDER_TARGET; - desc.MiscFlags = miscFlags | D3D11_RESOURCE_MISC_GENERATE_MIPS; - } - else - { - desc.BindFlags = bindFlags; - desc.MiscFlags = miscFlags; - } - - D3D11_SUBRESOURCE_DATA initData; - initData.pSysMem = temp.get(); - initData.SysMemPitch = static_cast( rowPitch ); - initData.SysMemSlicePitch = static_cast( imageSize ); - - ID3D11Texture2D* tex = nullptr; - hr = d3dDevice->CreateTexture2D( &desc, (autogen) ? nullptr : &initData, &tex ); - if ( SUCCEEDED(hr) && tex != 0 ) - { - if (textureView != 0) - { - D3D11_SHADER_RESOURCE_VIEW_DESC SRVDesc = {}; - SRVDesc.Format = desc.Format; - - SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; - SRVDesc.Texture2D.MipLevels = (autogen) ? -1 : 1; - - hr = d3dDevice->CreateShaderResourceView( tex, &SRVDesc, textureView ); - if ( FAILED(hr) ) + UINT fmtSupport = 0; + hr = d3dDevice->CheckFormatSupport( format, &fmtSupport ); + if ( SUCCEEDED(hr) && ( fmtSupport & D3D11_FORMAT_SUPPORT_MIP_AUTOGEN ) ) { - tex->Release(); - return hr; - } - - if ( autogen ) - { - assert( d3dContext != 0 ); - d3dContext->UpdateSubresource( tex, 0, nullptr, temp.get(), static_cast(rowPitch), static_cast(imageSize) ); - d3dContext->GenerateMips( *textureView ); + autogen = true; } } - if (texture != 0) + // Create texture + D3D11_TEXTURE2D_DESC desc; + desc.Width = twidth; + desc.Height = theight; + desc.MipLevels = (autogen) ? 0 : 1; + desc.ArraySize = 1; + desc.Format = format; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + desc.Usage = usage; + desc.CPUAccessFlags = cpuAccessFlags; + + if ( autogen ) { - *texture = tex; + desc.BindFlags = bindFlags | D3D11_BIND_RENDER_TARGET; + desc.MiscFlags = miscFlags | D3D11_RESOURCE_MISC_GENERATE_MIPS; } else { - SetDebugObjectName(tex, "WICTextureLoader"); - tex->Release(); + desc.BindFlags = bindFlags; + desc.MiscFlags = miscFlags; } - } - return hr; -} + D3D11_SUBRESOURCE_DATA initData; + initData.pSysMem = temp.get(); + initData.SysMemPitch = static_cast( rowPitch ); + initData.SysMemSlicePitch = static_cast( imageSize ); + + ID3D11Texture2D* tex = nullptr; + hr = d3dDevice->CreateTexture2D( &desc, (autogen) ? nullptr : &initData, &tex ); + if ( SUCCEEDED(hr) && tex != 0 ) + { + if (textureView != 0) + { + D3D11_SHADER_RESOURCE_VIEW_DESC SRVDesc = {}; + SRVDesc.Format = desc.Format; + + SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; + SRVDesc.Texture2D.MipLevels = (autogen) ? -1 : 1; + + hr = d3dDevice->CreateShaderResourceView( tex, &SRVDesc, textureView ); + if ( FAILED(hr) ) + { + tex->Release(); + return hr; + } + + if ( autogen ) + { + assert( d3dContext != 0 ); + d3dContext->UpdateSubresource( tex, 0, nullptr, temp.get(), static_cast(rowPitch), static_cast(imageSize) ); + d3dContext->GenerateMips( *textureView ); + } + } + + if (texture != 0) + { + *texture = tex; + } + else + { + SetDebugObjectName(tex, "WICTextureLoader"); + tex->Release(); + } + } + + return hr; + } +} // anonymous namespace //-------------------------------------------------------------------------------------- _Use_decl_annotations_ diff --git a/WICTextureLoader/WICTextureLoader12.cpp b/WICTextureLoader/WICTextureLoader12.cpp new file mode 100644 index 0000000..35f1c5a --- /dev/null +++ b/WICTextureLoader/WICTextureLoader12.cpp @@ -0,0 +1,712 @@ +//-------------------------------------------------------------------------------------- +// File: WICTextureLoader12.cpp +// +// Function for loading a WIC image and creating a Direct3D 12 runtime texture for it +// (auto-generating mipmaps if possible) +// +// Note: Assumes application has already called CoInitializeEx +// +// Note these functions are useful for images created as simple 2D textures. For +// more complex resources, DDSTextureLoader is an excellent light-weight runtime loader. +// For a full-featured DDS file reader, writer, and texture processing pipeline see +// the 'Texconv' sample and the 'DirectXTex' library. +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkId=248926 +// http://go.microsoft.com/fwlink/?LinkID=615561 +//-------------------------------------------------------------------------------------- + +// We could load multi-frame images (TIFF/GIF) into a texture array. +// For now, we just load the first frame (note: DirectXTex supports multi-frame images) + +#include "WICTextureLoader12.h" + +#include +#include + +#include + +#include + +#include + +using namespace DirectX; +using Microsoft::WRL::ComPtr; + +namespace +{ + //------------------------------------------------------------------------------------- + // WIC Pixel Format Translation Data + //------------------------------------------------------------------------------------- + struct WICTranslate + { + GUID wic; + DXGI_FORMAT format; + }; + + WICTranslate g_WICFormats[] = + { + { GUID_WICPixelFormat128bppRGBAFloat, DXGI_FORMAT_R32G32B32A32_FLOAT }, + + { GUID_WICPixelFormat64bppRGBAHalf, DXGI_FORMAT_R16G16B16A16_FLOAT }, + { GUID_WICPixelFormat64bppRGBA, DXGI_FORMAT_R16G16B16A16_UNORM }, + + { GUID_WICPixelFormat32bppRGBA, DXGI_FORMAT_R8G8B8A8_UNORM }, + { GUID_WICPixelFormat32bppBGRA, DXGI_FORMAT_B8G8R8A8_UNORM }, + { GUID_WICPixelFormat32bppBGR, DXGI_FORMAT_B8G8R8X8_UNORM }, + + { GUID_WICPixelFormat32bppRGBA1010102XR, DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM }, + { GUID_WICPixelFormat32bppRGBA1010102, DXGI_FORMAT_R10G10B10A2_UNORM }, + + { GUID_WICPixelFormat16bppBGRA5551, DXGI_FORMAT_B5G5R5A1_UNORM }, + { GUID_WICPixelFormat16bppBGR565, DXGI_FORMAT_B5G6R5_UNORM }, + + { GUID_WICPixelFormat32bppGrayFloat, DXGI_FORMAT_R32_FLOAT }, + { GUID_WICPixelFormat16bppGrayHalf, DXGI_FORMAT_R16_FLOAT }, + { GUID_WICPixelFormat16bppGray, DXGI_FORMAT_R16_UNORM }, + { GUID_WICPixelFormat8bppGray, DXGI_FORMAT_R8_UNORM }, + + { GUID_WICPixelFormat8bppAlpha, DXGI_FORMAT_A8_UNORM }, + + { GUID_WICPixelFormat96bppRGBFloat, DXGI_FORMAT_R32G32B32_FLOAT }, + }; + + //------------------------------------------------------------------------------------- + // WIC Pixel Format nearest conversion table + //------------------------------------------------------------------------------------- + + struct WICConvert + { + GUID source; + GUID target; + }; + + WICConvert g_WICConvert[] = + { + // Note target GUID in this conversion table must be one of those directly supported formats (above). + + { GUID_WICPixelFormatBlackWhite, GUID_WICPixelFormat8bppGray }, // DXGI_FORMAT_R8_UNORM + + { GUID_WICPixelFormat1bppIndexed, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM + { GUID_WICPixelFormat2bppIndexed, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM + { GUID_WICPixelFormat4bppIndexed, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM + { GUID_WICPixelFormat8bppIndexed, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM + + { GUID_WICPixelFormat2bppGray, GUID_WICPixelFormat8bppGray }, // DXGI_FORMAT_R8_UNORM + { GUID_WICPixelFormat4bppGray, GUID_WICPixelFormat8bppGray }, // DXGI_FORMAT_R8_UNORM + + { GUID_WICPixelFormat16bppGrayFixedPoint, GUID_WICPixelFormat16bppGrayHalf }, // DXGI_FORMAT_R16_FLOAT + { GUID_WICPixelFormat32bppGrayFixedPoint, GUID_WICPixelFormat32bppGrayFloat }, // DXGI_FORMAT_R32_FLOAT + + { GUID_WICPixelFormat16bppBGR555, GUID_WICPixelFormat16bppBGRA5551 }, // DXGI_FORMAT_B5G5R5A1_UNORM + + { GUID_WICPixelFormat32bppBGR101010, GUID_WICPixelFormat32bppRGBA1010102 }, // DXGI_FORMAT_R10G10B10A2_UNORM + + { GUID_WICPixelFormat24bppBGR, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM + { GUID_WICPixelFormat24bppRGB, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM + { GUID_WICPixelFormat32bppPBGRA, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM + { GUID_WICPixelFormat32bppPRGBA, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM + + { GUID_WICPixelFormat48bppRGB, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM + { GUID_WICPixelFormat48bppBGR, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM + { GUID_WICPixelFormat64bppBGRA, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM + { GUID_WICPixelFormat64bppPRGBA, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM + { GUID_WICPixelFormat64bppPBGRA, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM + + { GUID_WICPixelFormat48bppRGBFixedPoint, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT + { GUID_WICPixelFormat48bppBGRFixedPoint, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT + { GUID_WICPixelFormat64bppRGBAFixedPoint, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT + { GUID_WICPixelFormat64bppBGRAFixedPoint, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT + { GUID_WICPixelFormat64bppRGBFixedPoint, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT + { GUID_WICPixelFormat64bppRGBHalf, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT + { GUID_WICPixelFormat48bppRGBHalf, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT + + { GUID_WICPixelFormat128bppPRGBAFloat, GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT + { GUID_WICPixelFormat128bppRGBFloat, GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT + { GUID_WICPixelFormat128bppRGBAFixedPoint, GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT + { GUID_WICPixelFormat128bppRGBFixedPoint, GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT + { GUID_WICPixelFormat32bppRGBE, GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT + + { GUID_WICPixelFormat32bppCMYK, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM + { GUID_WICPixelFormat64bppCMYK, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM + { GUID_WICPixelFormat40bppCMYKAlpha, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM + { GUID_WICPixelFormat80bppCMYKAlpha, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM + + { GUID_WICPixelFormat32bppRGB, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM + { GUID_WICPixelFormat64bppRGB, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM + { GUID_WICPixelFormat64bppPRGBAHalf, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT + + { GUID_WICPixelFormat96bppRGBFixedPoint, GUID_WICPixelFormat96bppRGBFloat }, // DXGI_FORMAT_R32G32B32_FLOAT + + // We don't support n-channel formats + }; + + IWICImagingFactory2* _GetWIC() + { + static IWICImagingFactory2* s_Factory = nullptr; + + if (s_Factory) + return s_Factory; + + HRESULT hr = CoCreateInstance( + CLSID_WICImagingFactory2, + nullptr, + CLSCTX_INPROC_SERVER, + IID_PPV_ARGS(&s_Factory)); + if (FAILED(hr)) + { + s_Factory = nullptr; + return nullptr; + } + return s_Factory; + } + + //--------------------------------------------------------------------------------- + template + inline void SetDebugObjectName(_In_ ID3D12DeviceChild* resource, _In_z_ const wchar_t(&name)[TNameLength]) + { + #if !defined(NO_D3D12_DEBUG_NAME) && ( defined(_DEBUG) || defined(PROFILE) ) + resource->SetName(name); + #else + UNREFERENCED_PARAMETER(resource); + UNREFERENCED_PARAMETER(name); + #endif + } + + inline uint32_t CountMips(uint32_t width, uint32_t height) + { + if (width == 0 || height == 0) + return 0; + + uint32_t count = 1; + while (width > 1 || height > 1) + { + width >>= 1; + height >>= 1; + count++; + } + return count; + } + + //-------------------------------------------------------------------------------------- + DXGI_FORMAT MakeSRGB(_In_ DXGI_FORMAT format) + { + switch (format) + { + case DXGI_FORMAT_R8G8B8A8_UNORM: + return DXGI_FORMAT_R8G8B8A8_UNORM_SRGB; + + case DXGI_FORMAT_BC1_UNORM: + return DXGI_FORMAT_BC1_UNORM_SRGB; + + case DXGI_FORMAT_BC2_UNORM: + return DXGI_FORMAT_BC2_UNORM_SRGB; + + case DXGI_FORMAT_BC3_UNORM: + return DXGI_FORMAT_BC3_UNORM_SRGB; + + case DXGI_FORMAT_B8G8R8A8_UNORM: + return DXGI_FORMAT_B8G8R8A8_UNORM_SRGB; + + case DXGI_FORMAT_B8G8R8X8_UNORM: + return DXGI_FORMAT_B8G8R8X8_UNORM_SRGB; + + case DXGI_FORMAT_BC7_UNORM: + return DXGI_FORMAT_BC7_UNORM_SRGB; + + default: + return format; + } + } + + //--------------------------------------------------------------------------------- + DXGI_FORMAT _WICToDXGI(const GUID& guid) + { + for (size_t i = 0; i < _countof(g_WICFormats); ++i) + { + if (memcmp(&g_WICFormats[i].wic, &guid, sizeof(GUID)) == 0) + return g_WICFormats[i].format; + } + + return DXGI_FORMAT_UNKNOWN; + } + + //--------------------------------------------------------------------------------- + size_t _WICBitsPerPixel(REFGUID targetGuid) + { + auto pWIC = _GetWIC(); + if (!pWIC) + return 0; + + ComPtr cinfo; + if (FAILED(pWIC->CreateComponentInfo(targetGuid, cinfo.GetAddressOf()))) + return 0; + + WICComponentType type; + if (FAILED(cinfo->GetComponentType(&type))) + return 0; + + if (type != WICPixelFormat) + return 0; + + ComPtr pfinfo; + if (FAILED(cinfo.As(&pfinfo))) + return 0; + + UINT bpp; + if (FAILED(pfinfo->GetBitsPerPixel(&bpp))) + return 0; + + return bpp; + } + + //--------------------------------------------------------------------------------- + HRESULT CreateTextureFromWIC(_In_ ID3D12Device* d3dDevice, + _In_ IWICBitmapFrameDecode *frame, + size_t maxsize, + D3D12_RESOURCE_FLAGS flags, + bool forceSRGB, + bool reserveFullMipChain, + _Outptr_ ID3D12Resource** texture, + std::unique_ptr& decodedData, + D3D12_SUBRESOURCE_DATA& subresource) + { + UINT width, height; + HRESULT hr = frame->GetSize(&width, &height); + if (FAILED(hr)) + return hr; + + assert(width > 0 && height > 0); + + if (!maxsize) + { + maxsize = D3D12_REQ_TEXTURE2D_U_OR_V_DIMENSION; + } + + assert(maxsize > 0); + + UINT twidth, theight; + if (width > maxsize || height > maxsize) + { + float ar = static_cast(height) / static_cast(width); + if (width > height) + { + twidth = static_cast(maxsize); + theight = static_cast(static_cast(maxsize) * ar); + } + else + { + theight = static_cast(maxsize); + twidth = static_cast(static_cast(maxsize) / ar); + } + assert(twidth <= maxsize && theight <= maxsize); + } + else + { + twidth = width; + theight = height; + } + + // Determine format + WICPixelFormatGUID pixelFormat; + hr = frame->GetPixelFormat(&pixelFormat); + if (FAILED(hr)) + return hr; + + WICPixelFormatGUID convertGUID; + memcpy(&convertGUID, &pixelFormat, sizeof(WICPixelFormatGUID)); + + size_t bpp = 0; + + DXGI_FORMAT format = _WICToDXGI(pixelFormat); + if (format == DXGI_FORMAT_UNKNOWN) + { + for (size_t i = 0; i < _countof(g_WICConvert); ++i) + { + if (memcmp(&g_WICConvert[i].source, &pixelFormat, sizeof(WICPixelFormatGUID)) == 0) + { + memcpy(&convertGUID, &g_WICConvert[i].target, sizeof(WICPixelFormatGUID)); + + format = _WICToDXGI(g_WICConvert[i].target); + assert(format != DXGI_FORMAT_UNKNOWN); + bpp = _WICBitsPerPixel(convertGUID); + break; + } + } + + if (format == DXGI_FORMAT_UNKNOWN) + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + else + { + bpp = _WICBitsPerPixel(pixelFormat); + } + + if (!bpp) + return E_FAIL; + + // Handle sRGB formats + if (forceSRGB) + { + format = MakeSRGB(format); + } + else + { + ComPtr metareader; + if (SUCCEEDED(frame->GetMetadataQueryReader(metareader.GetAddressOf()))) + { + GUID containerFormat; + if (SUCCEEDED(metareader->GetContainerFormat(&containerFormat))) + { + // Check for sRGB colorspace metadata + bool sRGB = false; + + PROPVARIANT value; + PropVariantInit(&value); + + if (memcmp(&containerFormat, &GUID_ContainerFormatPng, sizeof(GUID)) == 0) + { + // Check for sRGB chunk + if (SUCCEEDED(metareader->GetMetadataByName(L"/sRGB/RenderingIntent", &value)) && value.vt == VT_UI1) + { + sRGB = true; + } + } + else if (SUCCEEDED(metareader->GetMetadataByName(L"System.Image.ColorSpace", &value)) && value.vt == VT_UI2 && value.uiVal == 1) + { + sRGB = true; + } + + PropVariantClear(&value); + + if (sRGB) + format = MakeSRGB(format); + } + } + } + + // Allocate memory for decoded image + size_t rowPitch = (twidth * bpp + 7) / 8; + size_t imageSize = rowPitch * theight; + + decodedData.reset(new (std::nothrow) uint8_t[imageSize]); + if (!decodedData) + return E_OUTOFMEMORY; + + // Load image data + if (memcmp(&convertGUID, &pixelFormat, sizeof(GUID)) == 0 + && twidth == width + && theight == height) + { + // No format conversion or resize needed + hr = frame->CopyPixels(0, static_cast(rowPitch), static_cast(imageSize), decodedData.get()); + if (FAILED(hr)) + return hr; + } + else if (twidth != width || theight != height) + { + // Resize + auto pWIC = _GetWIC(); + if (!pWIC) + return E_NOINTERFACE; + + ComPtr scaler; + hr = pWIC->CreateBitmapScaler(scaler.GetAddressOf()); + if (FAILED(hr)) + return hr; + + hr = scaler->Initialize(frame, twidth, theight, WICBitmapInterpolationModeFant); + if (FAILED(hr)) + return hr; + + WICPixelFormatGUID pfScaler; + hr = scaler->GetPixelFormat(&pfScaler); + if (FAILED(hr)) + return hr; + + if (memcmp(&convertGUID, &pfScaler, sizeof(GUID)) == 0) + { + // No format conversion needed + hr = scaler->CopyPixels(0, static_cast(rowPitch), static_cast(imageSize), decodedData.get()); + if (FAILED(hr)) + return hr; + } + else + { + ComPtr FC; + hr = pWIC->CreateFormatConverter(FC.GetAddressOf()); + if (FAILED(hr)) + return hr; + + BOOL canConvert = FALSE; + hr = FC->CanConvert(pfScaler, convertGUID, &canConvert); + if (FAILED(hr) || !canConvert) + { + return E_UNEXPECTED; + } + + hr = FC->Initialize(scaler.Get(), convertGUID, WICBitmapDitherTypeErrorDiffusion, 0, 0, WICBitmapPaletteTypeCustom); + if (FAILED(hr)) + return hr; + + hr = FC->CopyPixels(0, static_cast(rowPitch), static_cast(imageSize), decodedData.get()); + if (FAILED(hr)) + return hr; + } + } + else + { + // Format conversion but no resize + auto pWIC = _GetWIC(); + if (!pWIC) + return E_NOINTERFACE; + + ComPtr FC; + hr = pWIC->CreateFormatConverter(FC.GetAddressOf()); + if (FAILED(hr)) + return hr; + + BOOL canConvert = FALSE; + hr = FC->CanConvert(pixelFormat, convertGUID, &canConvert); + if (FAILED(hr) || !canConvert) + { + return E_UNEXPECTED; + } + + hr = FC->Initialize(frame, convertGUID, WICBitmapDitherTypeErrorDiffusion, 0, 0, WICBitmapPaletteTypeCustom); + if (FAILED(hr)) + return hr; + + hr = FC->CopyPixels(0, static_cast(rowPitch), static_cast(imageSize), decodedData.get()); + if (FAILED(hr)) + return hr; + } + + // Count the number of mips + uint32_t mipCount = (reserveFullMipChain) ? CountMips(twidth, theight) : 1; + + // Create texture + D3D12_RESOURCE_DESC desc = {}; + desc.Width = twidth; + desc.Height = theight; + desc.MipLevels = (uint16_t)mipCount; + desc.DepthOrArraySize = 1; + desc.Format = format; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + desc.Flags = flags; + desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; + + CD3DX12_HEAP_PROPERTIES defaultHeapProperties(D3D12_HEAP_TYPE_DEFAULT); + + ID3D12Resource* tex = nullptr; + hr = d3dDevice->CreateCommittedResource( + &defaultHeapProperties, + D3D12_HEAP_FLAG_NONE, + &desc, + D3D12_RESOURCE_STATE_COPY_DEST, + nullptr, + IID_PPV_ARGS(&tex)); + + if (FAILED(hr)) + { + return hr; + } + + _Analysis_assume_(tex != 0); + + subresource.pData = decodedData.get(); + subresource.RowPitch = rowPitch; + subresource.SlicePitch = imageSize; + + *texture = tex; + return hr; + } +} // anonymous namespace + + +//-------------------------------------------------------------------------------------- +_Use_decl_annotations_ +HRESULT DirectX::LoadWICTextureFromMemory( + ID3D12Device* d3dDevice, + const uint8_t* wicData, + size_t wicDataSize, + ID3D12Resource** texture, + std::unique_ptr& decodedData, + D3D12_SUBRESOURCE_DATA& subresource, + size_t maxsize) +{ + return LoadWICTextureFromMemoryEx( + d3dDevice, + wicData, + wicDataSize, + maxsize, + D3D12_RESOURCE_FLAG_NONE, + false, + false, + texture, + decodedData, + subresource); +} + + +//-------------------------------------------------------------------------------------- +_Use_decl_annotations_ +HRESULT DirectX::LoadWICTextureFromMemoryEx( + ID3D12Device* d3dDevice, + const uint8_t* wicData, + size_t wicDataSize, + size_t maxsize, + D3D12_RESOURCE_FLAGS flags, + bool forceSRGB, + bool reserveFullMipChain, + ID3D12Resource** texture, + std::unique_ptr& decodedData, + D3D12_SUBRESOURCE_DATA& subresource) +{ + if ( texture ) + { + *texture = nullptr; + } + + if (!d3dDevice || !wicData || !texture) + return E_INVALIDARG; + + if ( !wicDataSize ) + return E_FAIL; + +#ifdef _M_AMD64 + if ( wicDataSize > 0xFFFFFFFF ) + return HRESULT_FROM_WIN32( ERROR_FILE_TOO_LARGE ); +#endif + + auto pWIC = _GetWIC(); + if ( !pWIC ) + return E_NOINTERFACE; + + // Create input stream for memory + ComPtr stream; + HRESULT hr = pWIC->CreateStream( stream.GetAddressOf() ); + if ( FAILED(hr) ) + return hr; + + hr = stream->InitializeFromMemory( const_cast( wicData ), static_cast( wicDataSize ) ); + if ( FAILED(hr) ) + return hr; + + // Initialize WIC + ComPtr decoder; + hr = pWIC->CreateDecoderFromStream( stream.Get(), 0, WICDecodeMetadataCacheOnDemand, decoder.GetAddressOf() ); + if ( FAILED(hr) ) + return hr; + + ComPtr frame; + hr = decoder->GetFrame( 0, frame.GetAddressOf() ); + if ( FAILED(hr) ) + return hr; + + hr = CreateTextureFromWIC( d3dDevice, + frame.Get(), maxsize, + flags, forceSRGB, reserveFullMipChain, + texture, decodedData, subresource); + if ( FAILED(hr)) + return hr; + + _Analysis_assume_(*texture != nullptr); + SetDebugObjectName(*texture, L"WICTextureLoader"); + + return hr; +} + + +//-------------------------------------------------------------------------------------- +_Use_decl_annotations_ +HRESULT DirectX::LoadWICTextureFromFile( + ID3D12Device* d3dDevice, + const wchar_t* fileName, + ID3D12Resource** texture, + std::unique_ptr& wicData, + D3D12_SUBRESOURCE_DATA& subresource, + size_t maxsize) +{ + return LoadWICTextureFromFileEx( + d3dDevice, + fileName, + maxsize, + D3D12_RESOURCE_FLAG_NONE, + false, + false, + texture, + wicData, + subresource); +} + + +//-------------------------------------------------------------------------------------- +_Use_decl_annotations_ +HRESULT DirectX::LoadWICTextureFromFileEx( + ID3D12Device* d3dDevice, + const wchar_t* fileName, + size_t maxsize, + D3D12_RESOURCE_FLAGS flags, + bool forceSRGB, + bool reserveFullMipChain, + ID3D12Resource** texture, + std::unique_ptr& decodedData, + D3D12_SUBRESOURCE_DATA& subresource) +{ + if ( texture ) + { + *texture = nullptr; + } + + if (!d3dDevice || !fileName || !texture ) + return E_INVALIDARG; + + auto pWIC = _GetWIC(); + if ( !pWIC ) + return E_NOINTERFACE; + + // Initialize WIC + ComPtr decoder; + HRESULT hr = pWIC->CreateDecoderFromFilename( fileName, 0, GENERIC_READ, WICDecodeMetadataCacheOnDemand, decoder.GetAddressOf() ); + if ( FAILED(hr) ) + return hr; + + ComPtr frame; + hr = decoder->GetFrame( 0, frame.GetAddressOf() ); + if ( FAILED(hr) ) + return hr; + + hr = CreateTextureFromWIC( d3dDevice, frame.Get(), maxsize, + flags, forceSRGB, reserveFullMipChain, + texture, decodedData, subresource ); + +#if !defined(NO_D3D12_DEBUG_NAME) && ( defined(_DEBUG) || defined(PROFILE) ) + if ( SUCCEEDED(hr) ) + { + const wchar_t* pstrName = wcsrchr(fileName, '\\' ); + if (!pstrName) + { + pstrName = fileName; + } + else + { + pstrName++; + } + + if (texture != 0 && *texture != 0) + { + (*texture)->SetName(pstrName); + } + } +#endif + + return hr; +} diff --git a/WICTextureLoader/WICTextureLoader12.h b/WICTextureLoader/WICTextureLoader12.h new file mode 100644 index 0000000..ef97088 --- /dev/null +++ b/WICTextureLoader/WICTextureLoader12.h @@ -0,0 +1,75 @@ +//-------------------------------------------------------------------------------------- +// File: WICTextureLoader12.h +// +// Function for loading a WIC image and creating a Direct3D 12 runtime texture for it +// (auto-generating mipmaps if possible) +// +// Note: Assumes application has already called CoInitializeEx +// +// Note these functions are useful for images created as simple 2D textures. For +// more complex resources, DDSTextureLoader is an excellent light-weight runtime loader. +// For a full-featured DDS file reader, writer, and texture processing pipeline see +// the 'Texconv' sample and the 'DirectXTex' library. +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkId=248926 +// http://go.microsoft.com/fwlink/?LinkID=615561 +//-------------------------------------------------------------------------------------- + +#pragma once + +#include +#include +#include + + +namespace DirectX +{ + // Standard version + HRESULT __cdecl LoadWICTextureFromMemory( + _In_ ID3D12Device* d3dDevice, + _In_reads_bytes_(wicDataSize) const uint8_t* wicData, + size_t wicDataSize, + _Outptr_ ID3D12Resource** texture, + std::unique_ptr& decodedData, + D3D12_SUBRESOURCE_DATA& subresource, + size_t maxsize = 0); + + HRESULT __cdecl LoadWICTextureFromFile( + _In_ ID3D12Device* d3dDevice, + _In_z_ const wchar_t* szFileName, + _Outptr_ ID3D12Resource** texture, + std::unique_ptr& decodedData, + D3D12_SUBRESOURCE_DATA& subresource, + size_t maxsize = 0); + + // Extended version + HRESULT __cdecl LoadWICTextureFromMemoryEx( + _In_ ID3D12Device* d3dDevice, + _In_reads_bytes_(wicDataSize) const uint8_t* wicData, + size_t wicDataSize, + size_t maxsize, + D3D12_RESOURCE_FLAGS flags, + bool forceSRGB, + bool reserveFullMipChain, + _Outptr_ ID3D12Resource** texture, + std::unique_ptr& decodedData, + D3D12_SUBRESOURCE_DATA& subresource); + + HRESULT __cdecl LoadWICTextureFromFileEx( + _In_ ID3D12Device* d3dDevice, + _In_z_ const wchar_t* szFileName, + size_t maxsize, + D3D12_RESOURCE_FLAGS flags, + bool forceSRGB, + bool reserveFullMipChain, + _Outptr_ ID3D12Resource** texture, + std::unique_ptr& decodedData, + D3D12_SUBRESOURCE_DATA& subresource); +} \ No newline at end of file