Danbias/Code/OysterGraphics/FileLoader/ModelLoader.cpp

772 lines
23 KiB
C++

#include "GeneralLoader.h"
#include "..\Core\Dx11Includes.h"
#include "..\Core\Core.h"
#include "ObjReader.h"
HRESULT CreateWICTextureFromFileEx( ID3D11Device* d3dDevice,
ID3D11DeviceContext* d3dContext,
const wchar_t* fileName,
size_t maxsize,
D3D11_USAGE usage,
unsigned int bindFlags,
unsigned int cpuAccessFlags,
unsigned int miscFlags,
bool forceSRGB,
ID3D11Resource** texture,
ID3D11ShaderResourceView** textureView );
void* Oyster::Graphics::Loading::LoadTexture(const wchar_t filename[])
{
ID3D11ShaderResourceView* srv = NULL;
HRESULT hr = CreateWICTextureFromFileEx(Core::device,Core::deviceContext,filename,0,D3D11_USAGE_DEFAULT,D3D11_BIND_SHADER_RESOURCE,0,0,false,NULL,&srv);
if(hr!=S_OK)
{
return NULL;
}
else
{
return srv;
}
}
void Oyster::Graphics::Loading::UnloadTexture(void* data)
{
ID3D11ShaderResourceView* srv = (ID3D11ShaderResourceView*)data;
SAFE_RELEASE(srv);
}
void* Oyster::Graphics::Loading::LoadOBJ(const wchar_t filename[])
{
FileLoaders::ObjReader obj;
obj.LoadFile(filename);
Model::ModelInfo* info = new Model::ModelInfo();
Oyster::FileLoaders::ObjReader::Vertex* vdata;
int count;
obj.GetVertexData(&vdata, count);
info->Vertices = new Core::Buffer();
Core::Buffer::BUFFER_INIT_DESC desc;
desc.ElementSize = sizeof(FileLoaders::ObjReader::Vertex);
desc.NumElements = count;
desc.InitData = vdata;
desc.Type = Core::Buffer::VERTEX_BUFFER;
desc.Usage = Core::Buffer::BUFFER_USAGE_IMMUTABLE;
info->VertexCount = count;
info->Vertices->Init(desc);
info->Indexed = false;
void* texture = Core::loader.LoadResource((std::wstring(filename)+ L".png").c_str(),Graphics::Loading::LoadTexture, Graphics::Loading::UnloadTexture);
info->Material.push_back((ID3D11ShaderResourceView*)texture);
return info;
}
void Oyster::Graphics::Loading::UnloadOBJ(void* data)
{
Model::ModelInfo* info = (Model::ModelInfo*) data;
SAFE_DELETE(info->Vertices);
if(info->Indexed)
{
SAFE_DELETE(info->Indecies);
}
for(UINT i =0;i<info->Material.size();++i)
{
Core::loader.ReleaseResource(info->Material[i]);
}
delete info;
}
#include <wrl.h>
#include <memory>
#include <cassert>
#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) || defined(_WIN7_PLATFORM_UPDATE)
#include <d2d1.h>
#endif
#pragma warning(push)
#pragma warning(disable : 4005)
#include <wincodec.h>
#pragma warning(pop)
template<class T> class ScopedObject : public Microsoft::WRL::ComPtr<T> {};
//-------------------------------------------------------------------------------------
// WIC Pixel Format Translation Data
//-------------------------------------------------------------------------------------
struct WICTranslate
{
GUID wic;
DXGI_FORMAT format;
};
static 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 }, // 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 },
#ifdef DXGI_1_2_FORMATS
{ GUID_WICPixelFormat16bppBGRA5551, DXGI_FORMAT_B5G5R5A1_UNORM },
{ GUID_WICPixelFormat16bppBGR565, DXGI_FORMAT_B5G6R5_UNORM },
#endif // DXGI_1_2_FORMATS
{ 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 },
};
//-------------------------------------------------------------------------------------
// WIC Pixel Format nearest conversion table
//-------------------------------------------------------------------------------------
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).
{ 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
#ifdef DXGI_1_2_FORMATS
{ GUID_WICPixelFormat16bppBGR555, GUID_WICPixelFormat16bppBGRA5551 }, // DXGI_FORMAT_B5G5R5A1_UNORM
#else
{ GUID_WICPixelFormat16bppBGR555, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
{ GUID_WICPixelFormat16bppBGRA5551, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
{ GUID_WICPixelFormat16bppBGR565, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
#endif // DXGI_1_2_FORMATS
{ 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
#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
#endif
// We don't support n-channel formats
};
static bool g_WIC2 = false;
//--------------------------------------------------------------------------------------
bool _IsWIC2()
{
return g_WIC2;
}
IWICImagingFactory* _GetWIC()
{
static IWICImagingFactory* s_Factory = nullptr;
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
);
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,
__uuidof(IWICImagingFactory),
(LPVOID*)&s_Factory
);
if ( FAILED(hr) )
{
s_Factory = nullptr;
return nullptr;
}
}
#else
HRESULT hr = CoCreateInstance(
CLSID_WICImagingFactory,
nullptr,
CLSCTX_INPROC_SERVER,
__uuidof(IWICImagingFactory),
(LPVOID*)&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;
}
#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;
}
#endif
return DXGI_FORMAT_UNKNOWN;
}
//---------------------------------------------------------------------------------
static size_t _WICBitsPerPixel( REFGUID targetGuid )
{
IWICImagingFactory* pWIC = _GetWIC();
if ( !pWIC )
return 0;
ScopedObject<IWICComponentInfo> cinfo;
if ( FAILED( pWIC->CreateComponentInfo( targetGuid, &cinfo ) ) )
return 0;
WICComponentType type;
if ( FAILED( cinfo->GetComponentType( &type ) ) )
return 0;
if ( type != WICPixelFormat )
return 0;
Microsoft::WRL::ComPtr<IWICPixelFormatInfo> pfinfo;
if ( FAILED( cinfo.As( &pfinfo ) ) )
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;
}
}
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 )
{
// 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() )
{
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<float>(height) / static_cast<float>(width);
if ( width > height )
{
twidth = static_cast<UINT>( maxsize );
theight = static_cast<UINT>( static_cast<float>(maxsize) * ar );
}
else
{
theight = static_cast<UINT>( maxsize );
twidth = static_cast<UINT>( static_cast<float>(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 )
{
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) );
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 ) )
{
// 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;
// Handle sRGB formats
if ( forceSRGB )
{
format = MakeSRGB( format );
}
else
{
ScopedObject<IWICMetadataQueryReader> metareader;
if ( SUCCEEDED( frame->GetMetadataQueryReader( &metareader ) ) )
{
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 );
}
}
}
// 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<uint8_t[]> 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<UINT>( rowPitch ), static_cast<UINT>( imageSize ), temp.get() );
if ( FAILED(hr) )
return hr;
}
else if ( twidth != width || theight != height )
{
// Resize
IWICImagingFactory* pWIC = _GetWIC();
if ( !pWIC )
return E_NOINTERFACE;
ScopedObject<IWICBitmapScaler> scaler;
hr = pWIC->CreateBitmapScaler( &scaler );
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<UINT>( rowPitch ), static_cast<UINT>( imageSize ), temp.get() );
if ( FAILED(hr) )
return hr;
}
else
{
ScopedObject<IWICFormatConverter> FC;
hr = pWIC->CreateFormatConverter( &FC );
if ( FAILED(hr) )
return hr;
hr = FC->Initialize( scaler.Get(), convertGUID, WICBitmapDitherTypeErrorDiffusion, 0, 0, WICBitmapPaletteTypeCustom );
if ( FAILED(hr) )
return hr;
hr = FC->CopyPixels( 0, static_cast<UINT>( rowPitch ), static_cast<UINT>( imageSize ), temp.get() );
if ( FAILED(hr) )
return hr;
}
}
else
{
// Format conversion but no resize
IWICImagingFactory* pWIC = _GetWIC();
if ( !pWIC )
return E_NOINTERFACE;
ScopedObject<IWICFormatConverter> FC;
hr = pWIC->CreateFormatConverter( &FC );
if ( FAILED(hr) )
return hr;
hr = FC->Initialize( frame, convertGUID, WICBitmapDitherTypeErrorDiffusion, 0, 0, WICBitmapPaletteTypeCustom );
if ( FAILED(hr) )
return hr;
hr = FC->CopyPixels( 0, static_cast<UINT>( rowPitch ), static_cast<UINT>( 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;
autogen = false;
}
}
// 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<UINT>( rowPitch );
initData.SysMemSlicePitch = static_cast<UINT>( imageSize );
ID3D11Texture2D* tex = nullptr;
//Error with miscFlags Generate Mips
hr = d3dDevice->CreateTexture2D( &desc, (autogen) ? nullptr : &initData, &tex );
/// Replace To get Texture Data
if ( SUCCEEDED(hr) && tex != 0 )
{
if (textureView != 0)
{
D3D11_SHADER_RESOURCE_VIEW_DESC SRVDesc;
memset( &SRVDesc, 0, sizeof( SRVDesc ) );
SRVDesc.Format = desc.Format;
SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
SRVDesc.Texture2D.MipLevels = (autogen) ? -1 : 1;
//TODO calc mipmap data
hr = d3dDevice->CreateShaderResourceView( tex, &SRVDesc, textureView );
if ( FAILED(hr) )
{
tex->Release();
return hr;
}
//todo check calc
int TexSize = twidth * theight * (int)bpp;
Oyster::Graphics::Core::UsedMem += TexSize;
if ( autogen )
{
assert( d3dContext != 0 );
d3dContext->UpdateSubresource( tex, 0, nullptr, temp.get(), static_cast<UINT>(rowPitch), static_cast<UINT>(imageSize) );
d3dContext->GenerateMips( *textureView );
}
}
if (texture != 0)
{
*texture = tex;
}
else
{
//SetDebugObjectName(tex, "WICTextureLoader");
tex->Release();
}
}
return hr;
}
HRESULT CreateWICTextureFromFileEx( ID3D11Device* d3dDevice,
ID3D11DeviceContext* d3dContext,
const wchar_t* fileName,
size_t maxsize,
D3D11_USAGE usage,
unsigned int bindFlags,
unsigned int cpuAccessFlags,
unsigned int miscFlags,
bool forceSRGB,
ID3D11Resource** texture,
ID3D11ShaderResourceView** textureView )
{
if ( texture )
{
*texture = nullptr;
}
if ( textureView )
{
*textureView = nullptr;
}
if (!d3dDevice || !fileName || (!texture && !textureView))
return E_INVALIDARG;
IWICImagingFactory* pWIC = _GetWIC();
if ( !pWIC )
return E_NOINTERFACE;
// Initialize WIC
ScopedObject<IWICBitmapDecoder> decoder;
HRESULT hr = pWIC->CreateDecoderFromFilename( fileName, 0, GENERIC_READ, WICDecodeMetadataCacheOnDemand, &decoder );
if ( FAILED(hr) )
return hr;
ScopedObject<IWICBitmapFrameDecode> frame;
hr = decoder->GetFrame( 0, &frame );
if ( FAILED(hr) )
return hr;
hr = CreateTextureFromWIC( d3dDevice, d3dContext, frame.Get(), maxsize,
usage, bindFlags, cpuAccessFlags, miscFlags, forceSRGB,
texture, textureView );
return hr;
}