mirror of
https://github.com/microsoft/DirectXTex.git
synced 2026-02-09 06:16:14 +01:00
April 20, 2012 source
This commit is contained in:
691
WICTextureLoader/WICTextureLoader.cpp
Normal file
691
WICTextureLoader/WICTextureLoader.cpp
Normal file
@@ -0,0 +1,691 @@
|
||||
//--------------------------------------------------------------------------------------
|
||||
// File: WICTextureLoader.cpp
|
||||
//
|
||||
// Function for loading a WIC image and creating a Direct3D 11 runtime texture for it
|
||||
// (auto-generating mipmaps if possible)
|
||||
//
|
||||
// Note: Assumes application has already called CoInitializeEx
|
||||
//
|
||||
// Warning: CreateWICTexture* functions are not thread-safe if given a d3dContext instance for
|
||||
// auto-gen mipmap support.
|
||||
//
|
||||
// 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=248929
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// 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 <dxgiformat.h>
|
||||
#include <assert.h>
|
||||
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4005)
|
||||
#include <wincodec.h>
|
||||
#pragma warning(pop)
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "WICTextureLoader.h"
|
||||
|
||||
#if (_WIN32_WINNT >= 0x0602 /*_WIN32_WINNT_WIN8*/) && !defined(DXGI_1_2_FORMATS)
|
||||
#define DXGI_1_2_FORMATS
|
||||
#endif
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
template<class T> class ScopedObject
|
||||
{
|
||||
public:
|
||||
explicit ScopedObject( T *p = 0 ) : _pointer(p) {}
|
||||
~ScopedObject()
|
||||
{
|
||||
if ( _pointer )
|
||||
{
|
||||
_pointer->Release();
|
||||
_pointer = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool IsNull() const { return (!_pointer); }
|
||||
|
||||
T& operator*() { return *_pointer; }
|
||||
T* operator->() { return _pointer; }
|
||||
T** operator&() { return &_pointer; }
|
||||
|
||||
void Reset(T *p = 0) { if ( _pointer ) { _pointer->Release(); } _pointer = p; }
|
||||
|
||||
T* Get() const { return _pointer; }
|
||||
|
||||
private:
|
||||
ScopedObject(const ScopedObject&);
|
||||
ScopedObject& operator=(const ScopedObject&);
|
||||
|
||||
T* _pointer;
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------------------------
|
||||
// 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 },
|
||||
{ GUID_WICPixelFormat32bppRGBE, DXGI_FORMAT_R9G9B9E5_SHAREDEXP },
|
||||
|
||||
#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 },
|
||||
|
||||
#if (_WIN32_WINNT >= 0x0602 /*_WIN32_WINNT_WIN8*/)
|
||||
{ GUID_WICPixelFormat96bppRGBFloat, DXGI_FORMAT_R32G32B32_FLOAT },
|
||||
#endif
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------------------------
|
||||
// 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_WICPixelFormat96bppRGBFixedPoint, 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_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 >= 0x0602 /*_WIN32_WINNT_WIN8*/)
|
||||
{ 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 IWICImagingFactory* _GetWIC()
|
||||
{
|
||||
static IWICImagingFactory* s_Factory = nullptr;
|
||||
|
||||
if ( s_Factory )
|
||||
return s_Factory;
|
||||
|
||||
HRESULT hr = CoCreateInstance(
|
||||
CLSID_WICImagingFactory,
|
||||
nullptr,
|
||||
CLSCTX_INPROC_SERVER,
|
||||
__uuidof(IWICImagingFactory),
|
||||
(LPVOID*)&s_Factory
|
||||
);
|
||||
|
||||
if ( FAILED(hr) )
|
||||
{
|
||||
s_Factory = nullptr;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
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 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;
|
||||
|
||||
ScopedObject<IWICPixelFormatInfo> pfinfo;
|
||||
if ( FAILED( cinfo->QueryInterface( __uuidof(IWICPixelFormatInfo), reinterpret_cast<void**>( &pfinfo ) ) ) )
|
||||
return 0;
|
||||
|
||||
UINT bpp;
|
||||
if ( FAILED( pfinfo->GetBitsPerPixel( &bpp ) ) )
|
||||
return 0;
|
||||
|
||||
return bpp;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
static HRESULT CreateTextureFromWIC( _In_ ID3D11Device* d3dDevice,
|
||||
_In_opt_ ID3D11DeviceContext* d3dContext,
|
||||
_In_ IWICBitmapFrameDecode *frame,
|
||||
_Out_opt_ ID3D11Resource** texture,
|
||||
_Out_opt_ ID3D11ShaderResourceView** textureView,
|
||||
_In_ size_t maxsize )
|
||||
{
|
||||
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 )
|
||||
{
|
||||
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;
|
||||
|
||||
// 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 uint8_t[ imageSize ] );
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
// 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 = D3D11_USAGE_DEFAULT;
|
||||
desc.BindFlags = (autogen) ? (D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET) : (D3D11_BIND_SHADER_RESOURCE);
|
||||
desc.CPUAccessFlags = 0;
|
||||
desc.MiscFlags = (autogen) ? D3D11_RESOURCE_MISC_GENERATE_MIPS : 0;
|
||||
|
||||
D3D11_SUBRESOURCE_DATA initData;
|
||||
initData.pSysMem = temp.get();
|
||||
initData.SysMemPitch = static_cast<UINT>( rowPitch );
|
||||
initData.SysMemSlicePitch = static_cast<UINT>( 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;
|
||||
memset( &SRVDesc, 0, sizeof( SRVDesc ) );
|
||||
SRVDesc.Format = 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<UINT>(rowPitch), static_cast<UINT>(imageSize) );
|
||||
d3dContext->GenerateMips( *textureView );
|
||||
}
|
||||
}
|
||||
|
||||
if (texture != 0)
|
||||
{
|
||||
*texture = tex;
|
||||
}
|
||||
else
|
||||
{
|
||||
#if defined(DEBUG) || defined(PROFILE)
|
||||
tex->SetPrivateData( WKPDID_D3DDebugObjectName,
|
||||
sizeof("WICTextureLoader")-1,
|
||||
"WICTextureLoader"
|
||||
);
|
||||
#endif
|
||||
tex->Release();
|
||||
}
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
HRESULT CreateWICTextureFromMemory( _In_ ID3D11Device* d3dDevice,
|
||||
_In_opt_ ID3D11DeviceContext* d3dContext,
|
||||
_In_bytecount_(wicDataSize) const uint8_t* wicData,
|
||||
_In_ size_t wicDataSize,
|
||||
_Out_opt_ ID3D11Resource** texture,
|
||||
_Out_opt_ ID3D11ShaderResourceView** textureView,
|
||||
_In_ size_t maxsize
|
||||
)
|
||||
{
|
||||
if (!d3dDevice || !wicData || (!texture && !textureView))
|
||||
{
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
if ( !wicDataSize )
|
||||
{
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
#ifdef _M_AMD64
|
||||
if ( wicDataSize > 0xFFFFFFFF )
|
||||
return HRESULT_FROM_WIN32( ERROR_FILE_TOO_LARGE );
|
||||
#endif
|
||||
|
||||
IWICImagingFactory* pWIC = _GetWIC();
|
||||
if ( !pWIC )
|
||||
return E_NOINTERFACE;
|
||||
|
||||
// Create input stream for memory
|
||||
ScopedObject<IWICStream> stream;
|
||||
HRESULT hr = pWIC->CreateStream( &stream );
|
||||
if ( FAILED(hr) )
|
||||
return hr;
|
||||
|
||||
hr = stream->InitializeFromMemory( const_cast<uint8_t*>( wicData ), static_cast<DWORD>( wicDataSize ) );
|
||||
if ( FAILED(hr) )
|
||||
return hr;
|
||||
|
||||
// Initialize WIC
|
||||
ScopedObject<IWICBitmapDecoder> decoder;
|
||||
hr = pWIC->CreateDecoderFromStream( stream.Get(), 0, 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(), texture, textureView, maxsize );
|
||||
if ( FAILED(hr))
|
||||
return hr;
|
||||
|
||||
#if defined(DEBUG) || defined(PROFILE)
|
||||
if (texture != 0 && *texture != 0)
|
||||
{
|
||||
(*texture)->SetPrivateData( WKPDID_D3DDebugObjectName,
|
||||
sizeof("WICTextureLoader")-1,
|
||||
"WICTextureLoader"
|
||||
);
|
||||
}
|
||||
|
||||
if (textureView != 0 && *textureView != 0)
|
||||
{
|
||||
(*textureView)->SetPrivateData( WKPDID_D3DDebugObjectName,
|
||||
sizeof("WICTextureLoader")-1,
|
||||
"WICTextureLoader"
|
||||
);
|
||||
}
|
||||
#endif
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
HRESULT CreateWICTextureFromFile( _In_ ID3D11Device* d3dDevice,
|
||||
_In_opt_ ID3D11DeviceContext* d3dContext,
|
||||
_In_z_ const wchar_t* fileName,
|
||||
_Out_opt_ ID3D11Resource** texture,
|
||||
_Out_opt_ ID3D11ShaderResourceView** textureView,
|
||||
_In_ size_t maxsize )
|
||||
{
|
||||
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(), texture, textureView, maxsize );
|
||||
if ( FAILED(hr))
|
||||
return hr;
|
||||
|
||||
#if defined(DEBUG) || defined(PROFILE)
|
||||
if (texture != 0 || textureView != 0)
|
||||
{
|
||||
CHAR strFileA[MAX_PATH];
|
||||
WideCharToMultiByte( CP_ACP,
|
||||
WC_NO_BEST_FIT_CHARS,
|
||||
fileName,
|
||||
-1,
|
||||
strFileA,
|
||||
MAX_PATH,
|
||||
nullptr,
|
||||
FALSE
|
||||
);
|
||||
const CHAR* pstrName = strrchr( strFileA, '\\' );
|
||||
if (!pstrName)
|
||||
{
|
||||
pstrName = strFileA;
|
||||
}
|
||||
else
|
||||
{
|
||||
pstrName++;
|
||||
}
|
||||
|
||||
if (texture != 0 && *texture != 0)
|
||||
{
|
||||
(*texture)->SetPrivateData( WKPDID_D3DDebugObjectName,
|
||||
lstrlenA(pstrName),
|
||||
pstrName
|
||||
);
|
||||
}
|
||||
|
||||
if (textureView != 0 && *textureView != 0 )
|
||||
{
|
||||
(*textureView)->SetPrivateData( WKPDID_D3DDebugObjectName,
|
||||
lstrlenA(pstrName),
|
||||
pstrName
|
||||
);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return hr;
|
||||
}
|
||||
54
WICTextureLoader/WICTextureLoader.h
Normal file
54
WICTextureLoader/WICTextureLoader.h
Normal file
@@ -0,0 +1,54 @@
|
||||
//--------------------------------------------------------------------------------------
|
||||
// File: WICTextureLoader.h
|
||||
//
|
||||
// Function for loading a WIC image and creating a Direct3D 11 runtime texture for it
|
||||
// (auto-generating mipmaps if possible)
|
||||
//
|
||||
// Note: Assumes application has already called CoInitializeEx
|
||||
//
|
||||
// Warning: CreateWICTexture* functions are not thread-safe if given a d3dContext instance for
|
||||
// auto-gen mipmap support.
|
||||
//
|
||||
// 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=248929
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <d3d11.h>
|
||||
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4005)
|
||||
#include <stdint.h>
|
||||
#pragma warning(pop)
|
||||
|
||||
HRESULT CreateWICTextureFromMemory( _In_ ID3D11Device* d3dDevice,
|
||||
_In_opt_ ID3D11DeviceContext* d3dContext,
|
||||
_In_bytecount_(wicDataSize) const uint8_t* wicData,
|
||||
_In_ size_t wicDataSize,
|
||||
_Out_opt_ ID3D11Resource** texture,
|
||||
_Out_opt_ ID3D11ShaderResourceView** textureView,
|
||||
_In_ size_t maxsize = 0
|
||||
);
|
||||
|
||||
HRESULT CreateWICTextureFromFile( _In_ ID3D11Device* d3dDevice,
|
||||
_In_opt_ ID3D11DeviceContext* d3dContext,
|
||||
_In_z_ const wchar_t* szFileName,
|
||||
_Out_opt_ ID3D11Resource** texture,
|
||||
_Out_opt_ ID3D11ShaderResourceView** textureView,
|
||||
_In_ size_t maxsize = 0
|
||||
);
|
||||
Reference in New Issue
Block a user