Direct3D 9 versions of texture loaders (#176)
This commit is contained in:
parent
fdd7a70c44
commit
45fb8623d2
@ -1,5 +1,5 @@
|
||||
//--------------------------------------------------------------------------------------
|
||||
// File: DDSTextureLoader.cpp
|
||||
// File: DDSTextureLoader11.cpp
|
||||
//
|
||||
// Functions for loading a DDS texture and creating a Direct3D runtime resource for it
|
||||
//
|
||||
@ -14,7 +14,7 @@
|
||||
// http://go.microsoft.com/fwlink/?LinkId=248929
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
#include "DDSTextureLoader.h"
|
||||
#include "DDSTextureLoader11.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <algorithm>
|
||||
@ -639,12 +639,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
|
||||
@ -660,12 +660,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
|
||||
@ -681,19 +681,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;
|
||||
@ -703,14 +703,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
|
||||
}
|
||||
@ -718,11 +718,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
|
||||
}
|
||||
@ -739,7 +739,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
|
||||
}
|
||||
@ -751,13 +751,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)
|
||||
{
|
||||
@ -853,6 +855,8 @@ namespace
|
||||
|
||||
case 116: // D3DFMT_A32B32G32R32F
|
||||
return DXGI_FORMAT_R32G32B32A32_FLOAT;
|
||||
|
||||
// No DXGI format maps to D3DFMT_CxV8U8
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
//--------------------------------------------------------------------------------------
|
||||
// File: DDSTextureLoader.h
|
||||
// File: DDSTextureLoader11.h
|
||||
//
|
||||
// Functions for loading a DDS texture and creating a Direct3D runtime resource for it
|
||||
//
|
@ -27,6 +27,8 @@
|
||||
#pragma clang diagnostic ignored "-Wswitch-enum"
|
||||
#endif
|
||||
|
||||
#pragma warning(disable : 4062)
|
||||
|
||||
#define D3DX12_NO_STATE_OBJECT_HELPERS
|
||||
#include "d3dx12.h"
|
||||
|
||||
@ -654,12 +656,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
|
||||
@ -675,12 +677,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
|
||||
@ -696,19 +698,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;
|
||||
@ -718,14 +720,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
|
||||
// No DXGI format maps to ISBITMASK(0x0f,0,0,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
|
||||
}
|
||||
@ -733,11 +735,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
|
||||
}
|
||||
@ -754,7 +756,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
|
||||
}
|
||||
@ -766,13 +768,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)
|
||||
{
|
||||
@ -868,6 +872,8 @@ namespace
|
||||
|
||||
case 116: // D3DFMT_A32B32G32R32F
|
||||
return DXGI_FORMAT_R32G32B32A32_FLOAT;
|
||||
|
||||
// No DXGI format maps to D3DFMT_CxV8U8
|
||||
}
|
||||
}
|
||||
|
||||
@ -1355,7 +1361,8 @@ namespace
|
||||
size_t reservedMips = mipCount;
|
||||
if (loadFlags & DDS_LOADER_MIP_RESERVE)
|
||||
{
|
||||
reservedMips = std::min<size_t>(D3D12_REQ_MIP_LEVELS, CountMips(width, height));
|
||||
reservedMips = std::min<size_t>(D3D12_REQ_MIP_LEVELS,
|
||||
CountMips(width, height));
|
||||
}
|
||||
|
||||
hr = CreateTextureResource(d3dDevice, resDim, twidth, theight, tdepth, reservedMips - skipMip, arraySize,
|
||||
|
1278
DDSTextureLoader/DDSTextureLoader9.cpp
Normal file
1278
DDSTextureLoader/DDSTextureLoader9.cpp
Normal file
File diff suppressed because it is too large
Load Diff
78
DDSTextureLoader/DDSTextureLoader9.h
Normal file
78
DDSTextureLoader/DDSTextureLoader9.h
Normal file
@ -0,0 +1,78 @@
|
||||
//--------------------------------------------------------------------------------------
|
||||
// File: DDSTextureLoader9.h
|
||||
//
|
||||
// Functions for loading a DDS texture and creating a Direct3D runtime resource for it
|
||||
//
|
||||
// Note these functions are useful as a light-weight runtime loader for DDS files. For
|
||||
// a full-featured DDS file reader, writer, and texture processing pipeline see
|
||||
// the 'Texconv' sample and the 'DirectXTex' library.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
//
|
||||
// http://go.microsoft.com/fwlink/?LinkId=248926
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef DIRECT3D_VERSION
|
||||
#define DIRECT3D_VERSION 0x900
|
||||
#endif
|
||||
|
||||
#include <d3d9.h>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
|
||||
namespace DirectX
|
||||
{
|
||||
// Standard version
|
||||
HRESULT CreateDDSTextureFromMemory(
|
||||
_In_ LPDIRECT3DDEVICE9 d3dDevice,
|
||||
_In_reads_bytes_(ddsDataSize) const uint8_t* ddsData,
|
||||
_In_ size_t ddsDataSize,
|
||||
_Outptr_ LPDIRECT3DBASETEXTURE9* texture,
|
||||
bool generateMipsIfMissing = false) noexcept;
|
||||
|
||||
HRESULT CreateDDSTextureFromFile(
|
||||
_In_ LPDIRECT3DDEVICE9 d3dDevice,
|
||||
_In_z_ const wchar_t* fileName,
|
||||
_Outptr_ LPDIRECT3DBASETEXTURE9* texture,
|
||||
bool generateMipsIfMissing = false) noexcept;
|
||||
|
||||
// Type-specific versions
|
||||
HRESULT CreateDDSTextureFromMemory(
|
||||
_In_ LPDIRECT3DDEVICE9 d3dDevice,
|
||||
_In_reads_bytes_(ddsDataSize) const uint8_t* ddsData,
|
||||
_In_ size_t ddsDataSize,
|
||||
_Outptr_ LPDIRECT3DTEXTURE9* texture,
|
||||
bool generateMipsIfMissing = false) noexcept;
|
||||
|
||||
HRESULT CreateDDSTextureFromFile(
|
||||
_In_ LPDIRECT3DDEVICE9 d3dDevice,
|
||||
_In_z_ const wchar_t* fileName,
|
||||
_Outptr_ LPDIRECT3DTEXTURE9* texture,
|
||||
bool generateMipsIfMissing = false) noexcept;
|
||||
|
||||
HRESULT CreateDDSTextureFromMemory(
|
||||
_In_ LPDIRECT3DDEVICE9 d3dDevice,
|
||||
_In_reads_bytes_(ddsDataSize) const uint8_t* ddsData,
|
||||
_In_ size_t ddsDataSize,
|
||||
_Outptr_ LPDIRECT3DCUBETEXTURE9* texture) noexcept;
|
||||
|
||||
HRESULT CreateDDSTextureFromFile(
|
||||
_In_ LPDIRECT3DDEVICE9 d3dDevice,
|
||||
_In_z_ const wchar_t* fileName,
|
||||
_Outptr_ LPDIRECT3DCUBETEXTURE9* texture) noexcept;
|
||||
|
||||
HRESULT CreateDDSTextureFromMemory(
|
||||
_In_ LPDIRECT3DDEVICE9 d3dDevice,
|
||||
_In_reads_bytes_(ddsDataSize) const uint8_t* ddsData,
|
||||
_In_ size_t ddsDataSize,
|
||||
_Outptr_ LPDIRECT3DVOLUMETEXTURE9* texture) noexcept;
|
||||
|
||||
HRESULT CreateDDSTextureFromFile(
|
||||
_In_ LPDIRECT3DDEVICE9 d3dDevice,
|
||||
_In_z_ const wchar_t* fileName,
|
||||
_Outptr_ LPDIRECT3DVOLUMETEXTURE9* texture) noexcept;
|
||||
}
|
@ -136,7 +136,7 @@ extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_A8R3G3B2 =
|
||||
extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_R3G3B2 =
|
||||
{ sizeof(DDS_PIXELFORMAT), DDS_RGB, 0, 8, 0xe0, 0x1c, 0x03, 0 };
|
||||
|
||||
extern __declspec(selectany) DDS_PIXELFORMAT DDSPF_A4L4 =
|
||||
extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_A4L4 =
|
||||
{ sizeof(DDS_PIXELFORMAT), DDS_LUMINANCEA, 0, 8, 0x0f, 0, 0, 0xf0 };
|
||||
|
||||
extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_L8 =
|
||||
|
@ -1,8 +1,8 @@
|
||||
//--------------------------------------------------------------------------------------
|
||||
// File: ScreenGrab.cpp
|
||||
// File: ScreenGrab11.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,
|
||||
@ -21,7 +21,7 @@
|
||||
|
||||
// For 2D array textures and cubemaps, it captures only the first image in the array
|
||||
|
||||
#include "ScreenGrab.h"
|
||||
#include "ScreenGrab11.h"
|
||||
|
||||
#include <dxgiformat.h>
|
||||
#include <assert.h>
|
||||
@ -33,6 +33,11 @@
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic ignored "-Wcovered-switch-default"
|
||||
#pragma clang diagnostic ignored "-Wswitch-enum"
|
||||
#endif
|
||||
|
||||
using Microsoft::WRL::ComPtr;
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
@ -190,16 +195,16 @@ namespace
|
||||
{ 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); } };
|
||||
|
||||
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)
|
||||
@ -210,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)
|
||||
@ -232,14 +240,17 @@ 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;
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
@ -793,13 +804,12 @@ HRESULT DirectX::SaveDDSTextureToFile(
|
||||
|
||||
// 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->flags = DDS_HEADER_FLAGS_TEXTURE | DDS_HEADER_FLAGS_MIPMAP;
|
||||
header->height = desc.Height;
|
||||
@ -853,11 +863,10 @@ HRESULT DirectX::SaveDDSTextureToFile(
|
||||
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;
|
||||
@ -1165,13 +1174,21 @@ HRESULT DirectX::SaveWICTextureToFile(
|
||||
if ( FAILED(hr) )
|
||||
return hr;
|
||||
|
||||
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() );
|
||||
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 );
|
||||
@ -1190,6 +1207,7 @@ HRESULT DirectX::SaveWICTextureToFile(
|
||||
hr = FC->CanConvert( pfGuid, targetGuid, &canConvert );
|
||||
if ( FAILED(hr) || !canConvert )
|
||||
{
|
||||
pContext->Unmap( pStaging.Get(), 0 );
|
||||
return E_UNEXPECTED;
|
||||
}
|
||||
|
||||
@ -1202,22 +1220,18 @@ HRESULT DirectX::SaveWICTextureToFile(
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
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 );
|
||||
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
hr = frame->Commit();
|
||||
if ( FAILED(hr) )
|
||||
return hr;
|
@ -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).
|
@ -198,16 +198,16 @@ namespace
|
||||
{ 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); } };
|
||||
|
||||
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)
|
||||
@ -218,19 +218,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, LPCWSTR szFile) : m_filename(szFile), m_handle(hFile) {}
|
||||
auto_delete_file_wic(ComPtr<IWICStream>& hFile, LPCWSTR szFile) noexcept : m_filename(szFile), m_handle(hFile) {}
|
||||
~auto_delete_file_wic()
|
||||
{
|
||||
if (m_filename)
|
||||
@ -240,14 +243,17 @@ 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:
|
||||
LPCWSTR 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;
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
@ -896,13 +902,12 @@ HRESULT DirectX::SaveDDSTextureToFile(
|
||||
|
||||
// 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->flags = DDS_HEADER_FLAGS_TEXTURE | DDS_HEADER_FLAGS_MIPMAP;
|
||||
header->height = desc.Height;
|
||||
@ -956,11 +961,10 @@ HRESULT DirectX::SaveDDSTextureToFile(
|
||||
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 = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
|
||||
extHeader->arraySize = 1;
|
||||
|
1010
ScreenGrab/ScreenGrab9.cpp
Normal file
1010
ScreenGrab/ScreenGrab9.cpp
Normal file
File diff suppressed because it is too large
Load Diff
42
ScreenGrab/ScreenGrab9.h
Normal file
42
ScreenGrab/ScreenGrab9.h
Normal file
@ -0,0 +1,42 @@
|
||||
//--------------------------------------------------------------------------------------
|
||||
// File: ScreenGrab9.h
|
||||
//
|
||||
// Function for saving 2D surface to a file (aka a 'screenshot'
|
||||
// when used on a Direct3D 9's GetFrontBufferData).
|
||||
//
|
||||
// Note these functions are useful as a light-weight runtime screen grabber. For
|
||||
// full-featured texture capture, DDS writer, and texture processing pipeline,
|
||||
// see the 'Texconv' sample and the 'DirectXTex' library.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
//
|
||||
// http://go.microsoft.com/fwlink/?LinkId=248926
|
||||
// http://go.microsoft.com/fwlink/?LinkId=248929
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef DIRECT3D_VERSION
|
||||
#define DIRECT3D_VERSION 0x900
|
||||
#endif
|
||||
|
||||
#include <d3d9.h>
|
||||
|
||||
#include <OCIdl.h>
|
||||
#include <functional>
|
||||
|
||||
|
||||
namespace DirectX
|
||||
{
|
||||
HRESULT __cdecl SaveDDSTextureToFile(
|
||||
_In_ LPDIRECT3DSURFACE9 pSource,
|
||||
_In_z_ const wchar_t* fileName) noexcept;
|
||||
|
||||
HRESULT __cdecl SaveWICTextureToFile(
|
||||
_In_ LPDIRECT3DSURFACE9 pSource,
|
||||
_In_ REFGUID guidContainerFormat,
|
||||
_In_z_ const wchar_t* fileName,
|
||||
_In_opt_ const GUID* targetFormat = nullptr,
|
||||
_In_opt_ std::function<void __cdecl(IPropertyBag2*)> setCustomProps = nullptr) noexcept;
|
||||
}
|
@ -923,7 +923,7 @@ namespace
|
||||
float bestScore = FLT_MAX;
|
||||
for (size_t y = maxsize; y > 0; y >>= 1)
|
||||
{
|
||||
float score = fabs((float(x) / float(y)) - origAR);
|
||||
float score = fabsf((float(x) / float(y)) - origAR);
|
||||
if (score < bestScore)
|
||||
{
|
||||
bestScore = score;
|
||||
@ -940,7 +940,7 @@ namespace
|
||||
float bestScore = FLT_MAX;
|
||||
for (size_t x = maxsize; x > 0; x >>= 1)
|
||||
{
|
||||
float score = fabs((float(x) / float(y)) - origAR);
|
||||
float score = fabsf((float(x) / float(y)) - origAR);
|
||||
if (score < bestScore)
|
||||
{
|
||||
bestScore = score;
|
||||
|
@ -1,5 +1,5 @@
|
||||
//--------------------------------------------------------------------------------------
|
||||
// File: WICTextureLoader.cpp
|
||||
// File: WICTextureLoader11.cpp
|
||||
//
|
||||
// Function for loading a WIC image and creating a Direct3D runtime texture for it
|
||||
// (auto-generating mipmaps if possible)
|
||||
@ -24,7 +24,7 @@
|
||||
// We could load multi-frame images (TIFF/GIF) into a texture array.
|
||||
// For now, we just load the first frame (note: DirectXTex supports multi-frame images)
|
||||
|
||||
#include "WICTextureLoader.h"
|
||||
#include "WICTextureLoader11.h"
|
||||
|
||||
#include <dxgiformat.h>
|
||||
#include <assert.h>
|
||||
@ -164,7 +164,6 @@ namespace
|
||||
|
||||
bool g_WIC2 = false;
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
BOOL WINAPI InitializeWICFactory(PINIT_ONCE, PVOID, PVOID* ifactory) noexcept
|
||||
{
|
||||
#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) || defined(_WIN7_PLATFORM_UPDATE)
|
||||
@ -302,6 +301,48 @@ 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,
|
||||
@ -355,8 +396,13 @@ namespace
|
||||
|
||||
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)
|
||||
@ -371,10 +417,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
|
@ -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)
|
||||
@ -37,6 +37,8 @@ namespace DirectX
|
||||
WIC_LOADER_FORCE_SRGB = 0x1,
|
||||
WIC_LOADER_IGNORE_SRGB = 0x2,
|
||||
WIC_LOADER_FORCE_RGBA32 = 0x10,
|
||||
WIC_LOADER_FIT_POW2 = 0x20,
|
||||
WIC_LOADER_MAKE_SQUARE = 0x40,
|
||||
};
|
||||
#endif
|
||||
|
@ -1,7 +1,7 @@
|
||||
//--------------------------------------------------------------------------------------
|
||||
// File: WICTextureLoader12.cpp
|
||||
//
|
||||
// Function for loading a WIC image and creating a Direct3D 12 runtime texture for it
|
||||
// Function for loading a WIC image and creating a Direct3D runtime texture for it
|
||||
// (auto-generating mipmaps if possible)
|
||||
//
|
||||
// Note: Assumes application has already called CoInitializeEx
|
||||
@ -166,7 +166,8 @@ namespace
|
||||
static INIT_ONCE s_initOnce = INIT_ONCE_STATIC_INIT;
|
||||
|
||||
IWICImagingFactory2* factory = nullptr;
|
||||
if (!InitOnceExecuteOnce(&s_initOnce,
|
||||
if (!InitOnceExecuteOnce(
|
||||
&s_initOnce,
|
||||
InitializeWICFactory,
|
||||
nullptr,
|
||||
reinterpret_cast<LPVOID*>(&factory)))
|
||||
@ -276,6 +277,47 @@ namespace
|
||||
return bpp;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
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_ ID3D12Device* d3dDevice,
|
||||
_In_ IWICBitmapFrameDecode *frame,
|
||||
@ -298,11 +340,16 @@ namespace
|
||||
|
||||
if (!maxsize)
|
||||
{
|
||||
maxsize = D3D12_REQ_TEXTURE2D_U_OR_V_DIMENSION;
|
||||
maxsize = size_t(D3D12_REQ_TEXTURE2D_U_OR_V_DIMENSION);
|
||||
}
|
||||
|
||||
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)
|
||||
@ -317,10 +364,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
|
||||
@ -512,7 +560,8 @@ namespace
|
||||
}
|
||||
|
||||
// Count the number of mips
|
||||
uint32_t mipCount = (loadFlags & (WIC_LOADER_MIP_AUTOGEN|WIC_LOADER_MIP_RESERVE)) ? CountMips(twidth, theight) : 1;
|
||||
uint32_t mipCount = (loadFlags & (WIC_LOADER_MIP_AUTOGEN | WIC_LOADER_MIP_RESERVE))
|
||||
? CountMips(twidth, theight) : 1u;
|
||||
|
||||
// Create texture
|
||||
D3D12_RESOURCE_DESC desc = {};
|
||||
@ -559,7 +608,7 @@ namespace
|
||||
_In_ ID3D12Resource** texture) noexcept
|
||||
{
|
||||
#if !defined(NO_D3D12_DEBUG_NAME) && ( defined(_DEBUG) || defined(PROFILE) )
|
||||
if (texture)
|
||||
if (texture && *texture)
|
||||
{
|
||||
const wchar_t* pstrName = wcsrchr(fileName, '\\');
|
||||
if (!pstrName)
|
||||
@ -571,11 +620,8 @@ namespace
|
||||
pstrName++;
|
||||
}
|
||||
|
||||
if (texture && *texture)
|
||||
{
|
||||
(*texture)->SetName(pstrName);
|
||||
}
|
||||
}
|
||||
#else
|
||||
UNREFERENCED_PARAMETER(fileName);
|
||||
UNREFERENCED_PARAMETER(texture);
|
||||
@ -722,7 +768,11 @@ HRESULT DirectX::LoadWICTextureFromFileEx(
|
||||
|
||||
// Initialize WIC
|
||||
ComPtr<IWICBitmapDecoder> decoder;
|
||||
HRESULT hr = pWIC->CreateDecoderFromFilename(fileName, nullptr, GENERIC_READ, WICDecodeMetadataCacheOnDemand, decoder.GetAddressOf());
|
||||
HRESULT hr = pWIC->CreateDecoderFromFilename(fileName,
|
||||
nullptr,
|
||||
GENERIC_READ,
|
||||
WICDecodeMetadataCacheOnDemand,
|
||||
decoder.GetAddressOf());
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
|
@ -38,6 +38,8 @@ namespace DirectX
|
||||
WIC_LOADER_MIP_AUTOGEN = 0x4,
|
||||
WIC_LOADER_MIP_RESERVE = 0x8,
|
||||
WIC_LOADER_FORCE_RGBA32 = 0x10,
|
||||
WIC_LOADER_FIT_POW2 = 0x20,
|
||||
WIC_LOADER_MAKE_SQUARE = 0x40,
|
||||
};
|
||||
#endif
|
||||
|
||||
|
597
WICTextureLoader/WICTextureLoader9.cpp
Normal file
597
WICTextureLoader/WICTextureLoader9.cpp
Normal file
@ -0,0 +1,597 @@
|
||||
//--------------------------------------------------------------------------------------
|
||||
// File: WICTextureLoader9.cpp
|
||||
//
|
||||
// Function for loading a WIC image and creating a Direct3D runtime texture for it
|
||||
//
|
||||
// Note: Assumes application has already called CoInitializeEx
|
||||
//
|
||||
// Note these functions are useful for images created as simple 2D textures. For
|
||||
// more complex resources, DDSTextureLoader is an excellent light-weight runtime loader.
|
||||
// For a full-featured DDS file reader, writer, and texture processing pipeline see
|
||||
// the 'Texconv' sample and the 'DirectXTex' library.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
//
|
||||
// http://go.microsoft.com/fwlink/?LinkId=248926
|
||||
// http://go.microsoft.com/fwlink/?LinkId=248929
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// We could load multi-frame images (TIFF/GIF) into a texture array.
|
||||
// For now, we just load the first frame (note: DirectXTex supports multi-frame images)
|
||||
|
||||
#include "WICTextureLoader9.h"
|
||||
|
||||
#include <d3d9types.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
|
||||
#include <wincodec.h>
|
||||
|
||||
#include <wrl\client.h>
|
||||
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic ignored "-Wcovered-switch-default"
|
||||
#pragma clang diagnostic ignored "-Wswitch-enum"
|
||||
#endif
|
||||
|
||||
using namespace DirectX;
|
||||
using Microsoft::WRL::ComPtr;
|
||||
|
||||
namespace
|
||||
{
|
||||
//-------------------------------------------------------------------------------------
|
||||
// WIC Pixel Format Translation Data
|
||||
//-------------------------------------------------------------------------------------
|
||||
struct WICTranslate
|
||||
{
|
||||
GUID wic;
|
||||
D3DFORMAT format;
|
||||
};
|
||||
|
||||
const WICTranslate g_WICFormats[] =
|
||||
{
|
||||
{ GUID_WICPixelFormat128bppRGBAFloat, D3DFMT_A32B32G32R32F },
|
||||
|
||||
{ GUID_WICPixelFormat64bppRGBAHalf, D3DFMT_A16B16G16R16F },
|
||||
{ GUID_WICPixelFormat64bppRGBA, D3DFMT_A16B16G16R16 },
|
||||
|
||||
{ GUID_WICPixelFormat32bppBGRA, D3DFMT_A8R8G8B8 },
|
||||
|
||||
{ GUID_WICPixelFormat32bppRGBA1010102, D3DFMT_A2B10G10R10 },
|
||||
|
||||
{ GUID_WICPixelFormat16bppBGRA5551, D3DFMT_A1R5G5B5 },
|
||||
{ GUID_WICPixelFormat16bppBGR555, D3DFMT_X1R5G5B5 },
|
||||
{ GUID_WICPixelFormat16bppBGR565, D3DFMT_R5G6B5 },
|
||||
|
||||
{ GUID_WICPixelFormat32bppGrayFloat, D3DFMT_R32F },
|
||||
{ GUID_WICPixelFormat16bppGrayHalf, D3DFMT_R16F },
|
||||
{ GUID_WICPixelFormat16bppGray, D3DFMT_L16 },
|
||||
{ GUID_WICPixelFormat8bppGray, D3DFMT_L8 },
|
||||
|
||||
{ GUID_WICPixelFormat8bppAlpha, D3DFMT_A8 },
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------------------------
|
||||
// WIC Pixel Format nearest conversion table
|
||||
//-------------------------------------------------------------------------------------
|
||||
|
||||
struct WICConvert
|
||||
{
|
||||
GUID source;
|
||||
GUID target;
|
||||
};
|
||||
|
||||
const WICConvert g_WICConvert[] =
|
||||
{
|
||||
// Note target GUID in this conversion table must be one of those directly supported formats (above).
|
||||
|
||||
{ GUID_WICPixelFormatBlackWhite, GUID_WICPixelFormat8bppGray }, // D3DFMT_L8
|
||||
|
||||
{ GUID_WICPixelFormat1bppIndexed, GUID_WICPixelFormat32bppBGRA }, // D3DFMT_A8R8G8B8
|
||||
{ GUID_WICPixelFormat2bppIndexed, GUID_WICPixelFormat32bppBGRA }, // D3DFMT_A8R8G8B8
|
||||
{ GUID_WICPixelFormat4bppIndexed, GUID_WICPixelFormat32bppBGRA }, // D3DFMT_A8R8G8B8
|
||||
{ GUID_WICPixelFormat8bppIndexed, GUID_WICPixelFormat32bppBGRA }, // D3DFMT_A8R8G8B8
|
||||
|
||||
{ GUID_WICPixelFormat2bppGray, GUID_WICPixelFormat8bppGray }, // D3DFMT_L8
|
||||
{ GUID_WICPixelFormat4bppGray, GUID_WICPixelFormat8bppGray }, // D3DFMT_L8
|
||||
|
||||
{ GUID_WICPixelFormat16bppGrayFixedPoint, GUID_WICPixelFormat16bppGrayHalf }, // D3DFMT_R16F
|
||||
{ GUID_WICPixelFormat32bppGrayFixedPoint, GUID_WICPixelFormat32bppGrayFloat }, // D3DFMT_R32F
|
||||
|
||||
{ GUID_WICPixelFormat32bppBGR101010, GUID_WICPixelFormat32bppRGBA1010102 }, // D3DFMT_A2B10G10R10
|
||||
|
||||
{ GUID_WICPixelFormat24bppBGR, GUID_WICPixelFormat32bppBGRA }, // D3DFMT_A8R8G8B8
|
||||
{ GUID_WICPixelFormat24bppRGB, GUID_WICPixelFormat32bppBGRA }, // D3DFMT_A8R8G8B8
|
||||
{ GUID_WICPixelFormat32bppBGR, GUID_WICPixelFormat32bppBGRA }, // D3DFMT_A8R8G8B8
|
||||
{ GUID_WICPixelFormat32bppRGBA, GUID_WICPixelFormat32bppBGRA }, // D3DFMT_A8R8G8B8
|
||||
{ GUID_WICPixelFormat32bppPBGRA, GUID_WICPixelFormat32bppBGRA }, // D3DFMT_A8R8G8B8
|
||||
{ GUID_WICPixelFormat32bppPRGBA, GUID_WICPixelFormat32bppBGRA }, // D3DFMT_A8R8G8B8
|
||||
|
||||
{ GUID_WICPixelFormat48bppRGB, GUID_WICPixelFormat64bppRGBA }, // D3DFMT_A16B16G16R16
|
||||
{ GUID_WICPixelFormat48bppBGR, GUID_WICPixelFormat64bppRGBA }, // D3DFMT_A16B16G16R16
|
||||
{ GUID_WICPixelFormat64bppBGRA, GUID_WICPixelFormat64bppRGBA }, // D3DFMT_A16B16G16R16
|
||||
{ GUID_WICPixelFormat64bppPRGBA, GUID_WICPixelFormat64bppRGBA }, // D3DFMT_A16B16G16R16
|
||||
{ GUID_WICPixelFormat64bppPBGRA, GUID_WICPixelFormat64bppRGBA }, // D3DFMT_A16B16G16R16
|
||||
|
||||
{ GUID_WICPixelFormat48bppRGBFixedPoint, GUID_WICPixelFormat64bppRGBAHalf }, // D3DFMT_A16B16G16R16F
|
||||
{ GUID_WICPixelFormat48bppBGRFixedPoint, GUID_WICPixelFormat64bppRGBAHalf }, // D3DFMT_A16B16G16R16F
|
||||
{ GUID_WICPixelFormat64bppRGBAFixedPoint, GUID_WICPixelFormat64bppRGBAHalf }, // D3DFMT_A16B16G16R16F
|
||||
{ GUID_WICPixelFormat64bppBGRAFixedPoint, GUID_WICPixelFormat64bppRGBAHalf }, // D3DFMT_A16B16G16R16F
|
||||
{ GUID_WICPixelFormat64bppRGBFixedPoint, GUID_WICPixelFormat64bppRGBAHalf }, // D3DFMT_A16B16G16R16F
|
||||
{ GUID_WICPixelFormat64bppRGBHalf, GUID_WICPixelFormat64bppRGBAHalf }, // D3DFMT_A16B16G16R16F
|
||||
{ GUID_WICPixelFormat48bppRGBHalf, GUID_WICPixelFormat64bppRGBAHalf }, // D3DFMT_A16B16G16R16F
|
||||
|
||||
{ GUID_WICPixelFormat128bppPRGBAFloat, GUID_WICPixelFormat128bppRGBAFloat }, // D3DFMT_A32B32G32R32F
|
||||
{ GUID_WICPixelFormat128bppRGBFloat, GUID_WICPixelFormat128bppRGBAFloat }, // D3DFMT_A32B32G32R32F
|
||||
{ GUID_WICPixelFormat128bppRGBAFixedPoint, GUID_WICPixelFormat128bppRGBAFloat }, // D3DFMT_A32B32G32R32F
|
||||
{ GUID_WICPixelFormat128bppRGBFixedPoint, GUID_WICPixelFormat128bppRGBAFloat }, // D3DFMT_A32B32G32R32F
|
||||
{ GUID_WICPixelFormat32bppRGBE, GUID_WICPixelFormat128bppRGBAFloat }, // D3DFMT_A32B32G32R32F
|
||||
|
||||
{ GUID_WICPixelFormat32bppCMYK, GUID_WICPixelFormat32bppBGRA }, // D3DFMT_A8R8G8B8
|
||||
{ GUID_WICPixelFormat64bppCMYK, GUID_WICPixelFormat64bppRGBA }, // D3DFMT_A16B16G16R16
|
||||
{ GUID_WICPixelFormat40bppCMYKAlpha, GUID_WICPixelFormat32bppBGRA }, // D3DFMT_A8R8G8B8
|
||||
{ GUID_WICPixelFormat80bppCMYKAlpha, GUID_WICPixelFormat64bppRGBA }, // D3DFMT_A16B16G16R16
|
||||
|
||||
#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) || defined(_WIN7_PLATFORM_UPDATE)
|
||||
{ GUID_WICPixelFormat32bppRGB, GUID_WICPixelFormat32bppBGRA }, // D3DFMT_A8R8G8B8
|
||||
{ GUID_WICPixelFormat64bppRGB, GUID_WICPixelFormat64bppRGBA }, // D3DFMT_A16B16G16R16
|
||||
{ GUID_WICPixelFormat64bppPRGBAHalf, GUID_WICPixelFormat64bppRGBAHalf }, // D3DFMT_A16B16G16R16F
|
||||
{ GUID_WICPixelFormat96bppRGBFloat, GUID_WICPixelFormat128bppRGBAFloat }, // D3DFMT_A32B32G32R32F
|
||||
#endif
|
||||
|
||||
// We don't support n-channel formats
|
||||
};
|
||||
|
||||
bool g_WIC2 = false;
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
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;
|
||||
if (!InitOnceExecuteOnce(
|
||||
&s_initOnce,
|
||||
InitializeWICFactory,
|
||||
nullptr,
|
||||
reinterpret_cast<LPVOID*>(&factory)))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return factory;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
D3DFORMAT _WICToD3D9(const GUID& guid) noexcept
|
||||
{
|
||||
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 D3DFMT_UNKNOWN;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
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_ LPDIRECT3DDEVICE9 device,
|
||||
_In_ IWICBitmapFrameDecode *frame,
|
||||
_In_ size_t maxsize,
|
||||
_In_ unsigned int loadFlags,
|
||||
_Outptr_ LPDIRECT3DTEXTURE9* texture) noexcept
|
||||
{
|
||||
UINT width, height;
|
||||
HRESULT hr = frame->GetSize(&width, &height);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
if (maxsize > UINT32_MAX)
|
||||
return E_INVALIDARG;
|
||||
|
||||
assert(width > 0 && height > 0);
|
||||
|
||||
if (!maxsize)
|
||||
{
|
||||
maxsize = 4096u /*D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION*/;
|
||||
}
|
||||
|
||||
assert(maxsize > 0);
|
||||
|
||||
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)
|
||||
{
|
||||
twidth = static_cast<UINT>(maxsize);
|
||||
theight = std::max<UINT>(1, static_cast<UINT>(static_cast<float>(maxsize) * ar));
|
||||
}
|
||||
else
|
||||
{
|
||||
theight = static_cast<UINT>(maxsize);
|
||||
twidth = std::max<UINT>(1, static_cast<UINT>(static_cast<float>(maxsize) / ar));
|
||||
}
|
||||
assert(twidth <= maxsize && theight <= maxsize);
|
||||
}
|
||||
|
||||
if (loadFlags & WIC_LOADER_MAKE_SQUARE)
|
||||
{
|
||||
twidth = std::max<UINT>(twidth, theight);
|
||||
theight = twidth;
|
||||
}
|
||||
|
||||
// Determine format
|
||||
WICPixelFormatGUID pixelFormat;
|
||||
hr = frame->GetPixelFormat(&pixelFormat);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
WICPixelFormatGUID convertGUID;
|
||||
memcpy_s(&convertGUID, sizeof(WICPixelFormatGUID), &pixelFormat, sizeof(GUID));
|
||||
|
||||
D3DFORMAT format = _WICToD3D9(pixelFormat);
|
||||
if (format == D3DFMT_UNKNOWN)
|
||||
{
|
||||
for (size_t i = 0; i < _countof(g_WICConvert); ++i)
|
||||
{
|
||||
if (memcmp(&g_WICConvert[i].source, &pixelFormat, sizeof(WICPixelFormatGUID)) == 0)
|
||||
{
|
||||
memcpy_s(&convertGUID, sizeof(WICPixelFormatGUID), &g_WICConvert[i].target, sizeof(GUID));
|
||||
|
||||
format = _WICToD3D9(g_WICConvert[i].target);
|
||||
assert(format != D3DFMT_UNKNOWN);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (format == D3DFMT_UNKNOWN)
|
||||
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
|
||||
}
|
||||
|
||||
if (loadFlags & WIC_LOADER_FORCE_RGBA32)
|
||||
{
|
||||
memcpy_s(&convertGUID, sizeof(WICPixelFormatGUID), &GUID_WICPixelFormat32bppBGRA, sizeof(GUID));
|
||||
format = D3DFMT_A8R8G8B8;
|
||||
}
|
||||
|
||||
// Create texture
|
||||
ComPtr<IDirect3DTexture9> pTexture;
|
||||
hr = device->CreateTexture(twidth, theight, 1u,
|
||||
(loadFlags & WIC_LOADER_MIP_AUTOGEN) ? D3DUSAGE_AUTOGENMIPMAP : 0u,
|
||||
format, D3DPOOL_DEFAULT,
|
||||
pTexture.GetAddressOf(), nullptr);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
// Create staging texture memory
|
||||
ComPtr<IDirect3DTexture9> pStagingTexture;
|
||||
hr = device->CreateTexture(twidth, theight, 1u,
|
||||
0u, format, D3DPOOL_SYSTEMMEM,
|
||||
pStagingTexture.GetAddressOf(), nullptr);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
D3DLOCKED_RECT LockedRect = {};
|
||||
hr = pStagingTexture->LockRect(0, &LockedRect, nullptr, 0);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
uint64_t numBytes = uint64_t(LockedRect.Pitch) * uint64_t(theight);
|
||||
|
||||
pStagingTexture->UnlockRect(0);
|
||||
|
||||
if (numBytes > UINT32_MAX)
|
||||
{
|
||||
return HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW);
|
||||
}
|
||||
|
||||
// Load image data
|
||||
if (memcmp(&convertGUID, &pixelFormat, sizeof(GUID)) == 0
|
||||
&& twidth == width
|
||||
&& theight == height)
|
||||
{
|
||||
// No format conversion or resize needed
|
||||
hr = pStagingTexture->LockRect(0, &LockedRect, nullptr, 0);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
hr = frame->CopyPixels(nullptr, static_cast<UINT>(LockedRect.Pitch), static_cast<UINT>(numBytes),
|
||||
static_cast<BYTE*>(LockedRect.pBits));
|
||||
|
||||
pStagingTexture->UnlockRect(0);
|
||||
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
}
|
||||
else if (twidth != width || theight != height)
|
||||
{
|
||||
// Resize
|
||||
auto pWIC = _GetWIC();
|
||||
if (!pWIC)
|
||||
return E_NOINTERFACE;
|
||||
|
||||
ComPtr<IWICBitmapScaler> scaler;
|
||||
hr = pWIC->CreateBitmapScaler(scaler.GetAddressOf());
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
hr = scaler->Initialize(frame, twidth, theight, WICBitmapInterpolationModeFant);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
WICPixelFormatGUID pfScaler;
|
||||
hr = scaler->GetPixelFormat(&pfScaler);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
if (memcmp(&convertGUID, &pfScaler, sizeof(GUID)) == 0)
|
||||
{
|
||||
// No format conversion needed
|
||||
hr = pStagingTexture->LockRect(0, &LockedRect, nullptr, 0);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
hr = scaler->CopyPixels(nullptr, static_cast<UINT>(LockedRect.Pitch), static_cast<UINT>(numBytes),
|
||||
static_cast<BYTE*>(LockedRect.pBits));
|
||||
|
||||
pStagingTexture->UnlockRect(0);
|
||||
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
}
|
||||
else
|
||||
{
|
||||
ComPtr<IWICFormatConverter> FC;
|
||||
hr = pWIC->CreateFormatConverter(FC.GetAddressOf());
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
BOOL canConvert = FALSE;
|
||||
hr = FC->CanConvert(pfScaler, convertGUID, &canConvert);
|
||||
if (FAILED(hr) || !canConvert)
|
||||
{
|
||||
return E_UNEXPECTED;
|
||||
}
|
||||
|
||||
hr = FC->Initialize(scaler.Get(), convertGUID, WICBitmapDitherTypeErrorDiffusion, nullptr, 0, WICBitmapPaletteTypeMedianCut);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
hr = pStagingTexture->LockRect(0, &LockedRect, nullptr, 0);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
hr = FC->CopyPixels(nullptr, static_cast<UINT>(LockedRect.Pitch), static_cast<UINT>(numBytes),
|
||||
static_cast<BYTE*>(LockedRect.pBits));
|
||||
|
||||
pStagingTexture->UnlockRect(0);
|
||||
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Format conversion but no resize
|
||||
auto pWIC = _GetWIC();
|
||||
if (!pWIC)
|
||||
return E_NOINTERFACE;
|
||||
|
||||
ComPtr<IWICFormatConverter> FC;
|
||||
hr = pWIC->CreateFormatConverter(FC.GetAddressOf());
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
BOOL canConvert = FALSE;
|
||||
hr = FC->CanConvert(pixelFormat, convertGUID, &canConvert);
|
||||
if (FAILED(hr) || !canConvert)
|
||||
{
|
||||
return E_UNEXPECTED;
|
||||
}
|
||||
|
||||
hr = FC->Initialize(frame, convertGUID, WICBitmapDitherTypeErrorDiffusion, nullptr, 0, WICBitmapPaletteTypeMedianCut);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
hr = pStagingTexture->LockRect(0, &LockedRect, nullptr, 0);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
hr = FC->CopyPixels(nullptr, static_cast<UINT>(LockedRect.Pitch), static_cast<UINT>(numBytes),
|
||||
static_cast<BYTE*>(LockedRect.pBits));
|
||||
|
||||
pStagingTexture->UnlockRect(0);
|
||||
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
}
|
||||
|
||||
hr = device->UpdateTexture(pStagingTexture.Get(), pTexture.Get());
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
*texture = pTexture.Detach();
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
} // anonymous namespace
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
_Use_decl_annotations_
|
||||
HRESULT DirectX::CreateWICTextureFromMemory(
|
||||
LPDIRECT3DDEVICE9 d3dDevice,
|
||||
const uint8_t* wicData,
|
||||
size_t wicDataSize,
|
||||
LPDIRECT3DTEXTURE9* texture,
|
||||
size_t maxsize,
|
||||
unsigned int loadFlags) noexcept
|
||||
{
|
||||
if (texture)
|
||||
{
|
||||
*texture = nullptr;
|
||||
}
|
||||
|
||||
if (!d3dDevice || !wicData || !wicDataSize || !texture)
|
||||
return E_INVALIDARG;
|
||||
|
||||
if (!wicDataSize)
|
||||
return E_FAIL;
|
||||
|
||||
if (wicDataSize > UINT32_MAX)
|
||||
return HRESULT_FROM_WIN32(ERROR_FILE_TOO_LARGE);
|
||||
|
||||
auto pWIC = _GetWIC();
|
||||
if (!pWIC)
|
||||
return E_NOINTERFACE;
|
||||
|
||||
// Create input stream for memory
|
||||
ComPtr<IWICStream> stream;
|
||||
HRESULT hr = pWIC->CreateStream(stream.GetAddressOf());
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
hr = stream->InitializeFromMemory(const_cast<uint8_t*>(wicData), static_cast<DWORD>(wicDataSize));
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
// Initialize WIC
|
||||
ComPtr<IWICBitmapDecoder> decoder;
|
||||
hr = pWIC->CreateDecoderFromStream(stream.Get(), nullptr, WICDecodeMetadataCacheOnDemand, decoder.GetAddressOf());
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
ComPtr<IWICBitmapFrameDecode> frame;
|
||||
hr = decoder->GetFrame(0, frame.GetAddressOf());
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
return CreateTextureFromWIC(d3dDevice, frame.Get(), maxsize, loadFlags, texture);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
_Use_decl_annotations_
|
||||
HRESULT DirectX::CreateWICTextureFromFile(
|
||||
LPDIRECT3DDEVICE9 d3dDevice,
|
||||
const wchar_t* fileName,
|
||||
LPDIRECT3DTEXTURE9* texture,
|
||||
size_t maxsize,
|
||||
unsigned int loadFlags) noexcept
|
||||
{
|
||||
if (texture)
|
||||
{
|
||||
*texture = nullptr;
|
||||
}
|
||||
|
||||
if (!d3dDevice || !fileName || !texture)
|
||||
return E_INVALIDARG;
|
||||
|
||||
auto pWIC = _GetWIC();
|
||||
if (!pWIC)
|
||||
return E_NOINTERFACE;
|
||||
|
||||
// Initialize WIC
|
||||
ComPtr<IWICBitmapDecoder> decoder;
|
||||
HRESULT hr = pWIC->CreateDecoderFromFilename(fileName,
|
||||
nullptr,
|
||||
GENERIC_READ,
|
||||
WICDecodeMetadataCacheOnDemand,
|
||||
decoder.GetAddressOf());
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
ComPtr<IWICBitmapFrameDecode> frame;
|
||||
hr = decoder->GetFrame(0, frame.GetAddressOf());
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
return CreateTextureFromWIC(d3dDevice, frame.Get(), maxsize, loadFlags, texture);
|
||||
}
|
58
WICTextureLoader/WICTextureLoader9.h
Normal file
58
WICTextureLoader/WICTextureLoader9.h
Normal file
@ -0,0 +1,58 @@
|
||||
//--------------------------------------------------------------------------------------
|
||||
// File: WICTextureLoader9.h
|
||||
//
|
||||
// Function for loading a WIC image and creating a Direct3D runtime texture for it
|
||||
// (auto-generating mipmaps if possible)
|
||||
//
|
||||
// Note: Assumes application has already called CoInitializeEx
|
||||
//
|
||||
// Note these functions are useful for images created as simple 2D textures. For
|
||||
// more complex resources, DDSTextureLoader is an excellent light-weight runtime loader.
|
||||
// For a full-featured DDS file reader, writer, and texture processing pipeline see
|
||||
// the 'Texconv' sample and the 'DirectXTex' library.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
//
|
||||
// http://go.microsoft.com/fwlink/?LinkId=248926
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef DIRECT3D_VERSION
|
||||
#define DIRECT3D_VERSION 0x900
|
||||
#endif
|
||||
#include <d3d9.h>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace DirectX
|
||||
{
|
||||
#ifndef WIC_LOADER_FLAGS_DEFINED
|
||||
#define WIC_LOADER_FLAGS_DEFINED
|
||||
enum WIC_LOADER_FLAGS : uint32_t
|
||||
{
|
||||
WIC_LOADER_DEFAULT = 0,
|
||||
WIC_LOADER_MIP_AUTOGEN = 0x4,
|
||||
WIC_LOADER_FORCE_RGBA32 = 0x10,
|
||||
WIC_LOADER_FIT_POW2 = 0x20,
|
||||
WIC_LOADER_MAKE_SQUARE = 0x40,
|
||||
};
|
||||
#endif
|
||||
|
||||
// Standard version
|
||||
HRESULT CreateWICTextureFromMemory(
|
||||
_In_ LPDIRECT3DDEVICE9 d3dDevice,
|
||||
_In_reads_bytes_(wicDataSize) const uint8_t* wicData,
|
||||
_In_ size_t wicDataSize,
|
||||
_Outptr_ LPDIRECT3DTEXTURE9* texture,
|
||||
_In_ size_t maxsize = 0,
|
||||
_In_ unsigned int loadFlags = 0) noexcept;
|
||||
|
||||
HRESULT CreateWICTextureFromFile(
|
||||
_In_ LPDIRECT3DDEVICE9 d3dDevice,
|
||||
_In_z_ const wchar_t* fileName,
|
||||
_Outptr_ LPDIRECT3DTEXTURE9* texture,
|
||||
_In_ size_t maxsize = 0,
|
||||
_In_ unsigned int loadFlags = 0) noexcept;
|
||||
}
|
Loading…
Reference in New Issue
Block a user