Resync'd DDSTextureLoader, ScreenGrab, WICTextureLoader

This commit is contained in:
Chuck Walbourn 2020-06-03 01:04:35 -07:00
Родитель b78f18eec4
Коммит c5731f781c
6 изменённых файлов: 515 добавлений и 403 удалений

Просмотреть файл

@ -15,15 +15,15 @@
//--------------------------------------------------------------------------------------
#include "dxut.h"
#include "DDSTextureLoader.h"
#include <assert.h>
#include <algorithm>
#include <memory>
#if !defined(NO_D3D11_DEBUG_NAME) && ( defined(_DEBUG) || defined(PROFILE) )
#pragma comment(lib,"dxguid.lib")
#ifdef __clang__
#pragma clang diagnostic ignored "-Wcovered-switch-default"
#pragma clang diagnostic ignored "-Wswitch-enum"
#endif
using namespace DirectX;
@ -118,14 +118,14 @@ struct DDS_HEADER_DXT10
//--------------------------------------------------------------------------------------
namespace
{
struct handle_closer { void operator()(HANDLE h) { if (h) CloseHandle(h); } };
struct handle_closer { void operator()(HANDLE h) noexcept { if (h) CloseHandle(h); } };
typedef std::unique_ptr<void, handle_closer> ScopedHandle;
using ScopedHandle = std::unique_ptr<void, handle_closer>;
inline HANDLE safe_handle( HANDLE h ) { return (h == INVALID_HANDLE_VALUE) ? nullptr : h; }
inline HANDLE safe_handle( HANDLE h ) noexcept { return (h == INVALID_HANDLE_VALUE) ? nullptr : h; }
template<UINT TNameLength>
inline void SetDebugObjectName(_In_ ID3D11DeviceChild* resource, _In_ const char (&name)[TNameLength])
inline void SetDebugObjectName(_In_ ID3D11DeviceChild* resource, _In_ const char (&name)[TNameLength]) noexcept
{
#if defined(_DEBUG) || defined(PROFILE)
resource->SetPrivateData(WKPDID_D3DDebugObjectName, TNameLength - 1, name);
@ -141,7 +141,7 @@ namespace
size_t ddsDataSize,
const DDS_HEADER** header,
const uint8_t** bitData,
size_t* bitSize)
size_t* bitSize) noexcept
{
if (!header || !bitData || !bitSize)
{
@ -206,7 +206,7 @@ namespace
std::unique_ptr<uint8_t[]>& ddsData,
const DDS_HEADER** header,
const uint8_t** bitData,
size_t* bitSize)
size_t* bitSize) noexcept
{
if (!header || !bitData || !bitSize)
{
@ -322,7 +322,7 @@ namespace
//--------------------------------------------------------------------------------------
// Return the BPP for a particular format
//--------------------------------------------------------------------------------------
size_t BitsPerPixel(_In_ DXGI_FORMAT fmt)
size_t BitsPerPixel(_In_ DXGI_FORMAT fmt) noexcept
{
switch (fmt)
{
@ -478,7 +478,7 @@ namespace
_In_ DXGI_FORMAT fmt,
size_t* outNumBytes,
_Out_opt_ size_t* outRowBytes,
_Out_opt_ size_t* outNumRows)
_Out_opt_ size_t* outNumRows) noexcept
{
uint64_t numBytes = 0;
uint64_t rowBytes = 0;
@ -621,7 +621,7 @@ namespace
//--------------------------------------------------------------------------------------
#define ISBITMASK( r,g,b,a ) ( ddpf.RBitMask == r && ddpf.GBitMask == g && ddpf.BBitMask == b && ddpf.ABitMask == a )
DXGI_FORMAT GetDXGIFormat(const DDS_PIXELFORMAT& ddpf)
DXGI_FORMAT GetDXGIFormat(const DDS_PIXELFORMAT& ddpf) noexcept
{
if (ddpf.flags & DDS_RGB)
{
@ -640,12 +640,12 @@ namespace
return DXGI_FORMAT_B8G8R8A8_UNORM;
}
if (ISBITMASK(0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000))
if (ISBITMASK(0x00ff0000, 0x0000ff00, 0x000000ff, 0))
{
return DXGI_FORMAT_B8G8R8X8_UNORM;
}
// No DXGI format maps to ISBITMASK(0x000000ff,0x0000ff00,0x00ff0000,0x00000000) aka D3DFMT_X8B8G8R8
// No DXGI format maps to ISBITMASK(0x000000ff,0x0000ff00,0x00ff0000,0) 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 assume
@ -661,12 +661,12 @@ namespace
// No DXGI format maps to ISBITMASK(0x000003ff,0x000ffc00,0x3ff00000,0xc0000000) aka D3DFMT_A2R10G10B10
if (ISBITMASK(0x0000ffff, 0xffff0000, 0x00000000, 0x00000000))
if (ISBITMASK(0x0000ffff, 0xffff0000, 0, 0))
{
return DXGI_FORMAT_R16G16_UNORM;
}
if (ISBITMASK(0xffffffff, 0x00000000, 0x00000000, 0x00000000))
if (ISBITMASK(0xffffffff, 0, 0, 0))
{
// Only 32-bit color channel format in D3D9 was R32F
return DXGI_FORMAT_R32_FLOAT; // D3DX writes this out as a FourCC of 114
@ -682,19 +682,19 @@ namespace
{
return DXGI_FORMAT_B5G5R5A1_UNORM;
}
if (ISBITMASK(0xf800, 0x07e0, 0x001f, 0x0000))
if (ISBITMASK(0xf800, 0x07e0, 0x001f, 0))
{
return DXGI_FORMAT_B5G6R5_UNORM;
}
// No DXGI format maps to ISBITMASK(0x7c00,0x03e0,0x001f,0x0000) aka D3DFMT_X1R5G5B5
// No DXGI format maps to ISBITMASK(0x7c00,0x03e0,0x001f,0) aka D3DFMT_X1R5G5B5
if (ISBITMASK(0x0f00, 0x00f0, 0x000f, 0xf000))
{
return DXGI_FORMAT_B4G4R4A4_UNORM;
}
// No DXGI format maps to ISBITMASK(0x0f00,0x00f0,0x000f,0x0000) aka D3DFMT_X4R4G4B4
// No DXGI format maps to ISBITMASK(0x0f00,0x00f0,0x000f,0) aka D3DFMT_X4R4G4B4
// No 3:3:2, 3:3:2:8, or paletted DXGI formats aka D3DFMT_A8R3G3B2, D3DFMT_R3G3B2, D3DFMT_P8, D3DFMT_A8P8, etc.
break;
@ -704,14 +704,14 @@ namespace
{
if (8 == ddpf.RGBBitCount)
{
if (ISBITMASK(0x000000ff, 0x00000000, 0x00000000, 0x00000000))
if (ISBITMASK(0xff, 0, 0, 0))
{
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 (ISBITMASK(0x000000ff, 0x00000000, 0x00000000, 0x0000ff00))
if (ISBITMASK(0x00ff, 0, 0, 0xff00))
{
return DXGI_FORMAT_R8G8_UNORM; // Some DDS writers assume the bitcount should be 8 instead of 16
}
@ -719,11 +719,11 @@ namespace
if (16 == ddpf.RGBBitCount)
{
if (ISBITMASK(0x0000ffff, 0x00000000, 0x00000000, 0x00000000))
if (ISBITMASK(0xffff, 0, 0, 0))
{
return DXGI_FORMAT_R16_UNORM; // D3DX10/11 writes this out as DX10 extension
}
if (ISBITMASK(0x000000ff, 0x00000000, 0x00000000, 0x0000ff00))
if (ISBITMASK(0x00ff, 0, 0, 0xff00))
{
return DXGI_FORMAT_R8G8_UNORM; // D3DX10/11 writes this out as DX10 extension
}
@ -740,7 +740,7 @@ namespace
{
if (16 == ddpf.RGBBitCount)
{
if (ISBITMASK(0x00ff, 0xff00, 0x0000, 0x0000))
if (ISBITMASK(0x00ff, 0xff00, 0, 0))
{
return DXGI_FORMAT_R8G8_SNORM; // D3DX10/11 writes this out as DX10 extension
}
@ -752,13 +752,15 @@ namespace
{
return DXGI_FORMAT_R8G8B8A8_SNORM; // D3DX10/11 writes this out as DX10 extension
}
if (ISBITMASK(0x0000ffff, 0xffff0000, 0x00000000, 0x00000000))
if (ISBITMASK(0x0000ffff, 0xffff0000, 0, 0))
{
return DXGI_FORMAT_R16G16_SNORM; // D3DX10/11 writes this out as DX10 extension
}
// No DXGI format maps to ISBITMASK(0x3ff00000, 0x000ffc00, 0x000003ff, 0xc0000000) aka D3DFMT_A2W10V10U10
}
// No DXGI format maps to DDPF_BUMPLUMINANCE aka D3DFMT_L6V5U5, D3DFMT_X8L8V8U8
}
else if (ddpf.flags & DDS_FOURCC)
{
@ -854,15 +856,19 @@ namespace
case 116: // D3DFMT_A32B32G32R32F
return DXGI_FORMAT_R32G32B32A32_FLOAT;
// No DXGI format maps to D3DFMT_CxV8U8
}
}
return DXGI_FORMAT_UNKNOWN;
}
#undef ISBITMASK
//--------------------------------------------------------------------------------------
DXGI_FORMAT MakeSRGB(_In_ DXGI_FORMAT format)
DXGI_FORMAT MakeSRGB(_In_ DXGI_FORMAT format) noexcept
{
switch (format)
{
@ -908,7 +914,7 @@ namespace
_Out_ size_t& theight,
_Out_ size_t& tdepth,
_Out_ size_t& skipMip,
_Out_writes_(mipCount*arraySize) D3D11_SUBRESOURCE_DATA* initData)
_Out_writes_(mipCount*arraySize) D3D11_SUBRESOURCE_DATA* initData) noexcept
{
if (!bitData || !initData)
{
@ -1009,7 +1015,7 @@ namespace
_In_ bool isCubeMap,
_In_reads_opt_(mipCount*arraySize) D3D11_SUBRESOURCE_DATA* initData,
_Outptr_opt_ ID3D11Resource** texture,
_Outptr_opt_ ID3D11ShaderResourceView** textureView)
_Outptr_opt_ ID3D11ShaderResourceView** textureView) noexcept
{
if (!d3dDevice)
return E_POINTER;
@ -1239,7 +1245,7 @@ namespace
_In_ unsigned int miscFlags,
_In_ bool forceSRGB,
_Outptr_opt_ ID3D11Resource** texture,
_Outptr_opt_ ID3D11ShaderResourceView** textureView)
_Outptr_opt_ ID3D11ShaderResourceView** textureView) noexcept
{
HRESULT hr = S_OK;
@ -1554,26 +1560,26 @@ namespace
case D3D_FEATURE_LEVEL_9_2:
if (isCubeMap)
{
maxsize = 512 /*D3D_FL9_1_REQ_TEXTURECUBE_DIMENSION*/;
maxsize = 512u /*D3D_FL9_1_REQ_TEXTURECUBE_DIMENSION*/;
}
else
{
maxsize = (resDim == D3D11_RESOURCE_DIMENSION_TEXTURE3D)
? 256 /*D3D_FL9_1_REQ_TEXTURE3D_U_V_OR_W_DIMENSION*/
: 2048 /*D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION*/;
? 256u /*D3D_FL9_1_REQ_TEXTURE3D_U_V_OR_W_DIMENSION*/
: 2048u /*D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION*/;
}
break;
case D3D_FEATURE_LEVEL_9_3:
maxsize = (resDim == D3D11_RESOURCE_DIMENSION_TEXTURE3D)
? 256 /*D3D_FL9_1_REQ_TEXTURE3D_U_V_OR_W_DIMENSION*/
: 4096 /*D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION*/;
? 256u /*D3D_FL9_1_REQ_TEXTURE3D_U_V_OR_W_DIMENSION*/
: 4096u /*D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION*/;
break;
default: // D3D_FEATURE_LEVEL_10_0 & D3D_FEATURE_LEVEL_10_1
maxsize = (resDim == D3D11_RESOURCE_DIMENSION_TEXTURE3D)
? 2048 /*D3D10_REQ_TEXTURE3D_U_V_OR_W_DIMENSION*/
: 8192 /*D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION*/;
? 2048u /*D3D10_REQ_TEXTURE3D_U_V_OR_W_DIMENSION*/
: 8192u /*D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION*/;
break;
}
@ -1599,7 +1605,7 @@ namespace
//--------------------------------------------------------------------------------------
DDS_ALPHA_MODE GetAlphaMode(_In_ const DDS_HEADER* header)
DDS_ALPHA_MODE GetAlphaMode(_In_ const DDS_HEADER* header) noexcept
{
if (header->ddspf.flags & DDS_FOURCC)
{
@ -1634,7 +1640,7 @@ namespace
void SetDebugTextureInfo(
_In_z_ const wchar_t* fileName,
_In_opt_ ID3D11Resource** texture,
_In_opt_ ID3D11ShaderResourceView** textureView)
_In_opt_ ID3D11ShaderResourceView** textureView) noexcept
{
#if !defined(NO_D3D11_DEBUG_NAME) && ( defined(_DEBUG) || defined(PROFILE) )
if (texture || textureView)
@ -1695,7 +1701,7 @@ HRESULT DirectX::CreateDDSTextureFromMemory(
ID3D11Resource** texture,
ID3D11ShaderResourceView** textureView,
size_t maxsize,
DDS_ALPHA_MODE* alphaMode)
DDS_ALPHA_MODE* alphaMode) noexcept
{
return CreateDDSTextureFromMemoryEx(d3dDevice, nullptr,
ddsData, ddsDataSize,
@ -1714,7 +1720,7 @@ HRESULT DirectX::CreateDDSTextureFromMemory(
ID3D11Resource** texture,
ID3D11ShaderResourceView** textureView,
size_t maxsize,
DDS_ALPHA_MODE* alphaMode)
DDS_ALPHA_MODE* alphaMode) noexcept
{
return CreateDDSTextureFromMemoryEx(d3dDevice, d3dContext,
ddsData, ddsDataSize,
@ -1737,7 +1743,7 @@ HRESULT DirectX::CreateDDSTextureFromMemoryEx(
bool forceSRGB,
ID3D11Resource** texture,
ID3D11ShaderResourceView** textureView,
DDS_ALPHA_MODE* alphaMode)
DDS_ALPHA_MODE* alphaMode) noexcept
{
return CreateDDSTextureFromMemoryEx(d3dDevice, nullptr,
ddsData, ddsDataSize,
@ -1761,7 +1767,7 @@ HRESULT DirectX::CreateDDSTextureFromMemoryEx(
bool forceSRGB,
ID3D11Resource** texture,
ID3D11ShaderResourceView** textureView,
DDS_ALPHA_MODE* alphaMode)
DDS_ALPHA_MODE* alphaMode) noexcept
{
if (texture)
{
@ -1834,7 +1840,7 @@ HRESULT DirectX::CreateDDSTextureFromFile(
ID3D11Resource** texture,
ID3D11ShaderResourceView** textureView,
size_t maxsize,
DDS_ALPHA_MODE* alphaMode)
DDS_ALPHA_MODE* alphaMode) noexcept
{
return CreateDDSTextureFromFileEx(d3dDevice, nullptr,
fileName, maxsize,
@ -1851,7 +1857,7 @@ HRESULT DirectX::CreateDDSTextureFromFile(
ID3D11Resource** texture,
ID3D11ShaderResourceView** textureView,
size_t maxsize,
DDS_ALPHA_MODE* alphaMode)
DDS_ALPHA_MODE* alphaMode) noexcept
{
return CreateDDSTextureFromFileEx(d3dDevice, d3dContext,
fileName,
@ -1873,7 +1879,7 @@ HRESULT DirectX::CreateDDSTextureFromFileEx(
bool forceSRGB,
ID3D11Resource** texture,
ID3D11ShaderResourceView** textureView,
DDS_ALPHA_MODE* alphaMode)
DDS_ALPHA_MODE* alphaMode) noexcept
{
return CreateDDSTextureFromFileEx(d3dDevice, nullptr,
fileName,
@ -1896,7 +1902,7 @@ HRESULT DirectX::CreateDDSTextureFromFileEx(
bool forceSRGB,
ID3D11Resource** texture,
ID3D11ShaderResourceView** textureView,
DDS_ALPHA_MODE* alphaMode)
DDS_ALPHA_MODE* alphaMode) noexcept
{
if (texture)
{

Просмотреть файл

@ -1,5 +1,5 @@
//--------------------------------------------------------------------------------------
// File: DDSTextureLoader.h
// File: DDSTextureLoader11.h
//
// Functions for loading a DDS texture and creating a Direct3D runtime resource for it
//
@ -17,12 +17,15 @@
#pragma once
#include <d3d11_1.h>
#include <stdint.h>
#include <cstdint>
namespace DirectX
{
enum DDS_ALPHA_MODE
#ifndef DDS_ALPHA_MODE_DEFINED
#define DDS_ALPHA_MODE_DEFINED
enum DDS_ALPHA_MODE : uint32_t
{
DDS_ALPHA_MODE_UNKNOWN = 0,
DDS_ALPHA_MODE_STRAIGHT = 1,
@ -30,6 +33,7 @@ namespace DirectX
DDS_ALPHA_MODE_OPAQUE = 3,
DDS_ALPHA_MODE_CUSTOM = 4,
};
#endif
// Standard version
HRESULT CreateDDSTextureFromMemory(
@ -39,7 +43,7 @@ namespace DirectX
_Outptr_opt_ ID3D11Resource** texture,
_Outptr_opt_ ID3D11ShaderResourceView** textureView,
_In_ size_t maxsize = 0,
_Out_opt_ DDS_ALPHA_MODE* alphaMode = nullptr);
_Out_opt_ DDS_ALPHA_MODE* alphaMode = nullptr) noexcept;
HRESULT CreateDDSTextureFromFile(
_In_ ID3D11Device* d3dDevice,
@ -47,7 +51,7 @@ namespace DirectX
_Outptr_opt_ ID3D11Resource** texture,
_Outptr_opt_ ID3D11ShaderResourceView** textureView,
_In_ size_t maxsize = 0,
_Out_opt_ DDS_ALPHA_MODE* alphaMode = nullptr);
_Out_opt_ DDS_ALPHA_MODE* alphaMode = nullptr) noexcept;
// Standard version with optional auto-gen mipmap support
HRESULT CreateDDSTextureFromMemory(
@ -58,7 +62,7 @@ namespace DirectX
_Outptr_opt_ ID3D11Resource** texture,
_Outptr_opt_ ID3D11ShaderResourceView** textureView,
_In_ size_t maxsize = 0,
_Out_opt_ DDS_ALPHA_MODE* alphaMode = nullptr);
_Out_opt_ DDS_ALPHA_MODE* alphaMode = nullptr) noexcept;
HRESULT CreateDDSTextureFromFile(
_In_ ID3D11Device* d3dDevice,
@ -67,7 +71,7 @@ namespace DirectX
_Outptr_opt_ ID3D11Resource** texture,
_Outptr_opt_ ID3D11ShaderResourceView** textureView,
_In_ size_t maxsize = 0,
_Out_opt_ DDS_ALPHA_MODE* alphaMode = nullptr);
_Out_opt_ DDS_ALPHA_MODE* alphaMode = nullptr) noexcept;
// Extended version
HRESULT CreateDDSTextureFromMemoryEx(
@ -82,7 +86,7 @@ namespace DirectX
_In_ bool forceSRGB,
_Outptr_opt_ ID3D11Resource** texture,
_Outptr_opt_ ID3D11ShaderResourceView** textureView,
_Out_opt_ DDS_ALPHA_MODE* alphaMode = nullptr);
_Out_opt_ DDS_ALPHA_MODE* alphaMode = nullptr) noexcept;
HRESULT CreateDDSTextureFromFileEx(
_In_ ID3D11Device* d3dDevice,
@ -95,7 +99,7 @@ namespace DirectX
_In_ bool forceSRGB,
_Outptr_opt_ ID3D11Resource** texture,
_Outptr_opt_ ID3D11ShaderResourceView** textureView,
_Out_opt_ DDS_ALPHA_MODE* alphaMode = nullptr);
_Out_opt_ DDS_ALPHA_MODE* alphaMode = nullptr) noexcept;
// Extended version with optional auto-gen mipmap support
HRESULT CreateDDSTextureFromMemoryEx(
@ -111,7 +115,7 @@ namespace DirectX
_In_ bool forceSRGB,
_Outptr_opt_ ID3D11Resource** texture,
_Outptr_opt_ ID3D11ShaderResourceView** textureView,
_Out_opt_ DDS_ALPHA_MODE* alphaMode = nullptr);
_Out_opt_ DDS_ALPHA_MODE* alphaMode = nullptr) noexcept;
HRESULT CreateDDSTextureFromFileEx(
_In_ ID3D11Device* d3dDevice,
@ -125,5 +129,5 @@ namespace DirectX
_In_ bool forceSRGB,
_Outptr_opt_ ID3D11Resource** texture,
_Outptr_opt_ ID3D11ShaderResourceView** textureView,
_Out_opt_ DDS_ALPHA_MODE* alphaMode = nullptr);
}
_Out_opt_ DDS_ALPHA_MODE* alphaMode = nullptr) noexcept;
}

Просмотреть файл

@ -2,7 +2,7 @@
// File: ScreenGrab.cpp
//
// Function for capturing a 2D texture and saving it to a file (aka a 'screenshot'
// when used on a Direct3D 11 Render Target).
// when used on a Direct3D Render Target).
//
// Note these functions are useful as a light-weight runtime screen grabber. For
// full-featured texture capture, DDS writer, and texture processing pipeline,
@ -25,15 +25,18 @@
#include "ScreenGrab.h"
#include <dxgiformat.h>
#include <assert.h>
#include <algorithm>
#include <memory>
#include <wincodec.h>
#include <wrl\client.h>
#include <algorithm>
#include <memory>
#ifdef __clang__
#pragma clang diagnostic ignored "-Wcovered-switch-default"
#pragma clang diagnostic ignored "-Wswitch-enum"
#endif
using Microsoft::WRL::ComPtr;
@ -84,7 +87,7 @@ namespace
#define DDS_SURFACE_FLAGS_TEXTURE 0x00001000 // DDSCAPS_TEXTURE
typedef struct
struct DDS_HEADER
{
uint32_t size;
uint32_t flags;
@ -100,108 +103,108 @@ namespace
uint32_t caps3;
uint32_t caps4;
uint32_t reserved2;
} DDS_HEADER;
};
typedef struct
struct DDS_HEADER_DXT10
{
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)
const DDS_PIXELFORMAT DDSPF_DXT1 =
{ sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','T','1'), 0, 0, 0, 0, 0 };
{ sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','T','1'), 0, 0, 0, 0, 0 };
const DDS_PIXELFORMAT DDSPF_DXT3 =
{ sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','T','3'), 0, 0, 0, 0, 0 };
{ sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','T','3'), 0, 0, 0, 0, 0 };
const DDS_PIXELFORMAT DDSPF_DXT5 =
{ sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','T','5'), 0, 0, 0, 0, 0 };
{ sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','T','5'), 0, 0, 0, 0, 0 };
const DDS_PIXELFORMAT DDSPF_BC4_UNORM =
{ sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('B','C','4','U'), 0, 0, 0, 0, 0 };
{ sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('B','C','4','U'), 0, 0, 0, 0, 0 };
const DDS_PIXELFORMAT DDSPF_BC4_SNORM =
{ sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('B','C','4','S'), 0, 0, 0, 0, 0 };
{ sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('B','C','4','S'), 0, 0, 0, 0, 0 };
const DDS_PIXELFORMAT DDSPF_BC5_UNORM =
{ sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('B','C','5','U'), 0, 0, 0, 0, 0 };
{ sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('B','C','5','U'), 0, 0, 0, 0, 0 };
const DDS_PIXELFORMAT DDSPF_BC5_SNORM =
{ sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('B','C','5','S'), 0, 0, 0, 0, 0 };
{ sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('B','C','5','S'), 0, 0, 0, 0, 0 };
const DDS_PIXELFORMAT DDSPF_R8G8_B8G8 =
{ sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('R','G','B','G'), 0, 0, 0, 0, 0 };
{ sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('R','G','B','G'), 0, 0, 0, 0, 0 };
const DDS_PIXELFORMAT DDSPF_G8R8_G8B8 =
{ sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('G','R','G','B'), 0, 0, 0, 0, 0 };
{ sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('G','R','G','B'), 0, 0, 0, 0, 0 };
const DDS_PIXELFORMAT DDSPF_YUY2 =
{ sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('Y','U','Y','2'), 0, 0, 0, 0, 0 };
{ sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('Y','U','Y','2'), 0, 0, 0, 0, 0 };
const DDS_PIXELFORMAT DDSPF_A8R8G8B8 =
{ sizeof(DDS_PIXELFORMAT), DDS_RGBA, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 };
{ sizeof(DDS_PIXELFORMAT), DDS_RGBA, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 };
const DDS_PIXELFORMAT DDSPF_X8R8G8B8 =
{ sizeof(DDS_PIXELFORMAT), DDS_RGB, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000 };
{ sizeof(DDS_PIXELFORMAT), DDS_RGB, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0 };
const DDS_PIXELFORMAT DDSPF_A8B8G8R8 =
{ sizeof(DDS_PIXELFORMAT), DDS_RGBA, 0, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 };
{ sizeof(DDS_PIXELFORMAT), DDS_RGBA, 0, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 };
const DDS_PIXELFORMAT DDSPF_G16R16 =
{ sizeof(DDS_PIXELFORMAT), DDS_RGB, 0, 32, 0x0000ffff, 0xffff0000, 0x00000000, 0x00000000 };
{ sizeof(DDS_PIXELFORMAT), DDS_RGB, 0, 32, 0x0000ffff, 0xffff0000, 0, 0 };
const DDS_PIXELFORMAT DDSPF_R5G6B5 =
{ sizeof(DDS_PIXELFORMAT), DDS_RGB, 0, 16, 0x0000f800, 0x000007e0, 0x0000001f, 0x00000000 };
{ sizeof(DDS_PIXELFORMAT), DDS_RGB, 0, 16, 0xf800, 0x07e0, 0x001f, 0 };
const DDS_PIXELFORMAT DDSPF_A1R5G5B5 =
{ sizeof(DDS_PIXELFORMAT), DDS_RGBA, 0, 16, 0x00007c00, 0x000003e0, 0x0000001f, 0x00008000 };
{ sizeof(DDS_PIXELFORMAT), DDS_RGBA, 0, 16, 0x7c00, 0x03e0, 0x001f, 0x8000 };
const DDS_PIXELFORMAT DDSPF_A4R4G4B4 =
{ sizeof(DDS_PIXELFORMAT), DDS_RGBA, 0, 16, 0x00000f00, 0x000000f0, 0x0000000f, 0x0000f000 };
{ sizeof(DDS_PIXELFORMAT), DDS_RGBA, 0, 16, 0x0f00, 0x00f0, 0x000f, 0xf000 };
const DDS_PIXELFORMAT DDSPF_L8 =
{ sizeof(DDS_PIXELFORMAT), DDS_LUMINANCE, 0, 8, 0xff, 0x00, 0x00, 0x00 };
{ sizeof(DDS_PIXELFORMAT), DDS_LUMINANCE, 0, 8, 0xff, 0, 0, 0 };
const DDS_PIXELFORMAT DDSPF_L16 =
{ sizeof(DDS_PIXELFORMAT), DDS_LUMINANCE, 0, 16, 0xffff, 0x0000, 0x0000, 0x0000 };
{ sizeof(DDS_PIXELFORMAT), DDS_LUMINANCE, 0, 16, 0xffff, 0, 0, 0 };
const DDS_PIXELFORMAT DDSPF_A8L8 =
{ sizeof(DDS_PIXELFORMAT), DDS_LUMINANCEA, 0, 16, 0x00ff, 0x0000, 0x0000, 0xff00 };
{ sizeof(DDS_PIXELFORMAT), DDS_LUMINANCEA, 0, 16, 0x00ff, 0, 0, 0xff00 };
const DDS_PIXELFORMAT DDSPF_A8 =
{ sizeof(DDS_PIXELFORMAT), DDS_ALPHA, 0, 8, 0x00, 0x00, 0x00, 0xff };
{ sizeof(DDS_PIXELFORMAT), DDS_ALPHA, 0, 8, 0, 0, 0, 0xff };
const DDS_PIXELFORMAT DDSPF_V8U8 =
{ sizeof(DDS_PIXELFORMAT), DDS_BUMPDUDV, 0, 16, 0x00ff, 0xff00, 0x0000, 0x0000 };
const DDS_PIXELFORMAT DDSPF_V8U8 =
{ sizeof(DDS_PIXELFORMAT), DDS_BUMPDUDV, 0, 16, 0x00ff, 0xff00, 0, 0 };
const DDS_PIXELFORMAT DDSPF_Q8W8V8U8 =
{ sizeof(DDS_PIXELFORMAT), DDS_BUMPDUDV, 0, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 };
const DDS_PIXELFORMAT DDSPF_Q8W8V8U8 =
{ sizeof(DDS_PIXELFORMAT), DDS_BUMPDUDV, 0, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 };
const DDS_PIXELFORMAT DDSPF_V16U16 =
{ sizeof(DDS_PIXELFORMAT), DDS_BUMPDUDV, 0, 32, 0x0000ffff, 0xffff0000, 0x00000000, 0x00000000 };
const DDS_PIXELFORMAT DDSPF_V16U16 =
{ sizeof(DDS_PIXELFORMAT), DDS_BUMPDUDV, 0, 32, 0x0000ffff, 0xffff0000, 0, 0 };
// DXGI_FORMAT_R10G10B10A2_UNORM should be written using DX10 extension to avoid D3DX 10:10:10:2 reversal issue
// This indicates the DDS_HEADER_DXT10 extension is present (the format is in dxgiFormat)
const DDS_PIXELFORMAT DDSPF_DX10 =
{ sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','1','0'), 0, 0, 0, 0, 0 };
{ sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','1','0'), 0, 0, 0, 0, 0 };
//-----------------------------------------------------------------------------
struct handle_closer { void operator()(HANDLE h) { if (h) CloseHandle(h); } };
struct handle_closer { void operator()(HANDLE h) noexcept { if (h) CloseHandle(h); } };
typedef std::unique_ptr<void, handle_closer> ScopedHandle;
using ScopedHandle = std::unique_ptr<void, handle_closer>;
inline HANDLE safe_handle( HANDLE h ) { return (h == INVALID_HANDLE_VALUE) ? nullptr : h; }
inline HANDLE safe_handle(HANDLE h) noexcept { return (h == INVALID_HANDLE_VALUE) ? nullptr : h; }
class auto_delete_file
{
public:
auto_delete_file(HANDLE hFile) : m_handle(hFile) {}
auto_delete_file(HANDLE hFile) noexcept : m_handle(hFile) {}
~auto_delete_file()
{
if (m_handle)
@ -212,19 +215,22 @@ namespace
}
}
void clear() { m_handle = nullptr; }
auto_delete_file(const auto_delete_file&) = delete;
auto_delete_file& operator=(const auto_delete_file&) = delete;
auto_delete_file(const auto_delete_file&&) = delete;
auto_delete_file& operator=(const auto_delete_file&&) = delete;
void clear() noexcept { m_handle = nullptr; }
private:
HANDLE m_handle;
auto_delete_file(const auto_delete_file&) = delete;
auto_delete_file& operator=(const auto_delete_file&) = delete;
};
class auto_delete_file_wic
{
public:
auto_delete_file_wic(ComPtr<IWICStream>& hFile, const wchar_t* szFile) : m_filename(szFile), m_handle(hFile) {}
auto_delete_file_wic(ComPtr<IWICStream>& hFile, const wchar_t* szFile) noexcept : m_filename(szFile), m_handle(hFile) {}
~auto_delete_file_wic()
{
if (m_filename)
@ -234,22 +240,25 @@ namespace
}
}
void clear() { m_filename = nullptr; }
auto_delete_file_wic(const auto_delete_file_wic&) = delete;
auto_delete_file_wic& operator=(const auto_delete_file_wic&) = delete;
auto_delete_file_wic(const auto_delete_file_wic&&) = delete;
auto_delete_file_wic& operator=(const auto_delete_file_wic&&) = delete;
void clear() noexcept { m_filename = nullptr; }
private:
const wchar_t* m_filename;
ComPtr<IWICStream>& m_handle;
auto_delete_file_wic(const auto_delete_file_wic&) = delete;
auto_delete_file_wic& operator=(const auto_delete_file_wic&) = delete;
};
//--------------------------------------------------------------------------------------
// Return the BPP for a particular format
//--------------------------------------------------------------------------------------
size_t BitsPerPixel( _In_ DXGI_FORMAT fmt )
size_t BitsPerPixel(_In_ DXGI_FORMAT fmt) noexcept
{
switch( fmt )
switch (fmt)
{
case DXGI_FORMAT_R32G32B32A32_TYPELESS:
case DXGI_FORMAT_R32G32B32A32_FLOAT:
@ -397,9 +406,9 @@ namespace
//--------------------------------------------------------------------------------------
// Determines if the format is block compressed
//--------------------------------------------------------------------------------------
bool IsCompressed( _In_ DXGI_FORMAT fmt )
bool IsCompressed(_In_ DXGI_FORMAT fmt) noexcept
{
switch ( fmt )
switch (fmt)
{
case DXGI_FORMAT_BC1_TYPELESS:
case DXGI_FORMAT_BC1_UNORM:
@ -439,7 +448,7 @@ namespace
_In_ DXGI_FORMAT fmt,
_Out_opt_ size_t* outNumBytes,
_Out_opt_ size_t* outRowBytes,
_Out_opt_ size_t* outNumRows)
_Out_opt_ size_t* outNumRows) noexcept
{
uint64_t numBytes = 0;
uint64_t rowBytes = 0;
@ -580,10 +589,10 @@ namespace
//--------------------------------------------------------------------------------------
DXGI_FORMAT EnsureNotTypeless( DXGI_FORMAT fmt )
DXGI_FORMAT EnsureNotTypeless(DXGI_FORMAT fmt) noexcept
{
// Assumes UNORM or FLOAT; doesn't use UINT or SINT
switch( fmt )
switch (fmt)
{
case DXGI_FORMAT_R32G32B32A32_TYPELESS: return DXGI_FORMAT_R32G32B32A32_FLOAT;
case DXGI_FORMAT_R32G32B32_TYPELESS: return DXGI_FORMAT_R32G32B32_FLOAT;
@ -614,58 +623,58 @@ namespace
_In_ ID3D11DeviceContext* pContext,
_In_ ID3D11Resource* pSource,
D3D11_TEXTURE2D_DESC& desc,
ComPtr<ID3D11Texture2D>& pStaging )
ComPtr<ID3D11Texture2D>& pStaging) noexcept
{
if ( !pContext || !pSource )
if (!pContext || !pSource)
return E_INVALIDARG;
D3D11_RESOURCE_DIMENSION resType = D3D11_RESOURCE_DIMENSION_UNKNOWN;
pSource->GetType( &resType );
pSource->GetType(&resType);
if ( resType != D3D11_RESOURCE_DIMENSION_TEXTURE2D )
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
if (resType != D3D11_RESOURCE_DIMENSION_TEXTURE2D)
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
ComPtr<ID3D11Texture2D> pTexture;
HRESULT hr = pSource->QueryInterface(IID_ID3D11Texture2D, reinterpret_cast<void**>(pTexture.GetAddressOf()));
if ( FAILED(hr) )
if (FAILED(hr))
return hr;
assert( pTexture );
assert(pTexture);
pTexture->GetDesc( &desc );
pTexture->GetDesc(&desc);
ComPtr<ID3D11Device> d3dDevice;
pContext->GetDevice( d3dDevice.GetAddressOf() );
pContext->GetDevice(d3dDevice.GetAddressOf());
if ( desc.SampleDesc.Count > 1 )
if (desc.SampleDesc.Count > 1)
{
// MSAA content must be resolved before being copied to a staging texture
desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;
ComPtr<ID3D11Texture2D> pTemp;
hr = d3dDevice->CreateTexture2D( &desc, nullptr, pTemp.GetAddressOf() );
if ( FAILED(hr) )
hr = d3dDevice->CreateTexture2D(&desc, nullptr, pTemp.GetAddressOf());
if (FAILED(hr))
return hr;
assert( pTemp );
assert(pTemp);
DXGI_FORMAT fmt = EnsureNotTypeless( desc.Format );
DXGI_FORMAT fmt = EnsureNotTypeless(desc.Format);
UINT support = 0;
hr = d3dDevice->CheckFormatSupport( fmt, &support );
if ( FAILED(hr) )
hr = d3dDevice->CheckFormatSupport(fmt, &support);
if (FAILED(hr))
return hr;
if ( !(support & D3D11_FORMAT_SUPPORT_MULTISAMPLE_RESOLVE) )
if (!(support & D3D11_FORMAT_SUPPORT_MULTISAMPLE_RESOLVE))
return E_FAIL;
for( UINT item = 0; item < desc.ArraySize; ++item )
for (UINT item = 0; item < desc.ArraySize; ++item)
{
for( UINT level = 0; level < desc.MipLevels; ++level )
for (UINT level = 0; level < desc.MipLevels; ++level)
{
UINT index = D3D11CalcSubresource( level, item, desc.MipLevels );
pContext->ResolveSubresource( pTemp.Get(), index, pSource, index, fmt );
UINT index = D3D11CalcSubresource(level, item, desc.MipLevels);
pContext->ResolveSubresource(pTemp.Get(), index, pSource, index, fmt);
}
}
@ -675,14 +684,14 @@ namespace
desc.Usage = D3D11_USAGE_STAGING;
hr = d3dDevice->CreateTexture2D(&desc, nullptr, pStaging.ReleaseAndGetAddressOf());
if ( FAILED(hr) )
if (FAILED(hr))
return hr;
assert( pStaging );
assert(pStaging);
pContext->CopyResource( pStaging.Get(), pTemp.Get() );
pContext->CopyResource(pStaging.Get(), pTemp.Get());
}
else if ( (desc.Usage == D3D11_USAGE_STAGING) && (desc.CPUAccessFlags & D3D11_CPU_ACCESS_READ) )
else if ((desc.Usage == D3D11_USAGE_STAGING) && (desc.CPUAccessFlags & D3D11_CPU_ACCESS_READ))
{
// Handle case where the source is already a staging texture we can use directly
pStaging = pTexture;
@ -696,12 +705,12 @@ namespace
desc.Usage = D3D11_USAGE_STAGING;
hr = d3dDevice->CreateTexture2D(&desc, nullptr, pStaging.ReleaseAndGetAddressOf());
if ( FAILED(hr) )
if (FAILED(hr))
return hr;
assert( pStaging );
assert(pStaging);
pContext->CopyResource( pStaging.Get(), pSource );
pContext->CopyResource(pStaging.Get(), pSource);
}
return S_OK;
@ -710,49 +719,56 @@ namespace
//--------------------------------------------------------------------------------------
bool g_WIC2 = false;
IWICImagingFactory* _GetWIC()
BOOL WINAPI InitializeWICFactory(PINIT_ONCE, PVOID, PVOID* ifactory) noexcept
{
#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) || defined(_WIN7_PLATFORM_UPDATE)
HRESULT hr = CoCreateInstance(
CLSID_WICImagingFactory2,
nullptr,
CLSCTX_INPROC_SERVER,
__uuidof(IWICImagingFactory2),
ifactory
);
if (SUCCEEDED(hr))
{
// WIC2 is available on Windows 10, Windows 8.x, and Windows 7 SP1 with KB 2670838 installed
g_WIC2 = true;
return TRUE;
}
else
{
hr = CoCreateInstance(
CLSID_WICImagingFactory1,
nullptr,
CLSCTX_INPROC_SERVER,
__uuidof(IWICImagingFactory),
ifactory
);
return SUCCEEDED(hr) ? TRUE : FALSE;
}
#else
return SUCCEEDED(CoCreateInstance(
CLSID_WICImagingFactory,
nullptr,
CLSCTX_INPROC_SERVER,
__uuidof(IWICImagingFactory),
ifactory)) ? TRUE : FALSE;
#endif
}
IWICImagingFactory* _GetWIC() noexcept
{
static INIT_ONCE s_initOnce = INIT_ONCE_STATIC_INIT;
IWICImagingFactory* factory = nullptr;
InitOnceExecuteOnce(&s_initOnce,
[](PINIT_ONCE, PVOID, LPVOID *ifactory) -> BOOL
{
#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) || defined(_WIN7_PLATFORM_UPDATE)
HRESULT hr = CoCreateInstance(
CLSID_WICImagingFactory2,
nullptr,
CLSCTX_INPROC_SERVER,
__uuidof(IWICImagingFactory2),
ifactory
);
if ( SUCCEEDED(hr) )
{
// WIC2 is available on Windows 10, Windows 8.x, and Windows 7 SP1 with KB 2670838 installed
g_WIC2 = true;
return TRUE;
}
else
{
hr = CoCreateInstance(
CLSID_WICImagingFactory1,
nullptr,
CLSCTX_INPROC_SERVER,
__uuidof(IWICImagingFactory),
ifactory
);
return SUCCEEDED(hr) ? TRUE : FALSE;
}
#else
return SUCCEEDED( CoCreateInstance(
CLSID_WICImagingFactory,
nullptr,
CLSCTX_INPROC_SERVER,
__uuidof(IWICImagingFactory),
ifactory) ) ? TRUE : FALSE;
#endif
}, nullptr, reinterpret_cast<LPVOID*>(&factory));
if (!InitOnceExecuteOnce(&s_initOnce,
InitializeWICFactory,
nullptr,
reinterpret_cast<LPVOID*>(&factory)))
{
return nullptr;
}
return factory;
}
@ -764,38 +780,37 @@ _Use_decl_annotations_
HRESULT DirectX::SaveDDSTextureToFile(
ID3D11DeviceContext* pContext,
ID3D11Resource* pSource,
const wchar_t* fileName )
const wchar_t* fileName) noexcept
{
if ( !fileName )
if (!fileName)
return E_INVALIDARG;
D3D11_TEXTURE2D_DESC desc = {};
ComPtr<ID3D11Texture2D> pStaging;
HRESULT hr = CaptureTexture( pContext, pSource, desc, pStaging );
if ( FAILED(hr) )
HRESULT hr = CaptureTexture(pContext, pSource, desc, pStaging);
if (FAILED(hr))
return hr;
// Create file
#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8)
ScopedHandle hFile( safe_handle( CreateFile2( fileName, GENERIC_WRITE | DELETE, 0, CREATE_ALWAYS, nullptr ) ) );
ScopedHandle hFile(safe_handle(CreateFile2(fileName, GENERIC_WRITE | DELETE, 0, CREATE_ALWAYS, nullptr)));
#else
ScopedHandle hFile( safe_handle( CreateFileW( fileName, GENERIC_WRITE | DELETE, 0, nullptr, CREATE_ALWAYS, 0, nullptr ) ) );
ScopedHandle hFile(safe_handle(CreateFileW(fileName, GENERIC_WRITE | DELETE, 0, nullptr, CREATE_ALWAYS, 0, nullptr)));
#endif
if ( !hFile )
return HRESULT_FROM_WIN32( GetLastError() );
if (!hFile)
return HRESULT_FROM_WIN32(GetLastError());
auto_delete_file delonfail(hFile.get());
// Setup header
const size_t MAX_HEADER_SIZE = sizeof(uint32_t) + sizeof(DDS_HEADER) + sizeof(DDS_HEADER_DXT10);
uint8_t fileHeader[ MAX_HEADER_SIZE ];
uint8_t fileHeader[MAX_HEADER_SIZE] = {};
*reinterpret_cast<uint32_t*>(&fileHeader[0]) = DDS_MAGIC;
auto header = reinterpret_cast<DDS_HEADER*>( &fileHeader[0] + sizeof(uint32_t) );
auto header = reinterpret_cast<DDS_HEADER*>(&fileHeader[0] + sizeof(uint32_t));
size_t headerSize = sizeof(uint32_t) + sizeof(DDS_HEADER);
memset( header, 0, sizeof(DDS_HEADER) );
header->size = sizeof( DDS_HEADER );
header->size = sizeof(DDS_HEADER);
header->flags = DDS_HEADER_FLAGS_TEXTURE | DDS_HEADER_FLAGS_MIPMAP;
header->height = desc.Height;
header->width = desc.Width;
@ -804,32 +819,32 @@ HRESULT DirectX::SaveDDSTextureToFile(
// Try to use a legacy .DDS pixel format for better tools support, otherwise fallback to 'DX10' header extension
DDS_HEADER_DXT10* extHeader = nullptr;
switch( desc.Format )
switch (desc.Format)
{
case DXGI_FORMAT_R8G8B8A8_UNORM: memcpy_s( &header->ddspf, sizeof(header->ddspf), &DDSPF_A8B8G8R8, sizeof(DDS_PIXELFORMAT) ); break;
case DXGI_FORMAT_R16G16_UNORM: memcpy_s( &header->ddspf, sizeof(header->ddspf), &DDSPF_G16R16, sizeof(DDS_PIXELFORMAT) ); break;
case DXGI_FORMAT_R8G8_UNORM: memcpy_s( &header->ddspf, sizeof(header->ddspf), &DDSPF_A8L8, sizeof(DDS_PIXELFORMAT) ); break;
case DXGI_FORMAT_R16_UNORM: memcpy_s( &header->ddspf, sizeof(header->ddspf), &DDSPF_L16, sizeof(DDS_PIXELFORMAT) ); break;
case DXGI_FORMAT_R8_UNORM: memcpy_s( &header->ddspf, sizeof(header->ddspf), &DDSPF_L8, sizeof(DDS_PIXELFORMAT) ); break;
case DXGI_FORMAT_A8_UNORM: memcpy_s( &header->ddspf, sizeof(header->ddspf), &DDSPF_A8, sizeof(DDS_PIXELFORMAT) ); break;
case DXGI_FORMAT_R8G8_B8G8_UNORM: memcpy_s( &header->ddspf, sizeof(header->ddspf), &DDSPF_R8G8_B8G8, sizeof(DDS_PIXELFORMAT) ); break;
case DXGI_FORMAT_G8R8_G8B8_UNORM: memcpy_s( &header->ddspf, sizeof(header->ddspf), &DDSPF_G8R8_G8B8, sizeof(DDS_PIXELFORMAT) ); break;
case DXGI_FORMAT_BC1_UNORM: memcpy_s( &header->ddspf, sizeof(header->ddspf), &DDSPF_DXT1, sizeof(DDS_PIXELFORMAT) ); break;
case DXGI_FORMAT_BC2_UNORM: memcpy_s( &header->ddspf, sizeof(header->ddspf), &DDSPF_DXT3, sizeof(DDS_PIXELFORMAT) ); break;
case DXGI_FORMAT_BC3_UNORM: memcpy_s( &header->ddspf, sizeof(header->ddspf), &DDSPF_DXT5, sizeof(DDS_PIXELFORMAT) ); break;
case DXGI_FORMAT_BC4_UNORM: memcpy_s( &header->ddspf, sizeof(header->ddspf), &DDSPF_BC4_UNORM, sizeof(DDS_PIXELFORMAT) ); break;
case DXGI_FORMAT_BC4_SNORM: memcpy_s( &header->ddspf, sizeof(header->ddspf), &DDSPF_BC4_SNORM, sizeof(DDS_PIXELFORMAT) ); break;
case DXGI_FORMAT_BC5_UNORM: memcpy_s( &header->ddspf, sizeof(header->ddspf), &DDSPF_BC5_UNORM, sizeof(DDS_PIXELFORMAT) ); break;
case DXGI_FORMAT_BC5_SNORM: memcpy_s( &header->ddspf, sizeof(header->ddspf), &DDSPF_BC5_SNORM, sizeof(DDS_PIXELFORMAT) ); break;
case DXGI_FORMAT_B5G6R5_UNORM: memcpy_s( &header->ddspf, sizeof(header->ddspf), &DDSPF_R5G6B5, sizeof(DDS_PIXELFORMAT) ); break;
case DXGI_FORMAT_B5G5R5A1_UNORM: memcpy_s( &header->ddspf, sizeof(header->ddspf), &DDSPF_A1R5G5B5, sizeof(DDS_PIXELFORMAT) ); break;
case DXGI_FORMAT_R8G8_SNORM: memcpy_s( &header->ddspf, sizeof(header->ddspf), &DDSPF_V8U8, sizeof(DDS_PIXELFORMAT) ); break;
case DXGI_FORMAT_R8G8B8A8_SNORM: memcpy_s( &header->ddspf, sizeof(header->ddspf), &DDSPF_Q8W8V8U8, sizeof(DDS_PIXELFORMAT) ); break;
case DXGI_FORMAT_R16G16_SNORM: memcpy_s( &header->ddspf, sizeof(header->ddspf), &DDSPF_V16U16, sizeof(DDS_PIXELFORMAT) ); break;
case DXGI_FORMAT_B8G8R8A8_UNORM: memcpy_s( &header->ddspf, sizeof(header->ddspf), &DDSPF_A8R8G8B8, sizeof(DDS_PIXELFORMAT) ); break; // DXGI 1.1
case DXGI_FORMAT_B8G8R8X8_UNORM: memcpy_s( &header->ddspf, sizeof(header->ddspf), &DDSPF_X8R8G8B8, sizeof(DDS_PIXELFORMAT) ); break; // DXGI 1.1
case DXGI_FORMAT_YUY2: memcpy_s( &header->ddspf, sizeof(header->ddspf), &DDSPF_YUY2, sizeof(DDS_PIXELFORMAT) ); break; // DXGI 1.2
case DXGI_FORMAT_B4G4R4A4_UNORM: memcpy_s( &header->ddspf, sizeof(header->ddspf), &DDSPF_A4R4G4B4, sizeof(DDS_PIXELFORMAT) ); break; // DXGI 1.2
case DXGI_FORMAT_R8G8B8A8_UNORM: memcpy_s(&header->ddspf, sizeof(header->ddspf), &DDSPF_A8B8G8R8, sizeof(DDS_PIXELFORMAT)); break;
case DXGI_FORMAT_R16G16_UNORM: memcpy_s(&header->ddspf, sizeof(header->ddspf), &DDSPF_G16R16, sizeof(DDS_PIXELFORMAT)); break;
case DXGI_FORMAT_R8G8_UNORM: memcpy_s(&header->ddspf, sizeof(header->ddspf), &DDSPF_A8L8, sizeof(DDS_PIXELFORMAT)); break;
case DXGI_FORMAT_R16_UNORM: memcpy_s(&header->ddspf, sizeof(header->ddspf), &DDSPF_L16, sizeof(DDS_PIXELFORMAT)); break;
case DXGI_FORMAT_R8_UNORM: memcpy_s(&header->ddspf, sizeof(header->ddspf), &DDSPF_L8, sizeof(DDS_PIXELFORMAT)); break;
case DXGI_FORMAT_A8_UNORM: memcpy_s(&header->ddspf, sizeof(header->ddspf), &DDSPF_A8, sizeof(DDS_PIXELFORMAT)); break;
case DXGI_FORMAT_R8G8_B8G8_UNORM: memcpy_s(&header->ddspf, sizeof(header->ddspf), &DDSPF_R8G8_B8G8, sizeof(DDS_PIXELFORMAT)); break;
case DXGI_FORMAT_G8R8_G8B8_UNORM: memcpy_s(&header->ddspf, sizeof(header->ddspf), &DDSPF_G8R8_G8B8, sizeof(DDS_PIXELFORMAT)); break;
case DXGI_FORMAT_BC1_UNORM: memcpy_s(&header->ddspf, sizeof(header->ddspf), &DDSPF_DXT1, sizeof(DDS_PIXELFORMAT)); break;
case DXGI_FORMAT_BC2_UNORM: memcpy_s(&header->ddspf, sizeof(header->ddspf), &DDSPF_DXT3, sizeof(DDS_PIXELFORMAT)); break;
case DXGI_FORMAT_BC3_UNORM: memcpy_s(&header->ddspf, sizeof(header->ddspf), &DDSPF_DXT5, sizeof(DDS_PIXELFORMAT)); break;
case DXGI_FORMAT_BC4_UNORM: memcpy_s(&header->ddspf, sizeof(header->ddspf), &DDSPF_BC4_UNORM, sizeof(DDS_PIXELFORMAT)); break;
case DXGI_FORMAT_BC4_SNORM: memcpy_s(&header->ddspf, sizeof(header->ddspf), &DDSPF_BC4_SNORM, sizeof(DDS_PIXELFORMAT)); break;
case DXGI_FORMAT_BC5_UNORM: memcpy_s(&header->ddspf, sizeof(header->ddspf), &DDSPF_BC5_UNORM, sizeof(DDS_PIXELFORMAT)); break;
case DXGI_FORMAT_BC5_SNORM: memcpy_s(&header->ddspf, sizeof(header->ddspf), &DDSPF_BC5_SNORM, sizeof(DDS_PIXELFORMAT)); break;
case DXGI_FORMAT_B5G6R5_UNORM: memcpy_s(&header->ddspf, sizeof(header->ddspf), &DDSPF_R5G6B5, sizeof(DDS_PIXELFORMAT)); break;
case DXGI_FORMAT_B5G5R5A1_UNORM: memcpy_s(&header->ddspf, sizeof(header->ddspf), &DDSPF_A1R5G5B5, sizeof(DDS_PIXELFORMAT)); break;
case DXGI_FORMAT_R8G8_SNORM: memcpy_s(&header->ddspf, sizeof(header->ddspf), &DDSPF_V8U8, sizeof(DDS_PIXELFORMAT)); break;
case DXGI_FORMAT_R8G8B8A8_SNORM: memcpy_s(&header->ddspf, sizeof(header->ddspf), &DDSPF_Q8W8V8U8, sizeof(DDS_PIXELFORMAT)); break;
case DXGI_FORMAT_R16G16_SNORM: memcpy_s(&header->ddspf, sizeof(header->ddspf), &DDSPF_V16U16, sizeof(DDS_PIXELFORMAT)); break;
case DXGI_FORMAT_B8G8R8A8_UNORM: memcpy_s(&header->ddspf, sizeof(header->ddspf), &DDSPF_A8R8G8B8, sizeof(DDS_PIXELFORMAT)); break; // DXGI 1.1
case DXGI_FORMAT_B8G8R8X8_UNORM: memcpy_s(&header->ddspf, sizeof(header->ddspf), &DDSPF_X8R8G8B8, sizeof(DDS_PIXELFORMAT)); break; // DXGI 1.1
case DXGI_FORMAT_YUY2: memcpy_s(&header->ddspf, sizeof(header->ddspf), &DDSPF_YUY2, sizeof(DDS_PIXELFORMAT)); break; // DXGI 1.2
case DXGI_FORMAT_B4G4R4A4_UNORM: memcpy_s(&header->ddspf, sizeof(header->ddspf), &DDSPF_A4R4G4B4, sizeof(DDS_PIXELFORMAT)); break; // DXGI 1.2
// Legacy D3DX formats using D3DFMT enum value as FourCC
case DXGI_FORMAT_R32G32B32A32_FLOAT: header->ddspf.size = sizeof(DDS_PIXELFORMAT); header->ddspf.flags = DDS_FOURCC; header->ddspf.fourCC = 116; break; // D3DFMT_A32B32G32R32F
@ -845,14 +860,13 @@ HRESULT DirectX::SaveDDSTextureToFile(
case DXGI_FORMAT_IA44:
case DXGI_FORMAT_P8:
case DXGI_FORMAT_A8P8:
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
default:
memcpy_s( &header->ddspf, sizeof(header->ddspf), &DDSPF_DX10, sizeof(DDS_PIXELFORMAT) );
memcpy_s(&header->ddspf, sizeof(header->ddspf), &DDSPF_DX10, sizeof(DDS_PIXELFORMAT));
headerSize += sizeof(DDS_HEADER_DXT10);
extHeader = reinterpret_cast<DDS_HEADER_DXT10*>( fileHeader + sizeof(uint32_t) + sizeof(DDS_HEADER) );
memset( extHeader, 0, sizeof(DDS_HEADER_DXT10) );
extHeader = reinterpret_cast<DDS_HEADER_DXT10*>(fileHeader + sizeof(uint32_t) + sizeof(DDS_HEADER));
extHeader->dxgiFormat = desc.Format;
extHeader->resourceDimension = D3D11_RESOURCE_DIMENSION_TEXTURE2D;
extHeader->arraySize = 1;
@ -860,65 +874,65 @@ HRESULT DirectX::SaveDDSTextureToFile(
}
size_t rowPitch, slicePitch, rowCount;
hr = GetSurfaceInfo( desc.Width, desc.Height, desc.Format, &slicePitch, &rowPitch, &rowCount );
hr = GetSurfaceInfo(desc.Width, desc.Height, desc.Format, &slicePitch, &rowPitch, &rowCount);
if (FAILED(hr))
return hr;
if (rowPitch > UINT32_MAX || slicePitch > UINT32_MAX)
return HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW);
if ( IsCompressed( desc.Format ) )
if (IsCompressed(desc.Format))
{
header->flags |= DDS_HEADER_FLAGS_LINEARSIZE;
header->pitchOrLinearSize = static_cast<uint32_t>( slicePitch );
header->pitchOrLinearSize = static_cast<uint32_t>(slicePitch);
}
else
{
header->flags |= DDS_HEADER_FLAGS_PITCH;
header->pitchOrLinearSize = static_cast<uint32_t>( rowPitch );
header->pitchOrLinearSize = static_cast<uint32_t>(rowPitch);
}
// Setup pixels
std::unique_ptr<uint8_t[]> pixels( new (std::nothrow) uint8_t[ slicePitch ] );
std::unique_ptr<uint8_t[]> pixels(new (std::nothrow) uint8_t[slicePitch]);
if (!pixels)
return E_OUTOFMEMORY;
D3D11_MAPPED_SUBRESOURCE mapped;
hr = pContext->Map( pStaging.Get(), 0, D3D11_MAP_READ, 0, &mapped );
if ( FAILED(hr) )
hr = pContext->Map(pStaging.Get(), 0, D3D11_MAP_READ, 0, &mapped);
if (FAILED(hr))
return hr;
auto sptr = static_cast<const uint8_t*>( mapped.pData );
if ( !sptr )
auto sptr = static_cast<const uint8_t*>(mapped.pData);
if (!sptr)
{
pContext->Unmap( pStaging.Get(), 0 );
pContext->Unmap(pStaging.Get(), 0);
return E_POINTER;
}
uint8_t* dptr = pixels.get();
size_t msize = std::min<size_t>( rowPitch, mapped.RowPitch );
for( size_t h = 0; h < rowCount; ++h )
size_t msize = std::min<size_t>(rowPitch, mapped.RowPitch);
for (size_t h = 0; h < rowCount; ++h)
{
memcpy_s( dptr, rowPitch, sptr, msize );
memcpy_s(dptr, rowPitch, sptr, msize);
sptr += mapped.RowPitch;
dptr += rowPitch;
}
pContext->Unmap( pStaging.Get(), 0 );
pContext->Unmap(pStaging.Get(), 0);
// Write header & pixels
DWORD bytesWritten;
if ( !WriteFile( hFile.get(), fileHeader, static_cast<DWORD>( headerSize ), &bytesWritten, nullptr ) )
return HRESULT_FROM_WIN32( GetLastError() );
if (!WriteFile(hFile.get(), fileHeader, static_cast<DWORD>(headerSize), &bytesWritten, nullptr))
return HRESULT_FROM_WIN32(GetLastError());
if ( bytesWritten != headerSize )
if (bytesWritten != headerSize)
return E_FAIL;
if ( !WriteFile( hFile.get(), pixels.get(), static_cast<DWORD>( slicePitch ), &bytesWritten, nullptr ) )
return HRESULT_FROM_WIN32( GetLastError() );
if (!WriteFile(hFile.get(), pixels.get(), static_cast<DWORD>(slicePitch), &bytesWritten, nullptr))
return HRESULT_FROM_WIN32(GetLastError());
if ( bytesWritten != slicePitch )
if (bytesWritten != slicePitch)
return E_FAIL;
delonfail.clear();
@ -937,19 +951,19 @@ HRESULT DirectX::SaveWICTextureToFile(
std::function<void(IPropertyBag2*)> setCustomProps,
bool forceSRGB)
{
if ( !fileName )
if (!fileName)
return E_INVALIDARG;
D3D11_TEXTURE2D_DESC desc = {};
ComPtr<ID3D11Texture2D> pStaging;
HRESULT hr = CaptureTexture( pContext, pSource, desc, pStaging );
if ( FAILED(hr) )
HRESULT hr = CaptureTexture(pContext, pSource, desc, pStaging);
if (FAILED(hr))
return hr;
// Determine source format's WIC equivalent
WICPixelFormatGUID pfGuid;
WICPixelFormatGUID pfGuid = {};
bool sRGB = forceSRGB;
switch ( desc.Format )
switch (desc.Format)
{
case DXGI_FORMAT_R32G32B32A32_FLOAT: pfGuid = GUID_WICPixelFormat128bppRGBAFloat; break;
case DXGI_FORMAT_R16G16B16A16_FLOAT: pfGuid = GUID_WICPixelFormat64bppRGBAHalf; break;
@ -984,91 +998,91 @@ HRESULT DirectX::SaveWICTextureToFile(
case DXGI_FORMAT_B8G8R8X8_UNORM: // DXGI 1.1
pfGuid = GUID_WICPixelFormat32bppBGR;
break;
break;
case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: // DXGI 1.1
pfGuid = GUID_WICPixelFormat32bppBGR;
sRGB = true;
break;
break;
default:
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
}
auto pWIC = _GetWIC();
if ( !pWIC )
if (!pWIC)
return E_NOINTERFACE;
ComPtr<IWICStream> stream;
hr = pWIC->CreateStream( stream.GetAddressOf() );
if ( FAILED(hr) )
hr = pWIC->CreateStream(stream.GetAddressOf());
if (FAILED(hr))
return hr;
hr = stream->InitializeFromFilename( fileName, GENERIC_WRITE );
if ( FAILED(hr) )
hr = stream->InitializeFromFilename(fileName, GENERIC_WRITE);
if (FAILED(hr))
return hr;
auto_delete_file_wic delonfail(stream, fileName);
ComPtr<IWICBitmapEncoder> encoder;
hr = pWIC->CreateEncoder( guidContainerFormat, nullptr, encoder.GetAddressOf() );
if ( FAILED(hr) )
hr = pWIC->CreateEncoder(guidContainerFormat, nullptr, encoder.GetAddressOf());
if (FAILED(hr))
return hr;
hr = encoder->Initialize( stream.Get(), WICBitmapEncoderNoCache );
if ( FAILED(hr) )
hr = encoder->Initialize(stream.Get(), WICBitmapEncoderNoCache);
if (FAILED(hr))
return hr;
ComPtr<IWICBitmapFrameEncode> frame;
ComPtr<IPropertyBag2> props;
hr = encoder->CreateNewFrame( frame.GetAddressOf(), props.GetAddressOf() );
if ( FAILED(hr) )
hr = encoder->CreateNewFrame(frame.GetAddressOf(), props.GetAddressOf());
if (FAILED(hr))
return hr;
if ( targetFormat && memcmp( &guidContainerFormat, &GUID_ContainerFormatBmp, sizeof(WICPixelFormatGUID) ) == 0 && g_WIC2 )
if (targetFormat && memcmp(&guidContainerFormat, &GUID_ContainerFormatBmp, sizeof(WICPixelFormatGUID)) == 0 && g_WIC2)
{
// Opt-in to the WIC2 support for writing 32-bit Windows BMP files with an alpha channel
PROPBAG2 option = {};
option.pstrName = const_cast<wchar_t*>(L"EnableV5Header32bppBGRA");
VARIANT varValue;
VARIANT varValue;
varValue.vt = VT_BOOL;
varValue.boolVal = VARIANT_TRUE;
(void)props->Write( 1, &option, &varValue );
varValue.boolVal = VARIANT_TRUE;
(void)props->Write(1, &option, &varValue);
}
if ( setCustomProps )
if (setCustomProps)
{
setCustomProps( props.Get() );
setCustomProps(props.Get());
}
hr = frame->Initialize( props.Get() );
if ( FAILED(hr) )
hr = frame->Initialize(props.Get());
if (FAILED(hr))
return hr;
hr = frame->SetSize( desc.Width , desc.Height );
if ( FAILED(hr) )
hr = frame->SetSize(desc.Width, desc.Height);
if (FAILED(hr))
return hr;
hr = frame->SetResolution( 72, 72 );
if ( FAILED(hr) )
hr = frame->SetResolution(72, 72);
if (FAILED(hr))
return hr;
// Pick a target format
WICPixelFormatGUID targetGuid;
if ( targetFormat )
WICPixelFormatGUID targetGuid = {};
if (targetFormat)
{
targetGuid = *targetFormat;
}
else
{
// Screenshots don't typically include the alpha channel of the render target
switch ( desc.Format )
switch (desc.Format)
{
#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) || defined(_WIN7_PLATFORM_UPDATE)
case DXGI_FORMAT_R32G32B32A32_FLOAT:
case DXGI_FORMAT_R32G32B32A32_FLOAT:
case DXGI_FORMAT_R16G16B16A16_FLOAT:
if ( g_WIC2 )
if (g_WIC2)
{
targetGuid = GUID_WICPixelFormat96bppRGBFloat;
}
@ -1097,11 +1111,11 @@ HRESULT DirectX::SaveWICTextureToFile(
}
}
hr = frame->SetPixelFormat( &targetGuid );
if ( FAILED(hr) )
hr = frame->SetPixelFormat(&targetGuid);
if (FAILED(hr))
return hr;
if ( targetFormat && memcmp( targetFormat, &targetGuid, sizeof(WICPixelFormatGUID) ) != 0 )
if (targetFormat && memcmp(targetFormat, &targetGuid, sizeof(WICPixelFormatGUID)) != 0)
{
// Requested output pixel format is not supported by the WIC codec
return E_FAIL;
@ -1109,18 +1123,18 @@ HRESULT DirectX::SaveWICTextureToFile(
// Encode WIC metadata
ComPtr<IWICMetadataQueryWriter> metawriter;
if ( SUCCEEDED( frame->GetMetadataQueryWriter( metawriter.GetAddressOf() ) ) )
if (SUCCEEDED(frame->GetMetadataQueryWriter(metawriter.GetAddressOf())))
{
PROPVARIANT value;
PropVariantInit( &value );
PropVariantInit(&value);
value.vt = VT_LPSTR;
value.pszVal = const_cast<char*>("DirectXTK");
if ( memcmp( &guidContainerFormat, &GUID_ContainerFormatPng, sizeof(GUID) ) == 0 )
if (memcmp(&guidContainerFormat, &GUID_ContainerFormatPng, sizeof(GUID)) == 0)
{
// Set Software name
(void)metawriter->SetMetadataByName( L"/tEXt/{str=Software}", &value );
(void)metawriter->SetMetadataByName(L"/tEXt/{str=Software}", &value);
// Set sRGB chunk
if (sRGB)
@ -1143,82 +1157,89 @@ HRESULT DirectX::SaveWICTextureToFile(
else
{
// Set Software name
(void)metawriter->SetMetadataByName( L"System.ApplicationName", &value );
(void)metawriter->SetMetadataByName(L"System.ApplicationName", &value);
if ( sRGB )
if (sRGB)
{
// Set EXIF Colorspace of sRGB
value.vt = VT_UI2;
value.uiVal = 1;
(void)metawriter->SetMetadataByName( L"System.Image.ColorSpace", &value );
(void)metawriter->SetMetadataByName(L"System.Image.ColorSpace", &value);
}
}
}
D3D11_MAPPED_SUBRESOURCE mapped;
hr = pContext->Map( pStaging.Get(), 0, D3D11_MAP_READ, 0, &mapped );
if ( FAILED(hr) )
hr = pContext->Map(pStaging.Get(), 0, D3D11_MAP_READ, 0, &mapped);
if (FAILED(hr))
return hr;
if ( memcmp( &targetGuid, &pfGuid, sizeof(WICPixelFormatGUID) ) != 0 )
uint64_t imageSize = uint64_t(mapped.RowPitch) * uint64_t(desc.Height);
if (imageSize > UINT32_MAX)
{
pContext->Unmap(pStaging.Get(), 0);
return HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW);
}
if (memcmp(&targetGuid, &pfGuid, sizeof(WICPixelFormatGUID)) != 0)
{
// Conversion required to write
ComPtr<IWICBitmap> source;
hr = pWIC->CreateBitmapFromMemory( desc.Width, desc.Height, pfGuid,
mapped.RowPitch, mapped.RowPitch * desc.Height,
static_cast<BYTE*>( mapped.pData ), source.GetAddressOf() );
if ( FAILED(hr) )
hr = pWIC->CreateBitmapFromMemory(desc.Width, desc.Height,
pfGuid,
mapped.RowPitch, static_cast<UINT>(imageSize),
static_cast<BYTE*>(mapped.pData), source.GetAddressOf());
if (FAILED(hr))
{
pContext->Unmap( pStaging.Get(), 0 );
pContext->Unmap(pStaging.Get(), 0);
return hr;
}
ComPtr<IWICFormatConverter> FC;
hr = pWIC->CreateFormatConverter( FC.GetAddressOf() );
if ( FAILED(hr) )
hr = pWIC->CreateFormatConverter(FC.GetAddressOf());
if (FAILED(hr))
{
pContext->Unmap( pStaging.Get(), 0 );
pContext->Unmap(pStaging.Get(), 0);
return hr;
}
BOOL canConvert = FALSE;
hr = FC->CanConvert( pfGuid, targetGuid, &canConvert );
if ( FAILED(hr) || !canConvert )
hr = FC->CanConvert(pfGuid, targetGuid, &canConvert);
if (FAILED(hr) || !canConvert)
{
pContext->Unmap(pStaging.Get(), 0);
return E_UNEXPECTED;
}
hr = FC->Initialize( source.Get(), targetGuid, WICBitmapDitherTypeNone, nullptr, 0, WICBitmapPaletteTypeMedianCut );
if ( FAILED(hr) )
hr = FC->Initialize(source.Get(), targetGuid, WICBitmapDitherTypeNone, nullptr, 0, WICBitmapPaletteTypeMedianCut);
if (FAILED(hr))
{
pContext->Unmap( pStaging.Get(), 0 );
pContext->Unmap(pStaging.Get(), 0);
return hr;
}
WICRect rect = { 0, 0, static_cast<INT>( desc.Width ), static_cast<INT>( desc.Height ) };
hr = frame->WriteSource( FC.Get(), &rect );
if ( FAILED(hr) )
{
pContext->Unmap( pStaging.Get(), 0 );
return hr;
}
WICRect rect = { 0, 0, static_cast<INT>(desc.Width), static_cast<INT>(desc.Height) };
hr = frame->WriteSource(FC.Get(), &rect);
}
else
{
// No conversion required
hr = frame->WritePixels( desc.Height, mapped.RowPitch, mapped.RowPitch * desc.Height, static_cast<BYTE*>( mapped.pData ) );
if ( FAILED(hr) )
return hr;
hr = frame->WritePixels(desc.Height,
mapped.RowPitch, static_cast<UINT>(imageSize),
static_cast<BYTE*>(mapped.pData));
}
pContext->Unmap( pStaging.Get(), 0 );
pContext->Unmap(pStaging.Get(), 0);
if (FAILED(hr))
return hr;
hr = frame->Commit();
if ( FAILED(hr) )
if (FAILED(hr))
return hr;
hr = encoder->Commit();
if ( FAILED(hr) )
if (FAILED(hr))
return hr;
delonfail.clear();

Просмотреть файл

@ -1,5 +1,5 @@
//--------------------------------------------------------------------------------------
// File: ScreenGrab.h
// File: ScreenGrab11.h
//
// Function for capturing a 2D texture and saving it to a file (aka a 'screenshot'
// when used on a Direct3D 11 Render Target).
@ -28,7 +28,7 @@ namespace DirectX
HRESULT __cdecl SaveDDSTextureToFile(
_In_ ID3D11DeviceContext* pContext,
_In_ ID3D11Resource* pSource,
_In_z_ const wchar_t* fileName);
_In_z_ const wchar_t* fileName) noexcept;
HRESULT __cdecl SaveWICTextureToFile(
_In_ ID3D11DeviceContext* pContext,

Просмотреть файл

@ -38,8 +38,9 @@
#include <algorithm>
#include <memory>
#if !defined(NO_D3D11_DEBUG_NAME) && ( defined(_DEBUG) || defined(PROFILE) )
#pragma comment(lib,"dxguid.lib")
#ifdef __clang__
#pragma clang diagnostic ignored "-Wcovered-switch-default"
#pragma clang diagnostic ignored "-Wswitch-enum"
#endif
using namespace DirectX;
@ -49,7 +50,7 @@ namespace
{
//--------------------------------------------------------------------------------------
template<UINT TNameLength>
inline void SetDebugObjectName(_In_ ID3D11DeviceChild* resource, _In_ const char(&name)[TNameLength])
inline void SetDebugObjectName(_In_ ID3D11DeviceChild* resource, _In_ const char(&name)[TNameLength]) noexcept
{
#if !defined(NO_D3D11_DEBUG_NAME) && ( defined(_DEBUG) || defined(PROFILE) )
resource->SetPrivateData(WKPDID_D3DDebugObjectName, TNameLength - 1, name);
@ -165,56 +166,63 @@ namespace
bool g_WIC2 = false;
//--------------------------------------------------------------------------------------
IWICImagingFactory* _GetWIC()
BOOL WINAPI InitializeWICFactory(PINIT_ONCE, PVOID, PVOID* ifactory) noexcept
{
#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) || defined(_WIN7_PLATFORM_UPDATE)
HRESULT hr = CoCreateInstance(
CLSID_WICImagingFactory2,
nullptr,
CLSCTX_INPROC_SERVER,
__uuidof(IWICImagingFactory2),
ifactory
);
if (SUCCEEDED(hr))
{
// WIC2 is available on Windows 10, Windows 8.x, and Windows 7 SP1 with KB 2670838 installed
g_WIC2 = true;
return TRUE;
}
else
{
hr = CoCreateInstance(
CLSID_WICImagingFactory1,
nullptr,
CLSCTX_INPROC_SERVER,
__uuidof(IWICImagingFactory),
ifactory
);
return SUCCEEDED(hr) ? TRUE : FALSE;
}
#else
return SUCCEEDED(CoCreateInstance(
CLSID_WICImagingFactory,
nullptr,
CLSCTX_INPROC_SERVER,
__uuidof(IWICImagingFactory),
ifactory)) ? TRUE : FALSE;
#endif
}
IWICImagingFactory* _GetWIC() noexcept
{
static INIT_ONCE s_initOnce = INIT_ONCE_STATIC_INIT;
IWICImagingFactory* factory = nullptr;
InitOnceExecuteOnce(&s_initOnce,
[](PINIT_ONCE, PVOID, PVOID *ifactory) -> BOOL
if (!InitOnceExecuteOnce(
&s_initOnce,
InitializeWICFactory,
nullptr,
reinterpret_cast<LPVOID*>(&factory)))
{
#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) || defined(_WIN7_PLATFORM_UPDATE)
HRESULT hr = CoCreateInstance(
CLSID_WICImagingFactory2,
nullptr,
CLSCTX_INPROC_SERVER,
__uuidof(IWICImagingFactory2),
ifactory
);
if (SUCCEEDED(hr))
{
// WIC2 is available on Windows 10, Windows 8.x, and Windows 7 SP1 with KB 2670838 installed
g_WIC2 = true;
return TRUE;
}
else
{
hr = CoCreateInstance(
CLSID_WICImagingFactory1,
nullptr,
CLSCTX_INPROC_SERVER,
__uuidof(IWICImagingFactory),
ifactory
);
return SUCCEEDED(hr) ? TRUE : FALSE;
}
#else
return SUCCEEDED(CoCreateInstance(
CLSID_WICImagingFactory,
nullptr,
CLSCTX_INPROC_SERVER,
__uuidof(IWICImagingFactory),
ifactory)) ? TRUE : FALSE;
#endif
}, nullptr, reinterpret_cast<LPVOID*>(&factory));
return nullptr;
}
return factory;
}
//---------------------------------------------------------------------------------
DXGI_FORMAT _WICToDXGI(const GUID& guid)
DXGI_FORMAT _WICToDXGI(const GUID& guid) noexcept
{
for (size_t i = 0; i < _countof(g_WICFormats); ++i)
{
@ -234,7 +242,7 @@ namespace
}
//---------------------------------------------------------------------------------
size_t _WICBitsPerPixel(REFGUID targetGuid)
size_t _WICBitsPerPixel(REFGUID targetGuid) noexcept
{
auto pWIC = _GetWIC();
if (!pWIC)
@ -264,7 +272,7 @@ namespace
//--------------------------------------------------------------------------------------
DXGI_FORMAT MakeSRGB(_In_ DXGI_FORMAT format)
DXGI_FORMAT MakeSRGB(_In_ DXGI_FORMAT format) noexcept
{
switch (format)
{
@ -295,10 +303,52 @@ namespace
}
//---------------------------------------------------------------------------------
void FitPowerOf2(UINT origx, UINT origy, UINT& targetx, UINT& targety, size_t maxsize)
{
float origAR = float(origx) / float(origy);
if (origx > origy)
{
size_t x;
for (x = maxsize; x > 1; x >>= 1) { if (x <= targetx) break; }
targetx = UINT(x);
float bestScore = FLT_MAX;
for (size_t y = maxsize; y > 0; y >>= 1)
{
float score = fabsf((float(x) / float(y)) - origAR);
if (score < bestScore)
{
bestScore = score;
targety = UINT(y);
}
}
}
else
{
size_t y;
for (y = maxsize; y > 1; y >>= 1) { if (y <= targety) break; }
targety = UINT(y);
float bestScore = FLT_MAX;
for (size_t x = maxsize; x > 0; x >>= 1)
{
float score = fabsf((float(x) / float(y)) - origAR);
if (score < bestScore)
{
bestScore = score;
targetx = UINT(x);
}
}
}
}
//---------------------------------------------------------------------------------
HRESULT CreateTextureFromWIC(_In_ ID3D11Device* d3dDevice,
_In_opt_ ID3D11DeviceContext* d3dContext,
_In_ IWICBitmapFrameDecode *frame,
_In_ IWICBitmapFrameDecode* frame,
_In_ size_t maxsize,
_In_ D3D11_USAGE usage,
_In_ unsigned int bindFlags,
@ -306,7 +356,7 @@ namespace
_In_ unsigned int miscFlags,
_In_ unsigned int loadFlags,
_Outptr_opt_ ID3D11Resource** texture,
_Outptr_opt_ ID3D11ShaderResourceView** textureView)
_Outptr_opt_ ID3D11ShaderResourceView** textureView) noexcept
{
UINT width, height;
HRESULT hr = frame->GetSize(&width, &height);
@ -328,28 +378,33 @@ namespace
{
case D3D_FEATURE_LEVEL_9_1:
case D3D_FEATURE_LEVEL_9_2:
maxsize = 2048 /*D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION*/;
maxsize = 2048u /*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*/;
maxsize = 4096u /*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*/;
maxsize = 8192u /*D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION*/;
break;
default:
maxsize = D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION;
maxsize = size_t(D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION);
break;
}
}
assert(maxsize > 0);
UINT twidth, theight;
if (width > maxsize || height > maxsize)
UINT twidth = width;
UINT theight = height;
if (loadFlags & WIC_LOADER_FIT_POW2)
{
FitPowerOf2(width, height, twidth, theight, maxsize);
}
else if (width > maxsize || height > maxsize)
{
float ar = static_cast<float>(height) / static_cast<float>(width);
if (width > height)
@ -364,10 +419,11 @@ namespace
}
assert(twidth <= maxsize && theight <= maxsize);
}
else
if (loadFlags & WIC_LOADER_MAKE_SQUARE)
{
twidth = width;
theight = height;
twidth = std::max<UINT>(twidth, theight);
theight = twidth;
}
// Determine format
@ -441,6 +497,13 @@ namespace
}
#endif
if (loadFlags & WIC_LOADER_FORCE_RGBA32)
{
memcpy_s(&convertGUID, sizeof(WICPixelFormatGUID), &GUID_WICPixelFormat32bppRGBA, sizeof(GUID));
format = DXGI_FORMAT_R8G8B8A8_UNORM;
bpp = 32;
}
if (!bpp)
return E_FAIL;
@ -457,23 +520,34 @@ namespace
GUID containerFormat;
if (SUCCEEDED(metareader->GetContainerFormat(&containerFormat)))
{
// Check for sRGB colorspace metadata
bool sRGB = false;
PROPVARIANT value;
PropVariantInit(&value);
// Check for colorspace chunks
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"/gAMA/ImageGamma", &value)) && value.vt == VT_UI4)
{
sRGB = (value.uintVal == 45455);
}
else
{
sRGB = (loadFlags & WIC_LOADER_SRGB_DEFAULT) != 0;
}
}
else if (SUCCEEDED(metareader->GetMetadataByName(L"System.Image.ColorSpace", &value)) && value.vt == VT_UI2 && value.uiVal == 1)
else if (SUCCEEDED(metareader->GetMetadataByName(L"System.Image.ColorSpace", &value)) && value.vt == VT_UI2)
{
sRGB = true;
sRGB = (value.uiVal == 1);
}
else
{
sRGB = (loadFlags & WIC_LOADER_SRGB_DEFAULT) != 0;
}
(void)PropVariantClear(&value);
@ -612,10 +686,10 @@ namespace
}
// Create texture
D3D11_TEXTURE2D_DESC desc;
D3D11_TEXTURE2D_DESC desc = {};
desc.Width = twidth;
desc.Height = theight;
desc.MipLevels = (autogen) ? 0 : 1;
desc.MipLevels = (autogen) ? 0u : 1u;
desc.ArraySize = 1;
desc.Format = format;
desc.SampleDesc.Count = 1;
@ -649,7 +723,7 @@ namespace
SRVDesc.Format = desc.Format;
SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
SRVDesc.Texture2D.MipLevels = (autogen) ? UINT(-1) : 1;
SRVDesc.Texture2D.MipLevels = (autogen) ? unsigned(-1) : 1u;
hr = d3dDevice->CreateShaderResourceView(tex, &SRVDesc, textureView);
if (FAILED(hr))
@ -685,7 +759,7 @@ namespace
void SetDebugTextureInfo(
_In_z_ const wchar_t* fileName,
_In_opt_ ID3D11Resource** texture,
_In_opt_ ID3D11ShaderResourceView** textureView)
_In_opt_ ID3D11ShaderResourceView** textureView) noexcept
{
#if !defined(NO_D3D11_DEBUG_NAME) && ( defined(_DEBUG) || defined(PROFILE) )
if (texture || textureView)
@ -745,7 +819,7 @@ HRESULT DirectX::CreateWICTextureFromMemory(
size_t wicDataSize,
ID3D11Resource** texture,
ID3D11ShaderResourceView** textureView,
size_t maxsize)
size_t maxsize) noexcept
{
return CreateWICTextureFromMemoryEx(d3dDevice, nullptr,
wicData, wicDataSize,
@ -763,7 +837,7 @@ HRESULT DirectX::CreateWICTextureFromMemory(
size_t wicDataSize,
ID3D11Resource** texture,
ID3D11ShaderResourceView** textureView,
size_t maxsize)
size_t maxsize) noexcept
{
return CreateWICTextureFromMemoryEx(d3dDevice, d3dContext,
wicData, wicDataSize,
@ -785,7 +859,7 @@ HRESULT DirectX::CreateWICTextureFromMemoryEx(
unsigned int miscFlags,
unsigned int loadFlags,
ID3D11Resource** texture,
ID3D11ShaderResourceView** textureView)
ID3D11ShaderResourceView** textureView) noexcept
{
return CreateWICTextureFromMemoryEx(d3dDevice, nullptr,
wicData, wicDataSize,
@ -808,7 +882,7 @@ HRESULT DirectX::CreateWICTextureFromMemoryEx(
unsigned int miscFlags,
unsigned int loadFlags,
ID3D11Resource** texture,
ID3D11ShaderResourceView** textureView)
ID3D11ShaderResourceView** textureView) noexcept
{
if (texture)
{
@ -889,7 +963,7 @@ HRESULT DirectX::CreateWICTextureFromFile(
const wchar_t* fileName,
ID3D11Resource** texture,
ID3D11ShaderResourceView** textureView,
size_t maxsize)
size_t maxsize) noexcept
{
return CreateWICTextureFromFileEx(d3dDevice, nullptr,
fileName, maxsize,
@ -905,7 +979,7 @@ HRESULT DirectX::CreateWICTextureFromFile(
const wchar_t* fileName,
ID3D11Resource** texture,
ID3D11ShaderResourceView** textureView,
size_t maxsize)
size_t maxsize) noexcept
{
return CreateWICTextureFromFileEx(d3dDevice, d3dContext,
fileName,
@ -926,7 +1000,7 @@ HRESULT DirectX::CreateWICTextureFromFileEx(
unsigned int miscFlags,
unsigned int loadFlags,
ID3D11Resource** texture,
ID3D11ShaderResourceView** textureView)
ID3D11ShaderResourceView** textureView) noexcept
{
return CreateWICTextureFromFileEx(d3dDevice, nullptr,
fileName,
@ -948,7 +1022,7 @@ HRESULT DirectX::CreateWICTextureFromFileEx(
unsigned int miscFlags,
unsigned int loadFlags,
ID3D11Resource** texture,
ID3D11ShaderResourceView** textureView)
ID3D11ShaderResourceView** textureView) noexcept
{
if (texture)
{

Просмотреть файл

@ -1,5 +1,5 @@
//--------------------------------------------------------------------------------------
// File: WICTextureLoader.h
// File: WICTextureLoader11.h
//
// Function for loading a WIC image and creating a Direct3D runtime texture for it
// (auto-generating mipmaps if possible)
@ -24,17 +24,24 @@
#pragma once
#include <d3d11_1.h>
#include <stdint.h>
#include <cstdint>
namespace DirectX
{
enum WIC_LOADER_FLAGS
#ifndef WIC_LOADER_FLAGS_DEFINED
#define WIC_LOADER_FLAGS_DEFINED
enum WIC_LOADER_FLAGS : uint32_t
{
WIC_LOADER_DEFAULT = 0,
WIC_LOADER_FORCE_SRGB = 0x1,
WIC_LOADER_IGNORE_SRGB = 0x2,
WIC_LOADER_SRGB_DEFAULT = 0x4,
WIC_LOADER_FIT_POW2 = 0x20,
WIC_LOADER_MAKE_SQUARE = 0x40,
WIC_LOADER_FORCE_RGBA32 = 0x80,
};
#endif
// Standard version
HRESULT CreateWICTextureFromMemory(
@ -43,14 +50,14 @@ namespace DirectX
_In_ size_t wicDataSize,
_Outptr_opt_ ID3D11Resource** texture,
_Outptr_opt_ ID3D11ShaderResourceView** textureView,
_In_ size_t maxsize = 0);
_In_ size_t maxsize = 0) noexcept;
HRESULT CreateWICTextureFromFile(
_In_ ID3D11Device* d3dDevice,
_In_z_ const wchar_t* szFileName,
_Outptr_opt_ ID3D11Resource** texture,
_Outptr_opt_ ID3D11ShaderResourceView** textureView,
_In_ size_t maxsize = 0);
_In_ size_t maxsize = 0) noexcept;
// Standard version with optional auto-gen mipmap support
HRESULT CreateWICTextureFromMemory(
@ -60,7 +67,7 @@ namespace DirectX
_In_ size_t wicDataSize,
_Outptr_opt_ ID3D11Resource** texture,
_Outptr_opt_ ID3D11ShaderResourceView** textureView,
_In_ size_t maxsize = 0);
_In_ size_t maxsize = 0) noexcept;
HRESULT CreateWICTextureFromFile(
_In_ ID3D11Device* d3dDevice,
@ -68,7 +75,7 @@ namespace DirectX
_In_z_ const wchar_t* szFileName,
_Outptr_opt_ ID3D11Resource** texture,
_Outptr_opt_ ID3D11ShaderResourceView** textureView,
_In_ size_t maxsize = 0);
_In_ size_t maxsize = 0) noexcept;
// Extended version
HRESULT CreateWICTextureFromMemoryEx(
@ -82,7 +89,7 @@ namespace DirectX
_In_ unsigned int miscFlags,
_In_ unsigned int loadFlags,
_Outptr_opt_ ID3D11Resource** texture,
_Outptr_opt_ ID3D11ShaderResourceView** textureView);
_Outptr_opt_ ID3D11ShaderResourceView** textureView) noexcept;
HRESULT CreateWICTextureFromFileEx(
_In_ ID3D11Device* d3dDevice,
@ -94,7 +101,7 @@ namespace DirectX
_In_ unsigned int miscFlags,
_In_ unsigned int loadFlags,
_Outptr_opt_ ID3D11Resource** texture,
_Outptr_opt_ ID3D11ShaderResourceView** textureView);
_Outptr_opt_ ID3D11ShaderResourceView** textureView) noexcept;
// Extended version with optional auto-gen mipmap support
HRESULT CreateWICTextureFromMemoryEx(
@ -109,7 +116,7 @@ namespace DirectX
_In_ unsigned int miscFlags,
_In_ unsigned int loadFlags,
_Outptr_opt_ ID3D11Resource** texture,
_Outptr_opt_ ID3D11ShaderResourceView** textureView);
_Outptr_opt_ ID3D11ShaderResourceView** textureView) noexcept;
HRESULT CreateWICTextureFromFileEx(
_In_ ID3D11Device* d3dDevice,
@ -122,5 +129,5 @@ namespace DirectX
_In_ unsigned int miscFlags,
_In_ unsigned int loadFlags,
_Outptr_opt_ ID3D11Resource** texture,
_Outptr_opt_ ID3D11ShaderResourceView** textureView);
}
_Outptr_opt_ ID3D11ShaderResourceView** textureView) noexcept;
}