[slimdx] r2187 committed - Added texture loaders for WIC and DDS to replace removed D3DX function...

77 views
Skip to first unread message

sli...@googlecode.com

unread,
Mar 17, 2012, 8:27:44 PM3/17/12
to slimdx...@googlegroups.com
Revision: 2187
Author: mike.popoloski
Date: Sat Mar 17 17:27:04 2012
Log: Added texture loaders for WIC and DDS to replace removed D3DX
functionality.
http://code.google.com/p/slimdx/source/detail?r=2187

Added:
/branches/lite/source/direct3d11/TextureLoader.h
/branches/lite/source/direct3d11/TextureLoaderDDS.cpp
/branches/lite/source/direct3d11/TextureLoaderWIC.cpp
Modified:
/branches/lite/build/SlimDX.vcxproj
/branches/lite/build/SlimDX.vcxproj.filters
/branches/lite/source/Utilities.cpp
/branches/lite/source/Utilities.h
/branches/lite/source/stdafx.h

=======================================
--- /dev/null
+++ /branches/lite/source/direct3d11/TextureLoader.h Sat Mar 17 17:27:04
2012
@@ -0,0 +1,113 @@
+/*
+* Copyright (c) 2007-2012 SlimDX Group
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
copy
+* of this software and associated documentation files (the "Software"), to
deal
+* in the Software without restriction, including without limitation the
rights
+* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+* copies of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+* THE SOFTWARE.
+*/
+#pragma once
+#undef LoadBitmap // stupid Win32
+
+using System::Runtime::InteropServices::OutAttribute;
+
+namespace SlimDX
+{
+ namespace Direct3D11
+ {
+ /// <summary>
+ /// Provides methods for loading and creating textures from image data.
+ /// </summary>
+ public ref class TextureLoader sealed
+ {
+ private:
+ TextureLoader() { }
+
+ public:
+ /// <summary>
+ /// Loads a bitmap image from file and creates a texture from it.
+ /// </summary>
+ /// <param name="device">The device with which to associate the
texture.</param>
+ /// <param name="context">A device context used to generate mipmaps for
the texture. If <c>null</c>, no mipmaps will be generated.</param>
+ /// <param name="fileName">Name of the image file to load.</param>
+ /// <returns>The newly created texture containing the loaded image
data.</returns>
+ static Texture2D^ LoadBitmap(Device^ device, DeviceContext^ context,
System::String^ fileName);
+
+ /// <summary>
+ /// Loads a bitmap image from file and creates a texture from it.
+ /// </summary>
+ /// <param name="device">The device with which to associate the
texture.</param>
+ /// <param name="context">A device context used to generate mipmaps for
the texture. If <c>null</c>, no mipmaps will be generated.</param>
+ /// <param name="fileName">Name of the image file to load.</param>
+ /// <param name="resourceView">When the method completes, contains a
newly created resource view for the texture.</param>
+ /// <returns>The newly created texture containing the loaded image
data.</returns>
+ static Texture2D^ LoadBitmap(Device^ device, DeviceContext^ context,
System::String^ fileName, [Out] ShaderResourceView^ %resourceView);
+
+ /// <summary>
+ /// Loads a bitmap image from a stream and creates a texture from it.
+ /// </summary>
+ /// <param name="device">The device with which to associate the
texture.</param>
+ /// <param name="context">A device context used to generate mipmaps for
the texture. If <c>null</c>, no mipmaps will be generated.</param>
+ /// <param name="data">A stream containing the image data.</param>
+ /// <returns>The newly created texture containing the loaded image
data.</returns>
+ static Texture2D^ LoadBitmap(Device^ device, DeviceContext^ context,
System::IO::Stream^ data);
+
+ /// <summary>
+ /// Loads a bitmap image from a stream and creates a texture from it.
+ /// </summary>
+ /// <param name="device">The device with which to associate the
texture.</param>
+ /// <param name="context">A device context used to generate mipmaps for
the texture. If <c>null</c>, no mipmaps will be generated.</param>
+ /// <param name="data">A stream containing the image data.</param>
+ /// <param name="resourceView">When the method completes, contains a
newly created resource view for the texture.</param>
+ /// <returns>The newly created texture containing the loaded image
data.</returns>
+ static Texture2D^ LoadBitmap(Device^ device, DeviceContext^ context,
System::IO::Stream^ data, [Out] ShaderResourceView^ %resourceView);
+
+ /// <summary>
+ /// Loads a DDS image from file and creates a texture from it.
+ /// </summary>
+ /// <param name="device">The device with which to associate the
texture.</param>
+ /// <param name="fileName">Name of the image file to load.</param>
+ /// <returns>The newly created texture containing the loaded image
data. This can be one of any of the three texture types depending on the
image being loaded.</returns>
+ static Resource^ LoadDDS(Device^ device, System::String^ fileName);
+
+ /// <summary>
+ /// Loads a DDS image from file and creates a texture from it.
+ /// </summary>
+ /// <param name="device">The device with which to associate the
texture.</param>
+ /// <param name="fileName">Name of the image file to load.</param>
+ /// <param name="resourceView">When the method completes, contains a
newly created resource view for the texture.</param>
+ /// <returns>The newly created texture containing the loaded image
data. This can be one of any of the three texture types depending on the
image being loaded.</returns>
+ static Resource^ LoadDDS(Device^ device, System::String^ fileName,
[Out] ShaderResourceView^ %resourceView);
+
+ /// <summary>
+ /// Loads a DDS image from a stream and creates a texture from it.
+ /// </summary>
+ /// <param name="device">The device with which to associate the
texture.</param>
+ /// <param name="data">A stream containing the image data.</param>
+ /// <returns>The newly created texture containing the loaded image
data. This can be one of any of the three texture types depending on the
image being loaded.</returns>
+ static Resource^ LoadDDS(Device^ device, System::IO::Stream^ data);
+
+ /// <summary>
+ /// Loads a DDS image from a stream and creates a texture from it.
+ /// </summary>
+ /// <param name="device">The device with which to associate the
texture.</param>
+ /// <param name="data">A stream containing the image data.</param>
+ /// <param name="resourceView">When the method completes, contains a
newly created resource view for the texture.</param>
+ /// <returns>The newly created texture containing the loaded image
data. This can be one of any of the three texture types depending on the
image being loaded.</returns>
+ static Resource^ LoadDDS(Device^ device, System::IO::Stream^ data,
[Out] ShaderResourceView^ %resourceView);
+ };
+ }
+}
=======================================
--- /dev/null
+++ /branches/lite/source/direct3d11/TextureLoaderDDS.cpp Sat Mar 17
17:27:04 2012
@@ -0,0 +1,1472 @@
+/*
+* Copyright (c) 2007-2012 SlimDX Group
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
copy
+* of this software and associated documentation files (the "Software"), to
deal
+* in the Software without restriction, including without limitation the
rights
+* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+* copies of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+* THE SOFTWARE.
+*/
+#include "stdafx.h"
+
+#include "../Utilities.h"
+
+#include "Direct3D11Exception.h"
+
+#include "Device11.h"
+#include "Resource11.h"
+#include "ShaderResourceView11.h"
+#include "TextureLoader.h"
+
+using namespace System;
+using namespace System::IO;
+
+// NOTE: DDS loading code is from the DirectXTex utility library
+
+//--------------------------------------------------------------------------------------
+// Macros
+//--------------------------------------------------------------------------------------
+#ifndef MAKEFOURCC
+ #define MAKEFOURCC(ch0, ch1, ch2, ch3) \
+ ((uint32_t)(uint8_t)(ch0) | ((uint32_t)(uint8_t)(ch1) <<
8) | \
+ ((uint32_t)(uint8_t)(ch2) << 16) |
((uint32_t)(uint8_t)(ch3) << 24 ))
+#endif /* defined(MAKEFOURCC) */
+
+//--------------------------------------------------------------------------------------
+// DDS file structure definitions
+//
+// See DDS.h in the 'Texconv' sample and the 'DirectXTex' library
+//--------------------------------------------------------------------------------------
+#pragma pack(push,1)
+
+#define DDS_MAGIC 0x20534444 // "DDS "
+
+struct DDS_PIXELFORMAT
+{
+ uint32_t size;
+ uint32_t flags;
+ uint32_t fourCC;
+ uint32_t RGBBitCount;
+ uint32_t RBitMask;
+ uint32_t GBitMask;
+ uint32_t BBitMask;
+ uint32_t ABitMask;
+};
+
+#define DDS_FOURCC 0x00000004 // DDPF_FOURCC
+#define DDS_RGB 0x00000040 // DDPF_RGB
+#define DDS_RGBA 0x00000041 // DDPF_RGB | DDPF_ALPHAPIXELS
+#define DDS_LUMINANCE 0x00020000 // DDPF_LUMINANCE
+#define DDS_LUMINANCEA 0x00020001 // DDPF_LUMINANCE | DDPF_ALPHAPIXELS
+#define DDS_ALPHA 0x00000002 // DDPF_ALPHA
+#define DDS_PAL8 0x00000020 // DDPF_PALETTEINDEXED8
+
+#define DDS_HEADER_FLAGS_TEXTURE 0x00001007 // DDSD_CAPS |
DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT
+#define DDS_HEADER_FLAGS_MIPMAP 0x00020000 // DDSD_MIPMAPCOUNT
+#define DDS_HEADER_FLAGS_VOLUME 0x00800000 // DDSD_DEPTH
+#define DDS_HEADER_FLAGS_PITCH 0x00000008 // DDSD_PITCH
+#define DDS_HEADER_FLAGS_LINEARSIZE 0x00080000 // DDSD_LINEARSIZE
+
+#define DDS_HEIGHT 0x00000002 // DDSD_HEIGHT
+#define DDS_WIDTH 0x00000004 // DDSD_WIDTH
+
+#define DDS_SURFACE_FLAGS_TEXTURE 0x00001000 // DDSCAPS_TEXTURE
+#define DDS_SURFACE_FLAGS_MIPMAP 0x00400008 // DDSCAPS_COMPLEX |
DDSCAPS_MIPMAP
+#define DDS_SURFACE_FLAGS_CUBEMAP 0x00000008 // DDSCAPS_COMPLEX
+
+#define DDS_CUBEMAP_POSITIVEX 0x00000600 // DDSCAPS2_CUBEMAP |
DDSCAPS2_CUBEMAP_POSITIVEX
+#define DDS_CUBEMAP_NEGATIVEX 0x00000a00 // DDSCAPS2_CUBEMAP |
DDSCAPS2_CUBEMAP_NEGATIVEX
+#define DDS_CUBEMAP_POSITIVEY 0x00001200 // DDSCAPS2_CUBEMAP |
DDSCAPS2_CUBEMAP_POSITIVEY
+#define DDS_CUBEMAP_NEGATIVEY 0x00002200 // DDSCAPS2_CUBEMAP |
DDSCAPS2_CUBEMAP_NEGATIVEY
+#define DDS_CUBEMAP_POSITIVEZ 0x00004200 // DDSCAPS2_CUBEMAP |
DDSCAPS2_CUBEMAP_POSITIVEZ
+#define DDS_CUBEMAP_NEGATIVEZ 0x00008200 // DDSCAPS2_CUBEMAP |
DDSCAPS2_CUBEMAP_NEGATIVEZ
+
+#define DDS_CUBEMAP_ALLFACES ( DDS_CUBEMAP_POSITIVEX |
DDS_CUBEMAP_NEGATIVEX |\
+ DDS_CUBEMAP_POSITIVEY |
DDS_CUBEMAP_NEGATIVEY |\
+ DDS_CUBEMAP_POSITIVEZ |
DDS_CUBEMAP_NEGATIVEZ )
+
+#define DDS_CUBEMAP 0x00000200 // DDSCAPS2_CUBEMAP
+
+#define DDS_FLAGS_VOLUME 0x00200000 // DDSCAPS2_VOLUME
+
+typedef struct
+{
+ uint32_t size;
+ uint32_t flags;
+ uint32_t height;
+ uint32_t width;
+ uint32_t pitchOrLinearSize;
+ uint32_t depth; // only if DDS_HEADER_FLAGS_VOLUME is set in
flags
+ uint32_t mipMapCount;
+ uint32_t reserved1[11];
+ DDS_PIXELFORMAT ddspf;
+ uint32_t caps;
+ uint32_t caps2;
+ uint32_t caps3;
+ uint32_t caps4;
+ uint32_t reserved2;
+} DDS_HEADER;
+
+typedef struct
+{
+ DXGI_FORMAT dxgiFormat;
+ uint32_t resourceDimension;
+ uint32_t miscFlag; // see D3D11_RESOURCE_MISC_FLAG
+ uint32_t arraySize;
+ uint32_t reserved;
+} DDS_HEADER_DXT10;
+
+#pragma pack(pop)
+
+//---------------------------------------------------------------------------------
+struct handle_closer { void operator()(HANDLE h) { if (h) CloseHandle(h);
} };
+
+typedef public std::unique_ptr<void, handle_closer> ScopedHandle;
+
+inline HANDLE safe_handle( HANDLE h ) { return (h ==
INVALID_HANDLE_VALUE) ? 0 : h; }
+
+//--------------------------------------------------------------------------------------
+static HRESULT LoadTextureDataFromFile( _In_z_ const wchar_t* fileName,
+ std::unique_ptr<uint8_t[]>&
ddsData,
+ DDS_HEADER** header,
+ uint8_t** bitData,
+ size_t* bitSize
+ )
+{
+ if (!header || !bitData || !bitSize)
+ {
+ return E_POINTER;
+ }
+
+ // open the file
+#if (_WIN32_WINNT >= 0x0602 /*_WIN32_WINNT_WIN8*/)
+ ScopedHandle hFile( safe_handle( CreateFile2( fileName,
+ GENERIC_READ,
+ FILE_SHARE_READ,
+ OPEN_EXISTING,
+ nullptr ) ) );
+#else
+ ScopedHandle hFile( safe_handle( CreateFileW( fileName,
+ GENERIC_READ,
+ FILE_SHARE_READ,
+ nullptr,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ nullptr ) ) );
+#endif
+
+ if ( !hFile )
+ {
+ return HRESULT_FROM_WIN32( GetLastError() );
+ }
+
+ // Get the file size
+ LARGE_INTEGER FileSize = { 0 };
+
+#if (_WIN32_WINNT >= _WIN32_WINNT_VISTA)
+ FILE_STANDARD_INFO fileInfo;
+ if ( !GetFileInformationByHandleEx( hFile.get(), FileStandardInfo,
&fileInfo, sizeof(fileInfo) ) )
+ {
+ return HRESULT_FROM_WIN32( GetLastError() );
+ }
+ FileSize = fileInfo.EndOfFile;
+#else
+ GetFileSizeEx( hFile.get(), &FileSize );
+#endif
+
+ // File is too big for 32-bit allocation, so reject read
+ if (FileSize.HighPart > 0)
+ {
+ return E_FAIL;
+ }
+
+ // Need at least enough data to fill the header and magic number to be
a valid DDS
+ if (FileSize.LowPart < ( sizeof(DDS_HEADER) + sizeof(uint32_t) ) )
+ {
+ return E_FAIL;
+ }
+
+ // create enough space for the file data
+ ddsData.reset( new uint8_t[ FileSize.LowPart ] );
+ if (!ddsData )
+ {
+ return E_OUTOFMEMORY;
+ }
+
+ // read the data in
+ DWORD BytesRead = 0;
+ if (!ReadFile( hFile.get(),
+ ddsData.get(),
+ FileSize.LowPart,
+ &BytesRead,
+ nullptr
+ ))
+ {
+ return HRESULT_FROM_WIN32( GetLastError() );
+ }
+
+ if (BytesRead < FileSize.LowPart)
+ {
+ return E_FAIL;
+ }
+
+ // DDS files always start with the same magic number ("DDS ")
+ uint32_t dwMagicNumber = *( const uint32_t* )( ddsData.get() );
+ if (dwMagicNumber != DDS_MAGIC)
+ {
+ return E_FAIL;
+ }
+
+ DDS_HEADER* hdr = reinterpret_cast<DDS_HEADER*>( ddsData.get() +
sizeof( uint32_t ) );
+
+ // Verify header to validate DDS file
+ if (hdr->size != sizeof(DDS_HEADER) ||
+ hdr->ddspf.size != sizeof(DDS_PIXELFORMAT))
+ {
+ return E_FAIL;
+ }
+
+ // Check for DX10 extension
+ bool bDXT10Header = false;
+ if ((hdr->ddspf.flags & DDS_FOURCC) &&
+ (MAKEFOURCC( 'D', 'X', '1', '0' ) == hdr->ddspf.fourCC))
+ {
+ // Must be long enough for both headers and magic value
+ if (FileSize.LowPart < ( sizeof(DDS_HEADER) + sizeof(uint32_t) +
sizeof(DDS_HEADER_DXT10) ) )
+ {
+ return E_FAIL;
+ }
+
+ bDXT10Header = true;
+ }
+
+ // setup the pointers in the process request
+ *header = hdr;
+ ptrdiff_t offset = sizeof( uint32_t ) + sizeof( DDS_HEADER )
+ + (bDXT10Header ? sizeof( DDS_HEADER_DXT10 ) : 0);
+ *bitData = ddsData.get() + offset;
+ *bitSize = FileSize.LowPart - offset;
+
+ return S_OK;
+}
+
+
+//--------------------------------------------------------------------------------------
+// Return the BPP for a particular format
+//--------------------------------------------------------------------------------------
+static size_t BitsPerPixel( _In_ DXGI_FORMAT fmt )
+{
+ switch( fmt )
+ {
+ case DXGI_FORMAT_R32G32B32A32_TYPELESS:
+ case DXGI_FORMAT_R32G32B32A32_FLOAT:
+ case DXGI_FORMAT_R32G32B32A32_UINT:
+ case DXGI_FORMAT_R32G32B32A32_SINT:
+ return 128;
+
+ case DXGI_FORMAT_R32G32B32_TYPELESS:
+ case DXGI_FORMAT_R32G32B32_FLOAT:
+ case DXGI_FORMAT_R32G32B32_UINT:
+ case DXGI_FORMAT_R32G32B32_SINT:
+ return 96;
+
+ case DXGI_FORMAT_R16G16B16A16_TYPELESS:
+ case DXGI_FORMAT_R16G16B16A16_FLOAT:
+ case DXGI_FORMAT_R16G16B16A16_UNORM:
+ case DXGI_FORMAT_R16G16B16A16_UINT:
+ case DXGI_FORMAT_R16G16B16A16_SNORM:
+ case DXGI_FORMAT_R16G16B16A16_SINT:
+ case DXGI_FORMAT_R32G32_TYPELESS:
+ case DXGI_FORMAT_R32G32_FLOAT:
+ case DXGI_FORMAT_R32G32_UINT:
+ case DXGI_FORMAT_R32G32_SINT:
+ case DXGI_FORMAT_R32G8X24_TYPELESS:
+ case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
+ case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
+ case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT:
+ return 64;
+
+ case DXGI_FORMAT_R10G10B10A2_TYPELESS:
+ case DXGI_FORMAT_R10G10B10A2_UNORM:
+ case DXGI_FORMAT_R10G10B10A2_UINT:
+ case DXGI_FORMAT_R11G11B10_FLOAT:
+ case DXGI_FORMAT_R8G8B8A8_TYPELESS:
+ case DXGI_FORMAT_R8G8B8A8_UNORM:
+ case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
+ case DXGI_FORMAT_R8G8B8A8_UINT:
+ case DXGI_FORMAT_R8G8B8A8_SNORM:
+ case DXGI_FORMAT_R8G8B8A8_SINT:
+ case DXGI_FORMAT_R16G16_TYPELESS:
+ case DXGI_FORMAT_R16G16_FLOAT:
+ case DXGI_FORMAT_R16G16_UNORM:
+ case DXGI_FORMAT_R16G16_UINT:
+ case DXGI_FORMAT_R16G16_SNORM:
+ case DXGI_FORMAT_R16G16_SINT:
+ case DXGI_FORMAT_R32_TYPELESS:
+ case DXGI_FORMAT_D32_FLOAT:
+ case DXGI_FORMAT_R32_FLOAT:
+ case DXGI_FORMAT_R32_UINT:
+ case DXGI_FORMAT_R32_SINT:
+ case DXGI_FORMAT_R24G8_TYPELESS:
+ case DXGI_FORMAT_D24_UNORM_S8_UINT:
+ case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:
+ case DXGI_FORMAT_X24_TYPELESS_G8_UINT:
+ case DXGI_FORMAT_R9G9B9E5_SHAREDEXP:
+ case DXGI_FORMAT_R8G8_B8G8_UNORM:
+ case DXGI_FORMAT_G8R8_G8B8_UNORM:
+ case DXGI_FORMAT_B8G8R8A8_UNORM:
+ case DXGI_FORMAT_B8G8R8X8_UNORM:
+ case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM:
+ case DXGI_FORMAT_B8G8R8A8_TYPELESS:
+ case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
+ case DXGI_FORMAT_B8G8R8X8_TYPELESS:
+ case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
+ return 32;
+
+ case DXGI_FORMAT_R8G8_TYPELESS:
+ case DXGI_FORMAT_R8G8_UNORM:
+ case DXGI_FORMAT_R8G8_UINT:
+ case DXGI_FORMAT_R8G8_SNORM:
+ case DXGI_FORMAT_R8G8_SINT:
+ case DXGI_FORMAT_R16_TYPELESS:
+ case DXGI_FORMAT_R16_FLOAT:
+ case DXGI_FORMAT_D16_UNORM:
+ case DXGI_FORMAT_R16_UNORM:
+ case DXGI_FORMAT_R16_UINT:
+ case DXGI_FORMAT_R16_SNORM:
+ case DXGI_FORMAT_R16_SINT:
+ case DXGI_FORMAT_B5G6R5_UNORM:
+ case DXGI_FORMAT_B5G5R5A1_UNORM:
+
+#ifdef DXGI_1_2_FORMATS
+ case DXGI_FORMAT_B4G4R4A4_UNORM:
+#endif
+ return 16;
+
+ case DXGI_FORMAT_R8_TYPELESS:
+ case DXGI_FORMAT_R8_UNORM:
+ case DXGI_FORMAT_R8_UINT:
+ case DXGI_FORMAT_R8_SNORM:
+ case DXGI_FORMAT_R8_SINT:
+ case DXGI_FORMAT_A8_UNORM:
+ return 8;
+
+ case DXGI_FORMAT_R1_UNORM:
+ return 1;
+
+ case DXGI_FORMAT_BC1_TYPELESS:
+ case DXGI_FORMAT_BC1_UNORM:
+ case DXGI_FORMAT_BC1_UNORM_SRGB:
+ case DXGI_FORMAT_BC4_TYPELESS:
+ case DXGI_FORMAT_BC4_UNORM:
+ case DXGI_FORMAT_BC4_SNORM:
+ return 4;
+
+ case DXGI_FORMAT_BC2_TYPELESS:
+ case DXGI_FORMAT_BC2_UNORM:
+ case DXGI_FORMAT_BC2_UNORM_SRGB:
+ case DXGI_FORMAT_BC3_TYPELESS:
+ case DXGI_FORMAT_BC3_UNORM:
+ case DXGI_FORMAT_BC3_UNORM_SRGB:
+ case DXGI_FORMAT_BC5_TYPELESS:
+ case DXGI_FORMAT_BC5_UNORM:
+ case DXGI_FORMAT_BC5_SNORM:
+ case DXGI_FORMAT_BC6H_TYPELESS:
+ case DXGI_FORMAT_BC6H_UF16:
+ case DXGI_FORMAT_BC6H_SF16:
+ case DXGI_FORMAT_BC7_TYPELESS:
+ case DXGI_FORMAT_BC7_UNORM:
+ case DXGI_FORMAT_BC7_UNORM_SRGB:
+ return 8;
+
+ default:
+ return 0;
+ }
+}
+
+
+//--------------------------------------------------------------------------------------
+// Get surface information for a particular format
+//--------------------------------------------------------------------------------------
+static void GetSurfaceInfo( _In_ size_t width,
+ _In_ size_t height,
+ _In_ DXGI_FORMAT fmt,
+ _Out_opt_ size_t* outNumBytes,
+ _Out_opt_ size_t* outRowBytes,
+ _Out_opt_ size_t* outNumRows )
+{
+ size_t numBytes = 0;
+ size_t rowBytes = 0;
+ size_t numRows = 0;
+
+ bool bc = false;
+ bool packed = false;
+ size_t bcnumBytesPerBlock = 0;
+ switch (fmt)
+ {
+ case DXGI_FORMAT_BC1_TYPELESS:
+ case DXGI_FORMAT_BC1_UNORM:
+ case DXGI_FORMAT_BC1_UNORM_SRGB:
+ case DXGI_FORMAT_BC4_TYPELESS:
+ case DXGI_FORMAT_BC4_UNORM:
+ case DXGI_FORMAT_BC4_SNORM:
+ bc=true;
+ bcnumBytesPerBlock = 8;
+ break;
+
+ case DXGI_FORMAT_BC2_TYPELESS:
+ case DXGI_FORMAT_BC2_UNORM:
+ case DXGI_FORMAT_BC2_UNORM_SRGB:
+ case DXGI_FORMAT_BC3_TYPELESS:
+ case DXGI_FORMAT_BC3_UNORM:
+ case DXGI_FORMAT_BC3_UNORM_SRGB:
+ case DXGI_FORMAT_BC5_TYPELESS:
+ case DXGI_FORMAT_BC5_UNORM:
+ case DXGI_FORMAT_BC5_SNORM:
+ case DXGI_FORMAT_BC6H_TYPELESS:
+ case DXGI_FORMAT_BC6H_UF16:
+ case DXGI_FORMAT_BC6H_SF16:
+ case DXGI_FORMAT_BC7_TYPELESS:
+ case DXGI_FORMAT_BC7_UNORM:
+ case DXGI_FORMAT_BC7_UNORM_SRGB:
+ bc = true;
+ bcnumBytesPerBlock = 16;
+ break;
+
+ case DXGI_FORMAT_R8G8_B8G8_UNORM:
+ case DXGI_FORMAT_G8R8_G8B8_UNORM:
+ packed = true;
+ break;
+ }
+
+ if (bc)
+ {
+ size_t numBlocksWide = 0;
+ if (width > 0)
+ {
+ numBlocksWide = std::max<size_t>( 1, (width + 3) / 4 );
+ }
+ size_t numBlocksHigh = 0;
+ if (height > 0)
+ {
+ numBlocksHigh = std::max<size_t>( 1, (height + 3) / 4 );
+ }
+ rowBytes = numBlocksWide * bcnumBytesPerBlock;
+ numRows = numBlocksHigh;
+ }
+ else if (packed)
+ {
+ rowBytes = ( ( width + 1 ) >> 1 ) * 4;
+ numRows = height;
+ }
+ else
+ {
+ size_t bpp = BitsPerPixel( fmt );
+ rowBytes = ( width * bpp + 7 ) / 8; // round up to nearest byte
+ numRows = height;
+ }
+
+ numBytes = rowBytes * numRows;
+ if (outNumBytes)
+ {
+ *outNumBytes = numBytes;
+ }
+ if (outRowBytes)
+ {
+ *outRowBytes = rowBytes;
+ }
+ if (outNumRows)
+ {
+ *outNumRows = numRows;
+ }
+}
+
+
+//--------------------------------------------------------------------------------------
+#define ISBITMASK( r,g,b,a ) ( ddpf.RBitMask == r && ddpf.GBitMask == g &&
ddpf.BBitMask == b && ddpf.ABitMask == a )
+
+static DXGI_FORMAT GetDXGIFormat( const DDS_PIXELFORMAT& ddpf )
+{
+ if (ddpf.flags & DDS_RGB)
+ {
+ // Note that sRGB formats are written using the "DX10" extended
header
+
+ switch (ddpf.RGBBitCount)
+ {
+ case 32:
+ if (ISBITMASK(0x000000ff,0x0000ff00,0x00ff0000,0xff000000))
+ {
+ return DXGI_FORMAT_R8G8B8A8_UNORM;
+ }
+
+ if (ISBITMASK(0x00ff0000,0x0000ff00,0x000000ff,0xff000000))
+ {
+ return DXGI_FORMAT_B8G8R8A8_UNORM;
+ }
+
+ if (ISBITMASK(0x00ff0000,0x0000ff00,0x000000ff,0x00000000))
+ {
+ return DXGI_FORMAT_B8G8R8X8_UNORM;
+ }
+
+ // No DXGI format maps to
ISBITMASK(0x000000ff,0x0000ff00,0x00ff0000,0x00000000) aka D3DFMT_X8B8G8R8
+
+ // Note that many common DDS reader/writers (including D3DX)
swap the
+ // the RED/BLUE masks for 10:10:10:2 formats. We assumme
+ // below that the 'backwards' header mask is being used since
it is most
+ // likely written by D3DX. The more robust solution is to use
the 'DX10'
+ // header extension and specify the
DXGI_FORMAT_R10G10B10A2_UNORM format directly
+
+ // For 'correct' writers, this should be
0x000003ff,0x000ffc00,0x3ff00000 for RGB data
+ if (ISBITMASK(0x3ff00000,0x000ffc00,0x000003ff,0xc0000000))
+ {
+ return DXGI_FORMAT_R10G10B10A2_UNORM;
+ }
+
+ // No DXGI format maps to
ISBITMASK(0x000003ff,0x000ffc00,0x3ff00000,0xc0000000) aka
D3DFMT_A2R10G10B10
+
+ if (ISBITMASK(0x0000ffff,0xffff0000,0x00000000,0x00000000))
+ {
+ return DXGI_FORMAT_R16G16_UNORM;
+ }
+
+ if (ISBITMASK(0xffffffff,0x00000000,0x00000000,0x00000000))
+ {
+ // Only 32-bit color channel format in D3D9 was R32F
+ return DXGI_FORMAT_R32_FLOAT; // D3DX writes this out as a
FourCC of 114
+ }
+ break;
+
+ case 24:
+ // No 24bpp DXGI formats aka D3DFMT_R8G8B8
+ break;
+
+ case 16:
+ if (ISBITMASK(0x7c00,0x03e0,0x001f,0x8000))
+ {
+ return DXGI_FORMAT_B5G5R5A1_UNORM;
+ }
+ if (ISBITMASK(0xf800,0x07e0,0x001f,0x0000))
+ {
+ return DXGI_FORMAT_B5G6R5_UNORM;
+ }
+
+ // No DXGI format maps to
ISBITMASK(0x7c00,0x03e0,0x001f,0x0000) aka D3DFMT_X1R5G5B5
+
+#ifdef DXGI_1_2_FORMATS
+ if (ISBITMASK(0x0f00,0x00f0,0x000f,0xf000))
+ {
+ return DXGI_FORMAT_B4G4R4A4_UNORM;
+ }
+
+ // No DXGI format maps to
ISBITMASK(0x0f00,0x00f0,0x000f,0x0000) aka D3DFMT_X4R4G4B4
+#endif
+
+ // No 3:3:2, 3:3:2:8, or paletted DXGI formats aka
D3DFMT_A8R3G3B2, D3DFMT_R3G3B2, D3DFMT_P8, D3DFMT_A8P8, etc.
+ break;
+ }
+ }
+ else if (ddpf.flags & DDS_LUMINANCE)
+ {
+ if (8 == ddpf.RGBBitCount)
+ {
+ if (ISBITMASK(0x000000ff,0x00000000,0x00000000,0x00000000))
+ {
+ return DXGI_FORMAT_R8_UNORM; // D3DX10/11 writes this out
as DX10 extension
+ }
+
+ // No DXGI format maps to ISBITMASK(0x0f,0x00,0x00,0xf0) aka
D3DFMT_A4L4
+ }
+
+ if (16 == ddpf.RGBBitCount)
+ {
+ if (ISBITMASK(0x0000ffff,0x00000000,0x00000000,0x00000000))
+ {
+ return DXGI_FORMAT_R16_UNORM; // D3DX10/11 writes this out
as DX10 extension
+ }
+ if (ISBITMASK(0x000000ff,0x00000000,0x00000000,0x0000ff00))
+ {
+ return DXGI_FORMAT_R8G8_UNORM; // D3DX10/11 writes this
out as DX10 extension
+ }
+ }
+ }
+ else if (ddpf.flags & DDS_ALPHA)
+ {
+ if (8 == ddpf.RGBBitCount)
+ {
+ return DXGI_FORMAT_A8_UNORM;
+ }
+ }
+ else if (ddpf.flags & DDS_FOURCC)
+ {
+ if (MAKEFOURCC( 'D', 'X', 'T', '1' ) == ddpf.fourCC)
+ {
+ return DXGI_FORMAT_BC1_UNORM;
+ }
+ if (MAKEFOURCC( 'D', 'X', 'T', '3' ) == ddpf.fourCC)
+ {
+ return DXGI_FORMAT_BC2_UNORM;
+ }
+ if (MAKEFOURCC( 'D', 'X', 'T', '5' ) == ddpf.fourCC)
+ {
+ return DXGI_FORMAT_BC3_UNORM;
+ }
+
+ // While pre-mulitplied alpha isn't directly supported by the DXGI
formats,
+ // they are basically the same as these BC formats so they can be
mapped
+ if (MAKEFOURCC( 'D', 'X', 'T', '2' ) == ddpf.fourCC)
+ {
+ return DXGI_FORMAT_BC2_UNORM;
+ }
+ if (MAKEFOURCC( 'D', 'X', 'T', '4' ) == ddpf.fourCC)
+ {
+ return DXGI_FORMAT_BC3_UNORM;
+ }
+
+ if (MAKEFOURCC( 'A', 'T', 'I', '1' ) == ddpf.fourCC)
+ {
+ return DXGI_FORMAT_BC4_UNORM;
+ }
+ if (MAKEFOURCC( 'B', 'C', '4', 'U' ) == ddpf.fourCC)
+ {
+ return DXGI_FORMAT_BC4_UNORM;
+ }
+ if (MAKEFOURCC( 'B', 'C', '4', 'S' ) == ddpf.fourCC)
+ {
+ return DXGI_FORMAT_BC4_SNORM;
+ }
+
+ if (MAKEFOURCC( 'A', 'T', 'I', '2' ) == ddpf.fourCC)
+ {
+ return DXGI_FORMAT_BC5_UNORM;
+ }
+ if (MAKEFOURCC( 'B', 'C', '5', 'U' ) == ddpf.fourCC)
+ {
+ return DXGI_FORMAT_BC5_UNORM;
+ }
+ if (MAKEFOURCC( 'B', 'C', '5', 'S' ) == ddpf.fourCC)
+ {
+ return DXGI_FORMAT_BC5_SNORM;
+ }
+
+ // BC6H and BC7 are written using the "DX10" extended header
+
+ if (MAKEFOURCC( 'R', 'G', 'B', 'G' ) == ddpf.fourCC)
+ {
+ return DXGI_FORMAT_R8G8_B8G8_UNORM;
+ }
+ if (MAKEFOURCC( 'G', 'R', 'G', 'B' ) == ddpf.fourCC)
+ {
+ return DXGI_FORMAT_G8R8_G8B8_UNORM;
+ }
+
+ // Check for D3DFORMAT enums being set here
+ switch( ddpf.fourCC )
+ {
+ case 36: // D3DFMT_A16B16G16R16
+ return DXGI_FORMAT_R16G16B16A16_UNORM;
+
+ case 110: // D3DFMT_Q16W16V16U16
+ return DXGI_FORMAT_R16G16B16A16_SNORM;
+
+ case 111: // D3DFMT_R16F
+ return DXGI_FORMAT_R16_FLOAT;
+
+ case 112: // D3DFMT_G16R16F
+ return DXGI_FORMAT_R16G16_FLOAT;
+
+ case 113: // D3DFMT_A16B16G16R16F
+ return DXGI_FORMAT_R16G16B16A16_FLOAT;
+
+ case 114: // D3DFMT_R32F
+ return DXGI_FORMAT_R32_FLOAT;
+
+ case 115: // D3DFMT_G32R32F
+ return DXGI_FORMAT_R32G32_FLOAT;
+
+ case 116: // D3DFMT_A32B32G32R32F
+ return DXGI_FORMAT_R32G32B32A32_FLOAT;
+ }
+ }
+
+ return DXGI_FORMAT_UNKNOWN;
+}
+
+
+//--------------------------------------------------------------------------------------
+static HRESULT FillInitData( _In_ size_t width,
+ _In_ size_t height,
+ _In_ size_t depth,
+ _In_ size_t mipCount,
+ _In_ size_t arraySize,
+ _In_ DXGI_FORMAT format,
+ _In_ size_t maxsize,
+ _In_ size_t bitSize,
+ _In_bytecount_(bitSize) const uint8_t*
bitData,
+ _Out_ size_t& twidth,
+ _Out_ size_t& theight,
+ _Out_ size_t& tdepth,
+ _Out_ size_t& skipMip,
+ _Out_cap_(mipCount*arraySize)
D3D11_SUBRESOURCE_DATA* initData )
+{
+ if ( !bitData || !initData )
+ return E_POINTER;
+
+ skipMip = 0;
+ twidth = 0;
+ theight = 0;
+ tdepth = 0;
+
+ size_t NumBytes = 0;
+ size_t RowBytes = 0;
+ size_t NumRows = 0;
+ const uint8_t* pSrcBits = bitData;
+ const uint8_t* pEndBits = bitData + bitSize;
+
+ size_t index = 0;
+ for( size_t j = 0; j < arraySize; j++ )
+ {
+ size_t w = width;
+ size_t h = height;
+ size_t d = depth;
+ for( size_t i = 0; i < mipCount; i++ )
+ {
+ GetSurfaceInfo( w,
+ h,
+ format,
+ &NumBytes,
+ &RowBytes,
+ &NumRows
+ );
+
+ if ( (mipCount <= 1) || !maxsize || (w <= maxsize && h <=
maxsize && d <= maxsize) )
+ {
+ if ( !twidth )
+ {
+ twidth = w;
+ theight = h;
+ tdepth = d;
+ }
+
+ initData[index].pSysMem = ( const void* )pSrcBits;
+ initData[index].SysMemPitch = static_cast<UINT>( RowBytes
);
+ initData[index].SysMemSlicePitch = static_cast<UINT>(
NumBytes );
+ ++index;
+ }
+ else
+ ++skipMip;
+
+ if (pSrcBits + (NumBytes*d) > pEndBits)
+ {
+ return HRESULT_FROM_WIN32( ERROR_HANDLE_EOF );
+ }
+
+ pSrcBits += NumBytes * d;
+
+ w = w >> 1;
+ h = h >> 1;
+ d = d >> 1;
+ if (w == 0)
+ {
+ w = 1;
+ }
+ if (h == 0)
+ {
+ h = 1;
+ }
+ if (d == 0)
+ {
+ d = 1;
+ }
+ }
+ }
+
+ return (index > 0) ? S_OK : E_FAIL;
+}
+
+
+//--------------------------------------------------------------------------------------
+static HRESULT CreateD3DResources( _In_ ID3D11Device* d3dDevice,
+ _In_ uint32_t resDim,
+ _In_ size_t width,
+ _In_ size_t height,
+ _In_ size_t depth,
+ _In_ size_t mipCount,
+ _In_ size_t arraySize,
+ _In_ DXGI_FORMAT format,
+ _In_ bool isCubeMap,
+ _In_count_(mipCount*arraySize)
D3D11_SUBRESOURCE_DATA* initData,
+ _Out_opt_ ID3D11Resource** texture,
+ _Out_opt_ ID3D11ShaderResourceView**
textureView )
+{
+ if ( !d3dDevice || !initData )
+ return E_POINTER;
+
+ HRESULT hr = E_FAIL;
+
+ switch ( resDim )
+ {
+ case D3D11_RESOURCE_DIMENSION_TEXTURE1D:
+ {
+ D3D11_TEXTURE1D_DESC desc;
+ desc.Width = static_cast<UINT>( width );
+ desc.MipLevels = static_cast<UINT>( mipCount );
+ desc.ArraySize = static_cast<UINT>( arraySize );
+ desc.Format = format;
+ desc.Usage = D3D11_USAGE_DEFAULT;
+ desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
+ desc.CPUAccessFlags = 0;
+ desc.MiscFlags = 0;
+
+ ID3D11Texture1D* tex = nullptr;
+ hr = d3dDevice->CreateTexture1D( &desc,
+ initData,
+ &tex
+ );
+ if (SUCCEEDED( hr ) && tex != 0)
+ {
+ if (textureView != 0)
+ {
+ D3D11_SHADER_RESOURCE_VIEW_DESC SRVDesc;
+ memset( &SRVDesc, 0, sizeof( SRVDesc ) );
+ SRVDesc.Format = format;
+
+ if (arraySize > 1)
+ {
+ SRVDesc.ViewDimension =
D3D11_SRV_DIMENSION_TEXTURE1DARRAY;
+ SRVDesc.Texture1DArray.MipLevels =
desc.MipLevels;
+ SRVDesc.Texture1DArray.ArraySize =
static_cast<UINT>( arraySize );
+ }
+ else
+ {
+ SRVDesc.ViewDimension =
D3D11_SRV_DIMENSION_TEXTURE1D;
+ SRVDesc.Texture1D.MipLevels = desc.MipLevels;
+ }
+
+ hr = d3dDevice->CreateShaderResourceView( tex,
+ &SRVDesc,
+
textureView
+ );
+ if ( FAILED(hr) )
+ {
+ tex->Release();
+ return hr;
+ }
+ }
+
+ if (texture != 0)
+ {
+ *texture = tex;
+ }
+ else
+ {
+#if defined(DEBUG) || defined(PROFILE)
+ tex->SetPrivateData( WKPDID_D3DDebugObjectName,
+ sizeof("DDSTextureLoader")-1,
+ "DDSTextureLoader" );
+#endif
+ tex->Release();
+ }
+ }
+ }
+ break;
+
+ case D3D11_RESOURCE_DIMENSION_TEXTURE2D:
+ {
+ D3D11_TEXTURE2D_DESC desc;
+ desc.Width = static_cast<UINT>( width );
+ desc.Height = static_cast<UINT>( height );
+ desc.MipLevels = static_cast<UINT>( mipCount );
+ desc.ArraySize = static_cast<UINT>( arraySize );
+ desc.Format = format;
+ desc.SampleDesc.Count = 1;
+ desc.SampleDesc.Quality = 0;
+ desc.Usage = D3D11_USAGE_DEFAULT;
+ desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
+ desc.CPUAccessFlags = 0;
+ desc.MiscFlags = (isCubeMap) ?
D3D11_RESOURCE_MISC_TEXTURECUBE : 0;
+
+ ID3D11Texture2D* tex = nullptr;
+ hr = d3dDevice->CreateTexture2D( &desc,
+ initData,
+ &tex
+ );
+ if (SUCCEEDED( hr ) && tex != 0)
+ {
+ if (textureView != 0)
+ {
+ D3D11_SHADER_RESOURCE_VIEW_DESC SRVDesc;
+ memset( &SRVDesc, 0, sizeof( SRVDesc ) );
+ SRVDesc.Format = format;
+
+ if (isCubeMap)
+ {
+ if (arraySize > 6)
+ {
+ SRVDesc.ViewDimension =
D3D11_SRV_DIMENSION_TEXTURECUBEARRAY;
+ SRVDesc.TextureCubeArray.MipLevels =
desc.MipLevels;
+
+ // Earlier we set arraySize to (NumCubes *
6)
+ SRVDesc.TextureCubeArray.NumCubes =
static_cast<UINT>( arraySize / 6 );
+ }
+ else
+ {
+ SRVDesc.ViewDimension =
D3D11_SRV_DIMENSION_TEXTURECUBE;
+ SRVDesc.TextureCube.MipLevels =
desc.MipLevels;
+ }
+ }
+ else if (arraySize > 1)
+ {
+ SRVDesc.ViewDimension =
D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
+ SRVDesc.Texture2DArray.MipLevels =
desc.MipLevels;
+ SRVDesc.Texture2DArray.ArraySize =
static_cast<UINT>( arraySize );
+ }
+ else
+ {
+ SRVDesc.ViewDimension =
D3D11_SRV_DIMENSION_TEXTURE2D;
+ SRVDesc.Texture2D.MipLevels = desc.MipLevels;
+ }
+
+ hr = d3dDevice->CreateShaderResourceView( tex,
+ &SRVDesc,
+
textureView
+ );
+ if ( FAILED(hr) )
+ {
+ tex->Release();
+ return hr;
+ }
+ }
+
+ if (texture != 0)
+ {
+ *texture = tex;
+ }
+ else
+ {
+#if defined(DEBUG) || defined(PROFILE)
+ tex->SetPrivateData( WKPDID_D3DDebugObjectName,
+ sizeof("DDSTextureLoader")-1,
+ "DDSTextureLoader"
+ );
+#endif
+ tex->Release();
+ }
+ }
+ }
+ break;
+
+ case D3D11_RESOURCE_DIMENSION_TEXTURE3D:
+ {
+ D3D11_TEXTURE3D_DESC desc;
+ desc.Width = static_cast<UINT>( width );
+ desc.Height = static_cast<UINT>( height );
+ desc.Depth = static_cast<UINT>( depth );
+ desc.MipLevels = static_cast<UINT>( mipCount );
+ desc.Format = format;
+ desc.Usage = D3D11_USAGE_DEFAULT;
+ desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
+ desc.CPUAccessFlags = 0;
+ desc.MiscFlags = 0;
+
+ ID3D11Texture3D* tex = nullptr;
+ hr = d3dDevice->CreateTexture3D( &desc,
+ 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_TEXTURE3D;
+ SRVDesc.Texture3D.MipLevels = desc.MipLevels;
+
***The diff for this file has been truncated for email.***
=======================================
--- /dev/null
+++ /branches/lite/source/direct3d11/TextureLoaderWIC.cpp Sat Mar 17
17:27:04 2012
@@ -0,0 +1,687 @@
+/*
+* Copyright (c) 2007-2012 SlimDX Group
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
copy
+* of this software and associated documentation files (the "Software"), to
deal
+* in the Software without restriction, including without limitation the
rights
+* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+* copies of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+* THE SOFTWARE.
+*/
+#include "stdafx.h"
+
+#include "../Utilities.h"
+
+#include "Direct3D11Exception.h"
+
+#include "Device11.h"
+#include "DeviceContext11.h"
+#include "Texture2D11.h"
+#include "ShaderResourceView11.h"
+#include "TextureLoader.h"
+
+using namespace System;
+using namespace System::IO;
+
+// NOTE: WIC loading code is from the DirectXTex utility library
+
+//-------------------------------------------------------------------------------------
+// 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 },
+
+ { 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
+
+ { GUID_WICPixelFormat16bppBGR555,
GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
+ { GUID_WICPixelFormat16bppBGRA5551,
GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
+ { GUID_WICPixelFormat16bppBGR565,
GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_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_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
+
+ // We don't support n-channel formats
+};
+
+//---------------------------------------------------------------------------------
+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;
+};
+
+//--------------------------------------------------------------------------------------
+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_ ID3D11Texture2D** 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;
+}
+
+namespace SlimDX
+{
+namespace Direct3D11
+{
+ Texture2D^ TextureLoader::LoadBitmap(Device^ device, DeviceContext^
context, String^ fileName)
+ {
+ if (device == nullptr)
+ throw gcnew ArgumentNullException("device");
+ if (context == nullptr)
+ throw gcnew ArgumentNullException("context");
+ if (String::IsNullOrEmpty(fileName))
+ throw gcnew ArgumentNullException("fileName");
+
+ IWICImagingFactory* pWIC = _GetWIC();
+ if ( !pWIC )
+ throw gcnew InvalidOperationException("Failed to initialize WIC for
image load.");
+
+ // Initialize WIC
+ ScopedObject<IWICBitmapDecoder> decoder;
+ pin_ptr<const wchar_t> pinnedName = PtrToStringChars(fileName);
+ HRESULT hr = pWIC->CreateDecoderFromFilename( pinnedName, 0,
GENERIC_READ, WICDecodeMetadataCacheOnDemand, &decoder );
+ if ( FAILED(hr) )
+ throw gcnew FileNotFoundException("Unable to load the specified image
file.", fileName);
+
+ ScopedObject<IWICBitmapFrameDecode> frame;
+ hr = decoder->GetFrame( 0, &frame );
+ if ( FAILED(hr) )
+ throw gcnew InvalidDataException("Could not decode the given image
file.");
+
+ ID3D11Texture2D *texture;
+ hr = CreateTextureFromWIC( device->InternalPointer, context == nullptr ?
0 : context->InternalPointer, frame.Get(), &texture, 0, 0 );
+ if (RECORD_D3D11(hr).IsFailure)
+ return nullptr;
+
+ return Texture2D::FromPointer(texture);
+ }
+
+ Texture2D^ TextureLoader::LoadBitmap(Device^ device, DeviceContext^
context, String^ fileName, [Out] ShaderResourceView^ %resourceView)
+ {
+ if (device == nullptr)
+ throw gcnew ArgumentNullException("device");
+ if (context == nullptr)
+ throw gcnew ArgumentNullException("context");
+ if (String::IsNullOrEmpty(fileName))
+ throw gcnew ArgumentNullException("fileName");
+
+ IWICImagingFactory* pWIC = _GetWIC();
+ if ( !pWIC )
+ throw gcnew InvalidOperationException("Failed to initialize WIC for
image load.");
+
+ // Initialize WIC
+ ScopedObject<IWICBitmapDecoder> decoder;
+ pin_ptr<const wchar_t> pinnedName = PtrToStringChars(fileName);
+ HRESULT hr = pWIC->CreateDecoderFromFilename( pinnedName, 0,
GENERIC_READ, WICDecodeMetadataCacheOnDemand, &decoder );
+ if ( FAILED(hr) )
+ throw gcnew FileNotFoundException("Unable to load the specified image
file.", fileName);
+
+ ScopedObject<IWICBitmapFrameDecode> frame;
+ hr = decoder->GetFrame( 0, &frame );
+ if ( FAILED(hr) )
+ throw gcnew InvalidDataException("Could not decode the given image
file.");
+
+ ID3D11Texture2D *texture;
+ ID3D11ShaderResourceView *view;
+ hr = CreateTextureFromWIC( device->InternalPointer, context == nullptr ?
0 : context->InternalPointer, frame.Get(), &texture, &view, 0 );
+ if (RECORD_D3D11(hr).IsFailure)
+ {
+ resourceView = nullptr;
+ return nullptr;
+ }
+
+ resourceView = ShaderResourceView::FromPointer(view);
+ return Texture2D::FromPointer(texture);
+ }
+
+ Texture2D^ TextureLoader::LoadBitmap(Device^ device, DeviceContext^
context, Stream^ data)
+ {
+ if (device == nullptr)
+ throw gcnew ArgumentNullException("device");
+ if (context == nullptr)
+ throw gcnew ArgumentNullException("context");
+ if (data == nullptr)
+ throw gcnew ArgumentNullException("data");
+
+ IWICImagingFactory* pWIC = _GetWIC();
+ if ( !pWIC )
+ throw gcnew InvalidOperationException("Failed to initialize WIC for
image load.");
+
+ // Create input stream for memory
+ ScopedObject<IWICStream> stream;
+ HRESULT hr = pWIC->CreateStream( &stream );
+ if ( FAILED(hr) )
+ throw gcnew InvalidOperationException("Failed to create WIC stream.");
+
+ int wicDataSize = 0;
+ bool cleanUp = true;
+ std::unique_ptr<char> dataPtr;
+ char *wicData = Utilities::ReadStream(data, wicDataSize, cleanUp);
+ if (cleanUp)
+ dataPtr.reset(wicData);
+
+ hr = stream->InitializeFromMemory( reinterpret_cast<uint8_t*>( wicData
), static_cast<DWORD>( wicDataSize ) );
+ if ( FAILED(hr) )
+ throw gcnew InvalidDataException("Could not decode the given image
data.");
+
+ // Initialize WIC
+ ScopedObject<IWICBitmapDecoder> decoder;
+ hr = pWIC->CreateDecoderFromStream( stream.Get(), 0,
WICDecodeMetadataCacheOnDemand, &decoder );
+ if ( FAILED(hr) )
+ throw gcnew InvalidDataException("Could not decode the given image
data.");
+
+ ScopedObject<IWICBitmapFrameDecode> frame;
+ hr = decoder->GetFrame( 0, &frame );
+ if ( FAILED(hr) )
+ throw gcnew InvalidDataException("Could not decode the given image
data.");
+
+ ID3D11Texture2D *texture;
+ hr = CreateTextureFromWIC( device->InternalPointer, context == nullptr ?
0 : context->InternalPointer, frame.Get(), &texture, 0, 0 );
+ if (RECORD_D3D11(hr).IsFailure)
+ return nullptr;
+
+ return Texture2D::FromPointer(texture);
+ }
+
+ Texture2D^ TextureLoader::LoadBitmap(Device^ device, DeviceContext^
context, Stream^ data, [Out] ShaderResourceView^ %resourceView)
+ {
+ if (device == nullptr)
+ throw gcnew ArgumentNullException("device");
+ if (context == nullptr)
+ throw gcnew ArgumentNullException("context");
+ if (data == nullptr)
+ throw gcnew ArgumentNullException("data");
+
+ IWICImagingFactory* pWIC = _GetWIC();
+ if ( !pWIC )
+ throw gcnew InvalidOperationException("Failed to initialize WIC for
image load.");
+
+ // Create input stream for memory
+ ScopedObject<IWICStream> stream;
+ HRESULT hr = pWIC->CreateStream( &stream );
+ if ( FAILED(hr) )
+ throw gcnew InvalidOperationException("Failed to create WIC stream.");
+
+ int wicDataSize = 0;
+ bool cleanUp = true;
+ std::unique_ptr<char> dataPtr;
+ char *wicData = Utilities::ReadStream(data, wicDataSize, cleanUp);
+ if (cleanUp)
+ dataPtr.reset(wicData);
+
+ hr = stream->InitializeFromMemory( reinterpret_cast<uint8_t*>( wicData
), static_cast<DWORD>( wicDataSize ) );
+ if ( FAILED(hr) )
+ throw gcnew InvalidDataException("Could not decode the given image
data.");
+
+ // Initialize WIC
+ ScopedObject<IWICBitmapDecoder> decoder;
+ hr = pWIC->CreateDecoderFromStream( stream.Get(), 0,
WICDecodeMetadataCacheOnDemand, &decoder );
+ if ( FAILED(hr) )
+ throw gcnew InvalidDataException("Could not decode the given image
data.");
+
+ ScopedObject<IWICBitmapFrameDecode> frame;
+ hr = decoder->GetFrame( 0, &frame );
+ if ( FAILED(hr) )
+ throw gcnew InvalidDataException("Could not decode the given image
data.");
+
+ ID3D11Texture2D *texture;
+ ID3D11ShaderResourceView *view;
+ hr = CreateTextureFromWIC( device->InternalPointer, context == nullptr ?
0 : context->InternalPointer, frame.Get(), &texture, &view, 0 );
+ if (RECORD_D3D11(hr).IsFailure)
+ {
+ resourceView = nullptr;
+ return nullptr;
+ }
+
+ resourceView = ShaderResourceView::FromPointer(view);
+ return Texture2D::FromPointer(texture);
+ }
+}
+}
=======================================
--- /branches/lite/build/SlimDX.vcxproj Sat Mar 17 12:07:17 2012
+++ /branches/lite/build/SlimDX.vcxproj Sat Mar 17 17:27:04 2012
@@ -238,6 +238,8 @@
<ClCompile Include="..\source\ComObject.cpp" />
<ClCompile Include="..\source\CompilationException.cpp" />
<ClCompile Include="..\source\Configuration.cpp" />
+ <ClCompile Include="..\source\direct3d11\TextureLoaderDDS.cpp" />
+ <ClCompile Include="..\source\direct3d11\TextureLoaderWIC.cpp" />
<ClCompile Include="..\source\directwrite\GlyphRunDescription.cpp" />
<ClCompile Include="..\source\directwrite\ITextRenderer.cpp" />
<ClCompile Include="..\source\directwrite\Strikethrough.cpp" />
@@ -463,6 +465,7 @@
<ClInclude Include="..\source\ComObjectMacros.h" />
<ClInclude Include="..\source\CompilationException.h" />
<ClInclude Include="..\source\Configuration.h" />
+ <ClInclude Include="..\source\direct3d11\TextureLoader.h" />
<ClInclude Include="..\source\directwrite\GlyphRunDescription.h" />
<ClInclude Include="..\source\directwrite\ITextRenderer.h" />
<ClInclude Include="..\source\directwrite\Strikethrough.h" />
=======================================
--- /branches/lite/build/SlimDX.vcxproj.filters Sat Mar 17 12:07:17 2012
+++ /branches/lite/build/SlimDX.vcxproj.filters Sat Mar 17 17:27:04 2012
@@ -898,6 +898,12 @@
<ClCompile Include="..\source\directwrite\Underline.cpp">
<Filter>DirectWrite</Filter>
</ClCompile>
+ <ClCompile Include="..\source\direct3d11\TextureLoaderWIC.cpp">
+ <Filter>Direct3D11\Texture</Filter>
+ </ClCompile>
+ <ClCompile Include="..\source\direct3d11\TextureLoaderDDS.cpp">
+ <Filter>Direct3D11\Texture</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\source\auto_array.h">
@@ -1636,6 +1642,9 @@
<ClInclude Include="..\source\directwrite\Underline.h">
<Filter>DirectWrite</Filter>
</ClInclude>
+ <ClInclude Include="..\source\direct3d11\TextureLoader.h">
+ <Filter>Direct3D11\Texture</Filter>
+ </ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="..\source\directwrite\ToDo.txt">
=======================================
--- /branches/lite/source/Utilities.cpp Sat Mar 17 11:15:48 2012
+++ /branches/lite/source/Utilities.cpp Sat Mar 17 17:27:04 2012
@@ -287,6 +287,48 @@

return buffer;
}
+
+ char* Utilities::ReadStream( Stream^ stream, int% readLength, bool%
cleanUp )
+ {
+ if( stream == nullptr )
+ throw gcnew ArgumentNullException( "stream" );
+ if( !stream->CanRead )
+ throw gcnew NotSupportedException();
+
+ if( readLength > stream->Length - stream->Position )
+ throw gcnew ArgumentOutOfRangeException( "readLength" );
+ if( readLength == 0 )
+ readLength = static_cast<int>( stream->Length - stream->Position );
+ if( readLength < 0 )
+ throw gcnew ArgumentOutOfRangeException( "readLength" );
+ if( readLength == 0 )
+ {
+ cleanUp = true;
+ return new char[0];
+ }
+
+ // if we're reading a DataStream, don't return anything and send back
the casted DataStream
+ DataStream^ ds = dynamic_cast<DataStream^>( stream );
+ if( ds != nullptr )
+ {
+ cleanUp = false;
+ return ds->RawPointer;
+ }
+
+ WaveStream^ ws = dynamic_cast<WaveStream^>( stream );
+ if( ws != nullptr && ws->InternalMemory != nullptr )
+ {
+ cleanUp = false;
+ return ws->InternalMemory->RawPointer;
+ }
+
+ cleanUp = true;
+ char *result = new char[readLength];
+ for (int i = 0; i < readLength; i++)
+ result[i] = stream->ReadByte();
+
+ return result;
+ }

void Utilities::CheckArrayBounds( Array^ data, int offset, int% count )
{
=======================================
--- /branches/lite/source/Utilities.h Sat Mar 17 12:07:17 2012
+++ /branches/lite/source/Utilities.h Sat Mar 17 17:27:04 2012
@@ -55,6 +55,7 @@

static System::String^ BlobToString( ID3DBlob *blob );

+ static char* ReadStream( System::IO::Stream^ stream, int% readLength,
bool% cleanUp );
static array<System::Byte>^ ReadStream( System::IO::Stream^ stream,
DataStream^* dataStream );
static array<System::Byte>^ ReadStream( System::IO::Stream^ stream, int%
readLength, DataStream^* dataStream );

=======================================
--- /branches/lite/source/stdafx.h Sat Mar 17 12:07:17 2012
+++ /branches/lite/source/stdafx.h Sat Mar 17 17:27:04 2012
@@ -43,5 +43,12 @@
#include <memory>
#include <stdexcept>
#include <cmath>
+#include <cassert>
+
+#pragma warning(push)
+#pragma warning(disable : 4005)
+#include <cstdint>
+#include <wincodec.h>
+#pragma warning(pop)

using namespace SlimMath; // I'm lazy

Reply all
Reply to author
Forward
0 new messages