From f2e065dee10fb110e9d51175ee6381333319ef56 Mon Sep 17 00:00:00 2001 From: Egor Yusov Date: Tue, 20 Oct 2015 21:05:29 -0700 Subject: Release v1.0.0 --- TextureLoader/build/Windows/EngineRoot.props | 30 + .../build/Windows/TextureLoader-Debug.vgdbsettings | 76 + .../Windows/TextureLoader-Release.vgdbsettings | 76 + TextureLoader/build/Windows/TextureLoader.props | 10 + TextureLoader/build/Windows/TextureLoader.vcxproj | 204 +++ .../build/Windows/TextureLoader.vcxproj.filters | 37 + TextureLoader/build/Windows/jni/Android.mk | 37 + TextureLoader/build/Windows/jni/Application.mk | 7 + TextureLoader/build/WindowsStore/EngineRoot.props | 30 + .../TextureLoader.Shared.vcxitems | 36 + .../TextureLoader.Shared.vcxitems.filters | 51 + .../TextureLoader.Windows.vcxproj | 205 +++ .../TextureLoader.Windows.vcxproj.filters | 5 + .../TextureLoader.WindowsPhone.vcxproj | 144 ++ .../TextureLoader.WindowsPhone.vcxproj.filters | 5 + TextureLoader/include/DDSLoader.h | 70 + TextureLoader/include/dxgiformat.h | 154 ++ TextureLoader/include/pch.h | 30 + TextureLoader/interface/Image.h | 82 ++ TextureLoader/interface/TextureLoader.h | 61 + TextureLoader/interface/TextureUtilities.h | 46 + TextureLoader/src/DDSLoader.cpp | 1489 ++++++++++++++++++++ TextureLoader/src/Image.cpp | 409 ++++++ TextureLoader/src/TextureLoader.cpp | 248 ++++ TextureLoader/src/TextureUtilities.cpp | 95 ++ TextureLoader/src/pch.cpp | 25 + 26 files changed, 3662 insertions(+) create mode 100644 TextureLoader/build/Windows/EngineRoot.props create mode 100644 TextureLoader/build/Windows/TextureLoader-Debug.vgdbsettings create mode 100644 TextureLoader/build/Windows/TextureLoader-Release.vgdbsettings create mode 100644 TextureLoader/build/Windows/TextureLoader.props create mode 100644 TextureLoader/build/Windows/TextureLoader.vcxproj create mode 100644 TextureLoader/build/Windows/TextureLoader.vcxproj.filters create mode 100644 TextureLoader/build/Windows/jni/Android.mk create mode 100644 TextureLoader/build/Windows/jni/Application.mk create mode 100644 TextureLoader/build/WindowsStore/EngineRoot.props create mode 100644 TextureLoader/build/WindowsStore/TextureLoader.Shared/TextureLoader.Shared.vcxitems create mode 100644 TextureLoader/build/WindowsStore/TextureLoader.Shared/TextureLoader.Shared.vcxitems.filters create mode 100644 TextureLoader/build/WindowsStore/TextureLoader.Windows/TextureLoader.Windows.vcxproj create mode 100644 TextureLoader/build/WindowsStore/TextureLoader.Windows/TextureLoader.Windows.vcxproj.filters create mode 100644 TextureLoader/build/WindowsStore/TextureLoader.WindowsPhone/TextureLoader.WindowsPhone.vcxproj create mode 100644 TextureLoader/build/WindowsStore/TextureLoader.WindowsPhone/TextureLoader.WindowsPhone.vcxproj.filters create mode 100644 TextureLoader/include/DDSLoader.h create mode 100644 TextureLoader/include/dxgiformat.h create mode 100644 TextureLoader/include/pch.h create mode 100644 TextureLoader/interface/Image.h create mode 100644 TextureLoader/interface/TextureLoader.h create mode 100644 TextureLoader/interface/TextureUtilities.h create mode 100644 TextureLoader/src/DDSLoader.cpp create mode 100644 TextureLoader/src/Image.cpp create mode 100644 TextureLoader/src/TextureLoader.cpp create mode 100644 TextureLoader/src/TextureUtilities.cpp create mode 100644 TextureLoader/src/pch.cpp (limited to 'TextureLoader') diff --git a/TextureLoader/build/Windows/EngineRoot.props b/TextureLoader/build/Windows/EngineRoot.props new file mode 100644 index 0000000..f6bd042 --- /dev/null +++ b/TextureLoader/build/Windows/EngineRoot.props @@ -0,0 +1,30 @@ + + + + + ..\.. + ..\..\..\.. + $(EngineRoot)\diligentcore + $(CoreRoot)\Graphics + $(ProjectRoot)\.. + + + + + + $(ProjectRoot) + + + $(EngineRoot) + + + $(CoreRoot) + + + $(GraphicsRoot) + + + $(ToolsRoot) + + + \ No newline at end of file diff --git a/TextureLoader/build/Windows/TextureLoader-Debug.vgdbsettings b/TextureLoader/build/Windows/TextureLoader-Debug.vgdbsettings new file mode 100644 index 0000000..3f5b24b --- /dev/null +++ b/TextureLoader/build/Windows/TextureLoader-Debug.vgdbsettings @@ -0,0 +1,76 @@ + + + Debug + + + + MinGWWindowsSlash + + $(ProjectDir) + + + android-19 + true + true + bin;obj + false + false + + + + + + false + false + true + false + false + false + false + true + false + KillApp + + false + false + false + false + false + false + false + false + + false + false + main + true + + + false + false + 5039 + 5039 + 10000 + 0 + false + Ask + true + true + + + + + + + + + + + Default + + + + true + + + \ No newline at end of file diff --git a/TextureLoader/build/Windows/TextureLoader-Release.vgdbsettings b/TextureLoader/build/Windows/TextureLoader-Release.vgdbsettings new file mode 100644 index 0000000..669691f --- /dev/null +++ b/TextureLoader/build/Windows/TextureLoader-Release.vgdbsettings @@ -0,0 +1,76 @@ + + + Release + + + + MinGWWindowsSlash + + $(ProjectDir) + + + android-19 + false + true + bin;obj + false + false + + + + + + false + false + true + false + false + false + false + true + false + KillApp + + false + false + false + false + false + false + false + false + + false + false + main + true + + + false + false + 5039 + 5039 + 10000 + 0 + false + Ask + true + true + + + + + + + + + + + Default + + + + true + + + \ No newline at end of file diff --git a/TextureLoader/build/Windows/TextureLoader.props b/TextureLoader/build/Windows/TextureLoader.props new file mode 100644 index 0000000..a202be5 --- /dev/null +++ b/TextureLoader/build/Windows/TextureLoader.props @@ -0,0 +1,10 @@ + + + + + + $(ProjectRoot)\include;$(ProjectRoot)\interface;$(CoreRoot)\Common\interface;$(CoreRoot)\Common\include;$(CoreRoot)\Platforms\interface;$(GraphicsRoot)\GraphicsEngine\interface;$(GraphicsRoot)\GraphicsTools\include;$(ToolsRoot)\External\libtiff-4.0.3\libtiff;$(ToolsRoot)\External\lpng-1.6.17;$(ToolsRoot)\External\zlib-1.2.8;$(ToolsRoot)\External\libjpeg-9a;$(IncludePath) + + + + \ No newline at end of file diff --git a/TextureLoader/build/Windows/TextureLoader.vcxproj b/TextureLoader/build/Windows/TextureLoader.vcxproj new file mode 100644 index 0000000..38b73f1 --- /dev/null +++ b/TextureLoader/build/Windows/TextureLoader.vcxproj @@ -0,0 +1,204 @@ + + + + + Debug + ARM + + + Debug + Win32 + + + Debug + x64 + + + Release + ARM + + + Release + Win32 + + + Release + x64 + + + + + true + true + true + true + + + true + true + true + true + + + Create + Create + Create + Create + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + + + + + + {3DE4FDB9-DF4D-4B57-9FFE-616704D4FE2F} + Win32Proj + TextureLoader + + + + StaticLibrary + true + v140 + Unicode + + + StaticLibrary + true + v140 + Unicode + + + StaticLibrary + false + v140 + true + Unicode + + + StaticLibrary + false + v140 + true + Unicode + + + v120 + Makefile + + + v120 + Makefile + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Use + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + + + Windows + true + + + + + Use + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + + + Windows + true + + + + + Level3 + Use + MaxSpeed + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + + + Windows + true + true + true + + + + + Level3 + Use + MaxSpeed + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + + + Windows + true + true + true + + + + + + \ No newline at end of file diff --git a/TextureLoader/build/Windows/TextureLoader.vcxproj.filters b/TextureLoader/build/Windows/TextureLoader.vcxproj.filters new file mode 100644 index 0000000..cfb971d --- /dev/null +++ b/TextureLoader/build/Windows/TextureLoader.vcxproj.filters @@ -0,0 +1,37 @@ + + + + + {9aae993e-4783-459d-acd3-791162b94c61} + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + + + android_src + + + android_src + + + android_src + + + android_src + + + android_src + + + + + jni + + + jni + + + \ No newline at end of file diff --git a/TextureLoader/build/Windows/jni/Android.mk b/TextureLoader/build/Windows/jni/Android.mk new file mode 100644 index 0000000..2e99915 --- /dev/null +++ b/TextureLoader/build/Windows/jni/Android.mk @@ -0,0 +1,37 @@ +# Android NDK project makefile autogenerated by Premake + +# Preamble +DEPENDENCY_PATH := $(call my-dir) +LOCAL_PATH := $(abspath $(DEPENDENCY_PATH)) +include $(CLEAR_VARS) + + +# Project configuration +LOCAL_MODULE := TextureLoader +LOCAL_CFLAGS := -std=c++11 +LOCAL_CPP_FEATURES := exceptions +LOCAL_STATIC_LIBRARIES += + +# Include paths +PROJECT_ROOT := $(LOCAL_PATH)/../../.. +REPO_ROOT := $(PROJECT_ROOT)/.. +ENGINE_ROOT := $(REPO_ROOT)/.. +CORE_ROOT := $(ENGINE_ROOT)/diligentcore +GRAPHICS_ROOT := $(CORE_ROOT)/graphics +LOCAL_C_INCLUDES += $(PROJECT_ROOT)/include +LOCAL_C_INCLUDES += $(PROJECT_ROOT)/interface +LOCAL_C_INCLUDES += $(CORE_ROOT)/Common/include +LOCAL_C_INCLUDES += $(CORE_ROOT)/Common/interface +LOCAL_C_INCLUDES += $(CORE_ROOT)/Platforms/interface +LOCAL_C_INCLUDES += $(GRAPHICS_ROOT)/GraphicsEngine/interface +LOCAL_C_INCLUDES += $(GRAPHICS_ROOT)/GraphicsTools/include +LOCAL_C_INCLUDES += $(REPO_ROOT)/External/libtiff-4.0.3/libtiff +LOCAL_C_INCLUDES += $(REPO_ROOT)/External/lpng-1.6.17 +LOCAL_C_INCLUDES += $(REPO_ROOT)/External/libjpeg-9a +LOCAL_C_INCLUDES += $(REPO_ROOT)/External/zlib-1.2.8 + +# Source files +#VisualGDBAndroid: AutoUpdateSourcesInNextLine +LOCAL_SRC_FILES := ../../../src/DDSLoader.cpp ../../../src/Image.cpp ../../../src/pch.cpp ../../../src/TextureLoader.cpp ../../../src/TextureUtilities.cpp + +include $(BUILD_STATIC_LIBRARY) diff --git a/TextureLoader/build/Windows/jni/Application.mk b/TextureLoader/build/Windows/jni/Application.mk new file mode 100644 index 0000000..221d4b0 --- /dev/null +++ b/TextureLoader/build/Windows/jni/Application.mk @@ -0,0 +1,7 @@ +# Generated by VisualGDB + +DEPENDENCY_PATH := $(call my-dir) +LOCAL_PATH := $(abspath $(DEPENDENCY_PATH)) +include $(LOCAL_PATH)/../../../../../diligentcore/Common/make/AppCommon.mk + +APP_MODULES := TextureLoader \ No newline at end of file diff --git a/TextureLoader/build/WindowsStore/EngineRoot.props b/TextureLoader/build/WindowsStore/EngineRoot.props new file mode 100644 index 0000000..79dc389 --- /dev/null +++ b/TextureLoader/build/WindowsStore/EngineRoot.props @@ -0,0 +1,30 @@ + + + + + ..\..\.. + $(ProjectRoot)\.. + $(ToolsRoot)\.. + $(EngineRoot)\diligentcore + $(CoreRoot)\Graphics + + + + + + $(ProjectRoot) + + + $(ToolsRoot) + + + $(EngineRoot) + + + $(CoreRoot) + + + $(GraphicsRoot) + + + \ No newline at end of file diff --git a/TextureLoader/build/WindowsStore/TextureLoader.Shared/TextureLoader.Shared.vcxitems b/TextureLoader/build/WindowsStore/TextureLoader.Shared/TextureLoader.Shared.vcxitems new file mode 100644 index 0000000..bd4f2e5 --- /dev/null +++ b/TextureLoader/build/WindowsStore/TextureLoader.Shared/TextureLoader.Shared.vcxitems @@ -0,0 +1,36 @@ + + + + $(MSBuildAllProjects);$(MSBuildThisFileFullPath) + true + {149d2147-99ec-471e-a8cf-d894e0d11eda} + TextureLoader + TextureLoader.Shared + 248F659F-DAC5-46E8-AC09-60EC9FC95053 + + + + %(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory) + + + + + + + + + + + + + + + + + + Create + + + + + \ No newline at end of file diff --git a/TextureLoader/build/WindowsStore/TextureLoader.Shared/TextureLoader.Shared.vcxitems.filters b/TextureLoader/build/WindowsStore/TextureLoader.Shared/TextureLoader.Shared.vcxitems.filters new file mode 100644 index 0000000..a21e336 --- /dev/null +++ b/TextureLoader/build/WindowsStore/TextureLoader.Shared/TextureLoader.Shared.vcxitems.filters @@ -0,0 +1,51 @@ + + + + + {6588a729-c4b5-4470-b888-6be61248b64c} + + + {304ad504-120b-4e87-bfb9-b00d4f1cf0db} + + + {27789a26-7643-4bca-af3b-4d55c34cd456} + + + + + include + + + include + + + include + + + interface + + + interface + + + include + + + + + src + + + src + + + src + + + src + + + src + + + \ No newline at end of file diff --git a/TextureLoader/build/WindowsStore/TextureLoader.Windows/TextureLoader.Windows.vcxproj b/TextureLoader/build/WindowsStore/TextureLoader.Windows/TextureLoader.Windows.vcxproj new file mode 100644 index 0000000..108f536 --- /dev/null +++ b/TextureLoader/build/WindowsStore/TextureLoader.Windows/TextureLoader.Windows.vcxproj @@ -0,0 +1,205 @@ + + + + + Debug + ARM + + + Debug + Win32 + + + Debug + x64 + + + Release + ARM + + + Release + Win32 + + + Release + x64 + + + + {742b0d32-3535-4382-be47-65c179cd544c} + TextureLoader + en-US + 12.0 + true + Windows Store + 8.1 + CodeSharingStaticLibrary + + + + StaticLibrary + true + v120 + + + StaticLibrary + true + v120 + + + StaticLibrary + true + v120 + + + StaticLibrary + false + true + v120 + + + StaticLibrary + false + true + v120 + + + StaticLibrary + false + true + v120 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + false + + + false + + + false + + + false + + + false + + + false + + + + Use + false + true + + + Console + false + false + + + + + Use + false + true + + + Console + false + false + + + + + Use + false + true + + + Console + false + false + + + + + Use + false + true + + + Console + false + false + + + + + Use + false + true + + + Console + false + false + + + + + Use + false + true + + + Console + false + false + + + + + + \ No newline at end of file diff --git a/TextureLoader/build/WindowsStore/TextureLoader.Windows/TextureLoader.Windows.vcxproj.filters b/TextureLoader/build/WindowsStore/TextureLoader.Windows/TextureLoader.Windows.vcxproj.filters new file mode 100644 index 0000000..a7761ab --- /dev/null +++ b/TextureLoader/build/WindowsStore/TextureLoader.Windows/TextureLoader.Windows.vcxproj.filters @@ -0,0 +1,5 @@ + + + + + diff --git a/TextureLoader/build/WindowsStore/TextureLoader.WindowsPhone/TextureLoader.WindowsPhone.vcxproj b/TextureLoader/build/WindowsStore/TextureLoader.WindowsPhone/TextureLoader.WindowsPhone.vcxproj new file mode 100644 index 0000000..5f8ec42 --- /dev/null +++ b/TextureLoader/build/WindowsStore/TextureLoader.WindowsPhone/TextureLoader.WindowsPhone.vcxproj @@ -0,0 +1,144 @@ + + + + + Debug + ARM + + + Debug + Win32 + + + Release + ARM + + + Release + Win32 + + + + {d12eaf5b-1fee-4740-8ec3-7240760211b9} + TextureLoader + en-US + 12.0 + true + Windows Phone + 8.1 + CodeSharingStaticLibrary + + + + StaticLibrary + true + v120_wp81 + + + StaticLibrary + true + v120_wp81 + + + StaticLibrary + false + true + v120_wp81 + + + StaticLibrary + false + true + v120_wp81 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + false + + + false + + + false + + + false + + + + Use + false + true + + + Console + false + false + + + + + Use + false + true + + + Console + false + false + + + + + Use + false + true + + + Console + false + false + + + + + Use + false + true + + + Console + false + false + + + + + + \ No newline at end of file diff --git a/TextureLoader/build/WindowsStore/TextureLoader.WindowsPhone/TextureLoader.WindowsPhone.vcxproj.filters b/TextureLoader/build/WindowsStore/TextureLoader.WindowsPhone/TextureLoader.WindowsPhone.vcxproj.filters new file mode 100644 index 0000000..a7761ab --- /dev/null +++ b/TextureLoader/build/WindowsStore/TextureLoader.WindowsPhone/TextureLoader.WindowsPhone.vcxproj.filters @@ -0,0 +1,5 @@ + + + + + diff --git a/TextureLoader/include/DDSLoader.h b/TextureLoader/include/DDSLoader.h new file mode 100644 index 0000000..93cebe9 --- /dev/null +++ b/TextureLoader/include/DDSLoader.h @@ -0,0 +1,70 @@ +/* Copyright 2015 Egor Yusov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +//-------------------------------------------------------------------------------------- +// File: DDSLoader.h +// +// Functions for loading a DDS texture and creating a Direct3D 11 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. +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkId=248926 +// http://go.microsoft.com/fwlink/?LinkId=248929 +//-------------------------------------------------------------------------------------- + +#pragma once + +#include "RenderDevice.h" +#include "Texture.h" + +void CreateDDSTextureFromMemory( + Diligent::IRenderDevice* pDevice, + const Diligent::Uint8* ddsData, + size_t ddsDataSize, + Diligent::ITexture** texture, + size_t maxsize/*, + D2D1_ALPHA_MODE* alphaMode*/ + ); + +void CreateDDSTextureFromMemoryEx( + Diligent::IRenderDevice* pDevice, + const Diligent::Uint8* ddsData, + size_t ddsDataSize, + size_t maxsize, + Diligent::USAGE usage, + unsigned int bindFlags, + unsigned int cpuAccessFlags, + unsigned int miscFlags, + bool forceSRGB, + Diligent::ITexture** texture/*, + D2D1_ALPHA_MODE* alphaMode*/ + ); diff --git a/TextureLoader/include/dxgiformat.h b/TextureLoader/include/dxgiformat.h new file mode 100644 index 0000000..12f5539 --- /dev/null +++ b/TextureLoader/include/dxgiformat.h @@ -0,0 +1,154 @@ +/* Copyright 2015 Egor Yusov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +// +// Copyright (C) Microsoft. All rights reserved. +// + +#ifndef __dxgiformat_h__ +#define __dxgiformat_h__ + +#define DXGI_FORMAT_DEFINED 1 + +typedef enum DXGI_FORMAT +{ + DXGI_FORMAT_UNKNOWN = 0, + DXGI_FORMAT_R32G32B32A32_TYPELESS = 1, + DXGI_FORMAT_R32G32B32A32_FLOAT = 2, + DXGI_FORMAT_R32G32B32A32_UINT = 3, + DXGI_FORMAT_R32G32B32A32_SINT = 4, + DXGI_FORMAT_R32G32B32_TYPELESS = 5, + DXGI_FORMAT_R32G32B32_FLOAT = 6, + DXGI_FORMAT_R32G32B32_UINT = 7, + DXGI_FORMAT_R32G32B32_SINT = 8, + DXGI_FORMAT_R16G16B16A16_TYPELESS = 9, + DXGI_FORMAT_R16G16B16A16_FLOAT = 10, + DXGI_FORMAT_R16G16B16A16_UNORM = 11, + DXGI_FORMAT_R16G16B16A16_UINT = 12, + DXGI_FORMAT_R16G16B16A16_SNORM = 13, + DXGI_FORMAT_R16G16B16A16_SINT = 14, + DXGI_FORMAT_R32G32_TYPELESS = 15, + DXGI_FORMAT_R32G32_FLOAT = 16, + DXGI_FORMAT_R32G32_UINT = 17, + DXGI_FORMAT_R32G32_SINT = 18, + DXGI_FORMAT_R32G8X24_TYPELESS = 19, + DXGI_FORMAT_D32_FLOAT_S8X24_UINT = 20, + DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS = 21, + DXGI_FORMAT_X32_TYPELESS_G8X24_UINT = 22, + DXGI_FORMAT_R10G10B10A2_TYPELESS = 23, + DXGI_FORMAT_R10G10B10A2_UNORM = 24, + DXGI_FORMAT_R10G10B10A2_UINT = 25, + DXGI_FORMAT_R11G11B10_FLOAT = 26, + DXGI_FORMAT_R8G8B8A8_TYPELESS = 27, + DXGI_FORMAT_R8G8B8A8_UNORM = 28, + DXGI_FORMAT_R8G8B8A8_UNORM_SRGB = 29, + DXGI_FORMAT_R8G8B8A8_UINT = 30, + DXGI_FORMAT_R8G8B8A8_SNORM = 31, + DXGI_FORMAT_R8G8B8A8_SINT = 32, + DXGI_FORMAT_R16G16_TYPELESS = 33, + DXGI_FORMAT_R16G16_FLOAT = 34, + DXGI_FORMAT_R16G16_UNORM = 35, + DXGI_FORMAT_R16G16_UINT = 36, + DXGI_FORMAT_R16G16_SNORM = 37, + DXGI_FORMAT_R16G16_SINT = 38, + DXGI_FORMAT_R32_TYPELESS = 39, + DXGI_FORMAT_D32_FLOAT = 40, + DXGI_FORMAT_R32_FLOAT = 41, + DXGI_FORMAT_R32_UINT = 42, + DXGI_FORMAT_R32_SINT = 43, + DXGI_FORMAT_R24G8_TYPELESS = 44, + DXGI_FORMAT_D24_UNORM_S8_UINT = 45, + DXGI_FORMAT_R24_UNORM_X8_TYPELESS = 46, + DXGI_FORMAT_X24_TYPELESS_G8_UINT = 47, + DXGI_FORMAT_R8G8_TYPELESS = 48, + DXGI_FORMAT_R8G8_UNORM = 49, + DXGI_FORMAT_R8G8_UINT = 50, + DXGI_FORMAT_R8G8_SNORM = 51, + DXGI_FORMAT_R8G8_SINT = 52, + DXGI_FORMAT_R16_TYPELESS = 53, + DXGI_FORMAT_R16_FLOAT = 54, + DXGI_FORMAT_D16_UNORM = 55, + DXGI_FORMAT_R16_UNORM = 56, + DXGI_FORMAT_R16_UINT = 57, + DXGI_FORMAT_R16_SNORM = 58, + DXGI_FORMAT_R16_SINT = 59, + DXGI_FORMAT_R8_TYPELESS = 60, + DXGI_FORMAT_R8_UNORM = 61, + DXGI_FORMAT_R8_UINT = 62, + DXGI_FORMAT_R8_SNORM = 63, + DXGI_FORMAT_R8_SINT = 64, + DXGI_FORMAT_A8_UNORM = 65, + DXGI_FORMAT_R1_UNORM = 66, + DXGI_FORMAT_R9G9B9E5_SHAREDEXP = 67, + DXGI_FORMAT_R8G8_B8G8_UNORM = 68, + DXGI_FORMAT_G8R8_G8B8_UNORM = 69, + DXGI_FORMAT_BC1_TYPELESS = 70, + DXGI_FORMAT_BC1_UNORM = 71, + DXGI_FORMAT_BC1_UNORM_SRGB = 72, + DXGI_FORMAT_BC2_TYPELESS = 73, + DXGI_FORMAT_BC2_UNORM = 74, + DXGI_FORMAT_BC2_UNORM_SRGB = 75, + DXGI_FORMAT_BC3_TYPELESS = 76, + DXGI_FORMAT_BC3_UNORM = 77, + DXGI_FORMAT_BC3_UNORM_SRGB = 78, + DXGI_FORMAT_BC4_TYPELESS = 79, + DXGI_FORMAT_BC4_UNORM = 80, + DXGI_FORMAT_BC4_SNORM = 81, + DXGI_FORMAT_BC5_TYPELESS = 82, + DXGI_FORMAT_BC5_UNORM = 83, + DXGI_FORMAT_BC5_SNORM = 84, + DXGI_FORMAT_B5G6R5_UNORM = 85, + DXGI_FORMAT_B5G5R5A1_UNORM = 86, + DXGI_FORMAT_B8G8R8A8_UNORM = 87, + DXGI_FORMAT_B8G8R8X8_UNORM = 88, + DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM = 89, + DXGI_FORMAT_B8G8R8A8_TYPELESS = 90, + DXGI_FORMAT_B8G8R8A8_UNORM_SRGB = 91, + DXGI_FORMAT_B8G8R8X8_TYPELESS = 92, + DXGI_FORMAT_B8G8R8X8_UNORM_SRGB = 93, + DXGI_FORMAT_BC6H_TYPELESS = 94, + DXGI_FORMAT_BC6H_UF16 = 95, + DXGI_FORMAT_BC6H_SF16 = 96, + DXGI_FORMAT_BC7_TYPELESS = 97, + DXGI_FORMAT_BC7_UNORM = 98, + DXGI_FORMAT_BC7_UNORM_SRGB = 99, + DXGI_FORMAT_AYUV = 100, + DXGI_FORMAT_Y410 = 101, + DXGI_FORMAT_Y416 = 102, + DXGI_FORMAT_NV12 = 103, + DXGI_FORMAT_P010 = 104, + DXGI_FORMAT_P016 = 105, + DXGI_FORMAT_420_OPAQUE = 106, + DXGI_FORMAT_YUY2 = 107, + DXGI_FORMAT_Y210 = 108, + DXGI_FORMAT_Y216 = 109, + DXGI_FORMAT_NV11 = 110, + DXGI_FORMAT_AI44 = 111, + DXGI_FORMAT_IA44 = 112, + DXGI_FORMAT_P8 = 113, + DXGI_FORMAT_A8P8 = 114, + DXGI_FORMAT_B4G4R4A4_UNORM = 115, + DXGI_FORMAT_FORCE_UINT = 0xffffffff +} DXGI_FORMAT; + +#endif // __dxgiformat_h__ diff --git a/TextureLoader/include/pch.h b/TextureLoader/include/pch.h new file mode 100644 index 0000000..25b03a3 --- /dev/null +++ b/TextureLoader/include/pch.h @@ -0,0 +1,30 @@ +/* Copyright 2015 Egor Yusov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#pragma once + +#include "BasicTypes.h" +#include "RenderDevice.h" +#include "DeviceContext.h" +#include "Errors.h" +#include "DebugUtilities.h" diff --git a/TextureLoader/interface/Image.h b/TextureLoader/interface/Image.h new file mode 100644 index 0000000..74917e6 --- /dev/null +++ b/TextureLoader/interface/Image.h @@ -0,0 +1,82 @@ +/* Copyright 2015 Egor Yusov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#pragma once + +#include "FileStream.h" +#include "DataBlob.h" +#include "RefCntAutoPtr.h" +#include "ObjectBase.h" + +namespace Diligent +{ + enum class EImageFileFormat + { + unknown = 0, + jpeg, + png, + tiff + }; + + struct ImageLoadInfo + { + EImageFileFormat Format; + ImageLoadInfo() : + Format(EImageFileFormat::unknown) + {} + }; + + struct ImageDesc + { + Diligent::Uint32 Width; + Diligent::Uint32 Height; + Diligent::Uint32 BitsPerPixel; + Diligent::Uint32 NumComponents; + Diligent::Uint32 RowStride; // In bytes + ImageDesc() : + Width(0), + Height(0), + BitsPerPixel(0), + NumComponents(0), + RowStride(0) + {} + }; + + class Image : public Diligent::ObjectBase + { + public: + Image( Diligent::IFileStream *pSrcFile, + const ImageLoadInfo& LoadInfo ); + + const ImageDesc &GetDesc(){ return m_Desc; } + IDataBlob *GetData(){ return m_pData; } + + private: + void LoadPngFile( IDataBlob *pFileData, const ImageLoadInfo& LoadInfo ); + void LoadTiffFile( IDataBlob *pFileData,const ImageLoadInfo& LoadInfo ); + void LoadJpegFile( IDataBlob *pFileData,const ImageLoadInfo& LoadInfo ); + + ImageDesc m_Desc; + RefCntAutoPtr m_pData; + }; +} diff --git a/TextureLoader/interface/TextureLoader.h b/TextureLoader/interface/TextureLoader.h new file mode 100644 index 0000000..d46582e --- /dev/null +++ b/TextureLoader/interface/TextureLoader.h @@ -0,0 +1,61 @@ +/* Copyright 2015 Egor Yusov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#pragma once + +#include "FileStream.h" +#include "RenderDevice.h" +#include "Texture.h" +#include "Image.h" + +namespace Diligent +{ + struct TextureLoadInfo + { + Diligent::USAGE Usage; + Diligent::Uint32 BindFlags; + Diligent::Uint32 MipLevels; + Diligent::Uint32 CPUAccessFlags; + Diligent::Bool IsSRGB; + Diligent::TEXTURE_FORMAT Format; + + TextureLoadInfo() : + Usage( Diligent::USAGE_STATIC ), + BindFlags( Diligent::BIND_SHADER_RESOURCE ), + MipLevels(0), + CPUAccessFlags(0), + IsSRGB(true), + Format(Diligent::TEX_FORMAT_UNKNOWN) + {} + }; + + void CreateTextureFromImage( Image *pSrcImage, + const TextureLoadInfo& TexLoadInfo, + Diligent::IRenderDevice *pDevice, + Diligent::ITexture **ppTexture ); + + void CreateTextureFromDDS( IDataBlob *pDDSData, + const TextureLoadInfo& TexLoadInfo, + Diligent::IRenderDevice *pDevice, + Diligent::ITexture **ppTexture ); +}; diff --git a/TextureLoader/interface/TextureUtilities.h b/TextureLoader/interface/TextureUtilities.h new file mode 100644 index 0000000..e68ac40 --- /dev/null +++ b/TextureLoader/interface/TextureUtilities.h @@ -0,0 +1,46 @@ +/* Copyright 2015 Egor Yusov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#pragma once + +/// \file +/// Defines texture utilities + +#include "GraphicsTypes.h" +#include "Texture.h" +#include "RenderDevice.h" +#include "TextureLoader.h" + +namespace Diligent +{ + +void CreateImageFromFile( const Diligent::Char *FilePath, + Image **ppImage, + IDataBlob **ppDDSData = nullptr); + +void CreateTextureFromFile( const Diligent::Char *FilePath, + const TextureLoadInfo& TexLoadInfo, + Diligent::IRenderDevice *pDevice, + Diligent::ITexture **ppTexture ); + +} diff --git a/TextureLoader/src/DDSLoader.cpp b/TextureLoader/src/DDSLoader.cpp new file mode 100644 index 0000000..2c701f3 --- /dev/null +++ b/TextureLoader/src/DDSLoader.cpp @@ -0,0 +1,1489 @@ +/* Copyright 2015 Egor Yusov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +//-------------------------------------------------------------------------------------- +// File: DDSLoader.cpp +// +// Functions for loading a DDS texture and creating a Direct3D 11 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. +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkId=248926 +// http://go.microsoft.com/fwlink/?LinkId=248929 +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "dxgiformat.h" +#include +#include +#include "DDSLoader.h" + +#ifndef _In_ +# define _In_ +#endif + +#ifndef _Out_ +# define _Out_ +#endif + +#ifndef _Out_opt_ +# define _Out_opt_ +#endif + +#ifndef _Outptr_opt_ +# define _Outptr_opt_ +#endif + +using namespace Diligent; +using namespace Diligent; + +// D3D11 definitions + +enum D3D11_RESOURCE_DIMENSION +{ + D3D11_RESOURCE_DIMENSION_UNKNOWN = 0, + D3D11_RESOURCE_DIMENSION_BUFFER = 1, + D3D11_RESOURCE_DIMENSION_TEXTURE1D = 2, + D3D11_RESOURCE_DIMENSION_TEXTURE2D = 3, + D3D11_RESOURCE_DIMENSION_TEXTURE3D = 4 +}; + +enum D3D11_RESOURCE_MISC_FLAG +{ + D3D11_RESOURCE_MISC_TEXTURECUBE = 0x4L, +}; + +#ifndef D3D11_REQ_MIP_LEVELS +# define D3D11_REQ_MIP_LEVELS ( 15 ) +#endif + +#ifndef D3D11_REQ_TEXTURE1D_ARRAY_AXIS_DIMENSION +# define D3D11_REQ_TEXTURE1D_ARRAY_AXIS_DIMENSION ( 2048 ) +#endif + +#ifndef D3D11_REQ_TEXTURE1D_U_DIMENSION +# define D3D11_REQ_TEXTURE1D_U_DIMENSION ( 16384 ) +#endif + +#ifndef D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION +# define D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION ( 2048 ) +#endif + +#ifndef D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION +# define D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION ( 16384 ) +#endif + +#ifndef D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION +# define D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION ( 2048 ) +#endif + +#ifndef D3D11_REQ_TEXTURECUBE_DIMENSION +# define D3D11_REQ_TEXTURECUBE_DIMENSION ( 16384 ) +#endif + + +//-------------------------------------------------------------------------------------- +// Macros +//-------------------------------------------------------------------------------------- +#ifndef MAKEFOURCC + #define MAKEFOURCC(ch0, ch1, ch2, ch3) \ + ((Uint32)(Uint8)(ch0) | ((Uint32)(Uint8)(ch1) << 8) | \ + ((Uint32)(Uint8)(ch2) << 16) | ((Uint32)(Uint8)(ch3) << 24)) +#endif /* defined(MAKEFOURCC) */ + +//-------------------------------------------------------------------------------------- +// DDS file structure definitions +// +// See DDS.h in the 'Texconv' sample and the 'DirectXTex' library +//-------------------------------------------------------------------------------------- +#pragma pack(push, 1) + +#define DDS_MAGIC 0x20534444 // "DDS " + +struct DDS_PIXELFORMAT +{ + Uint32 size; + Uint32 flags; + Uint32 fourCC; + Uint32 RGBBitCount; + Uint32 RBitMask; + Uint32 GBitMask; + Uint32 BBitMask; + Uint32 ABitMask; +}; + +#define DDS_FOURCC 0x00000004 // DDPF_FOURCC +#define DDS_RGB 0x00000040 // DDPF_RGB +#define DDS_RGBA 0x00000041 // DDPF_RGB | DDPF_ALPHAPIXELS +#define DDS_LUMINANCE 0x00020000 // DDPF_LUMINANCE +#define DDS_LUMINANCEA 0x00020001 // DDPF_LUMINANCE | DDPF_ALPHAPIXELS +#define DDS_ALPHA 0x00000002 // DDPF_ALPHA +#define DDS_PAL8 0x00000020 // DDPF_PALETTEINDEXED8 + +#define DDS_HEADER_FLAGS_TEXTURE 0x00001007 // DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT +#define DDS_HEADER_FLAGS_MIPMAP 0x00020000 // DDSD_MIPMAPCOUNT +#define DDS_HEADER_FLAGS_VOLUME 0x00800000 // DDSD_DEPTH +#define DDS_HEADER_FLAGS_PITCH 0x00000008 // DDSD_PITCH +#define DDS_HEADER_FLAGS_LINEARSIZE 0x00080000 // DDSD_LINEARSIZE + +#define DDS_HEIGHT 0x00000002 // DDSD_HEIGHT +#define DDS_WIDTH 0x00000004 // DDSD_WIDTH + +#define DDS_SURFACE_FLAGS_TEXTURE 0x00001000 // DDSCAPS_TEXTURE +#define DDS_SURFACE_FLAGS_MIPMAP 0x00400008 // DDSCAPS_COMPLEX | DDSCAPS_MIPMAP +#define DDS_SURFACE_FLAGS_CUBEMAP 0x00000008 // DDSCAPS_COMPLEX + +#define DDS_CUBEMAP_POSITIVEX 0x00000600 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEX +#define DDS_CUBEMAP_NEGATIVEX 0x00000a00 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEX +#define DDS_CUBEMAP_POSITIVEY 0x00001200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEY +#define DDS_CUBEMAP_NEGATIVEY 0x00002200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEY +#define DDS_CUBEMAP_POSITIVEZ 0x00004200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEZ +#define DDS_CUBEMAP_NEGATIVEZ 0x00008200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEZ + +#define DDS_CUBEMAP_ALLFACES (DDS_CUBEMAP_POSITIVEX | DDS_CUBEMAP_NEGATIVEX |\ + DDS_CUBEMAP_POSITIVEY | DDS_CUBEMAP_NEGATIVEY |\ + DDS_CUBEMAP_POSITIVEZ | DDS_CUBEMAP_NEGATIVEZ) + +#define DDS_CUBEMAP 0x00000200 // DDSCAPS2_CUBEMAP + +#define DDS_FLAGS_VOLUME 0x00200000 // DDSCAPS2_VOLUME + +enum DDS_MISC_FLAGS2 +{ + DDS_MISC_FLAGS2_ALPHA_MODE_MASK = 0x7L, +}; + +enum DDS_ALPHA_MODE +{ + DDS_ALPHA_MODE_UNKNOWN = 0, + DDS_ALPHA_MODE_STRAIGHT = 1, + DDS_ALPHA_MODE_PREMULTIPLIED = 2, + DDS_ALPHA_MODE_OPAQUE = 3, + DDS_ALPHA_MODE_CUSTOM = 4, +}; + +typedef struct +{ + Uint32 size; + Uint32 flags; + Uint32 height; + Uint32 width; + Uint32 pitchOrLinearSize; + Uint32 depth; // only if DDS_HEADER_FLAGS_VOLUME is set in flags + Uint32 mipMapCount; + Uint32 reserved1[11]; + DDS_PIXELFORMAT ddspf; + Uint32 caps; + Uint32 caps2; + Uint32 caps3; + Uint32 caps4; + Uint32 reserved2; +} DDS_HEADER; + + +typedef struct +{ + DXGI_FORMAT dxgiFormat; + Uint32 resourceDimension; + Uint32 miscFlag; // see D3D11_RESOURCE_MISC_FLAG + Uint32 arraySize; + Uint32 miscFlags2; +} DDS_HEADER_DXT10; + +#pragma pack(pop) + + + +//-------------------------------------------------------------------------------------- +// Return the BPP for a particular format +//-------------------------------------------------------------------------------------- +static size_t BitsPerPixel(_In_ DXGI_FORMAT fmt) +{ + switch (fmt) + { + case DXGI_FORMAT_R32G32B32A32_TYPELESS: + case DXGI_FORMAT_R32G32B32A32_FLOAT: + case DXGI_FORMAT_R32G32B32A32_UINT: + case DXGI_FORMAT_R32G32B32A32_SINT: + return 128; + + case DXGI_FORMAT_R32G32B32_TYPELESS: + case DXGI_FORMAT_R32G32B32_FLOAT: + case DXGI_FORMAT_R32G32B32_UINT: + case DXGI_FORMAT_R32G32B32_SINT: + return 96; + + case DXGI_FORMAT_R16G16B16A16_TYPELESS: + case DXGI_FORMAT_R16G16B16A16_FLOAT: + case DXGI_FORMAT_R16G16B16A16_UNORM: + case DXGI_FORMAT_R16G16B16A16_UINT: + case DXGI_FORMAT_R16G16B16A16_SNORM: + case DXGI_FORMAT_R16G16B16A16_SINT: + case DXGI_FORMAT_R32G32_TYPELESS: + case DXGI_FORMAT_R32G32_FLOAT: + case DXGI_FORMAT_R32G32_UINT: + case DXGI_FORMAT_R32G32_SINT: + case DXGI_FORMAT_R32G8X24_TYPELESS: + case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: + case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS: + case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT: + return 64; + + case DXGI_FORMAT_R10G10B10A2_TYPELESS: + case DXGI_FORMAT_R10G10B10A2_UNORM: + case DXGI_FORMAT_R10G10B10A2_UINT: + case DXGI_FORMAT_R11G11B10_FLOAT: + case DXGI_FORMAT_R8G8B8A8_TYPELESS: + case DXGI_FORMAT_R8G8B8A8_UNORM: + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + case DXGI_FORMAT_R8G8B8A8_UINT: + case DXGI_FORMAT_R8G8B8A8_SNORM: + case DXGI_FORMAT_R8G8B8A8_SINT: + case DXGI_FORMAT_R16G16_TYPELESS: + case DXGI_FORMAT_R16G16_FLOAT: + case DXGI_FORMAT_R16G16_UNORM: + case DXGI_FORMAT_R16G16_UINT: + case DXGI_FORMAT_R16G16_SNORM: + case DXGI_FORMAT_R16G16_SINT: + case DXGI_FORMAT_R32_TYPELESS: + case DXGI_FORMAT_D32_FLOAT: + case DXGI_FORMAT_R32_FLOAT: + case DXGI_FORMAT_R32_UINT: + case DXGI_FORMAT_R32_SINT: + case DXGI_FORMAT_R24G8_TYPELESS: + case DXGI_FORMAT_D24_UNORM_S8_UINT: + case DXGI_FORMAT_R24_UNORM_X8_TYPELESS: + case DXGI_FORMAT_X24_TYPELESS_G8_UINT: + case DXGI_FORMAT_R9G9B9E5_SHAREDEXP: + case DXGI_FORMAT_R8G8_B8G8_UNORM: + case DXGI_FORMAT_G8R8_G8B8_UNORM: + case DXGI_FORMAT_B8G8R8A8_UNORM: + case DXGI_FORMAT_B8G8R8X8_UNORM: + case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM: + case DXGI_FORMAT_B8G8R8A8_TYPELESS: + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: + case DXGI_FORMAT_B8G8R8X8_TYPELESS: + case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: + return 32; + + case DXGI_FORMAT_R8G8_TYPELESS: + case DXGI_FORMAT_R8G8_UNORM: + case DXGI_FORMAT_R8G8_UINT: + case DXGI_FORMAT_R8G8_SNORM: + case DXGI_FORMAT_R8G8_SINT: + case DXGI_FORMAT_R16_TYPELESS: + case DXGI_FORMAT_R16_FLOAT: + case DXGI_FORMAT_D16_UNORM: + case DXGI_FORMAT_R16_UNORM: + case DXGI_FORMAT_R16_UINT: + case DXGI_FORMAT_R16_SNORM: + case DXGI_FORMAT_R16_SINT: + case DXGI_FORMAT_B5G6R5_UNORM: + case DXGI_FORMAT_B5G5R5A1_UNORM: + case DXGI_FORMAT_B4G4R4A4_UNORM: + return 16; + + case DXGI_FORMAT_R8_TYPELESS: + case DXGI_FORMAT_R8_UNORM: + case DXGI_FORMAT_R8_UINT: + case DXGI_FORMAT_R8_SNORM: + case DXGI_FORMAT_R8_SINT: + case DXGI_FORMAT_A8_UNORM: + return 8; + + case DXGI_FORMAT_R1_UNORM: + return 1; + + case DXGI_FORMAT_BC1_TYPELESS: + case DXGI_FORMAT_BC1_UNORM: + case DXGI_FORMAT_BC1_UNORM_SRGB: + case DXGI_FORMAT_BC4_TYPELESS: + case DXGI_FORMAT_BC4_UNORM: + case DXGI_FORMAT_BC4_SNORM: + return 4; + + case DXGI_FORMAT_BC2_TYPELESS: + case DXGI_FORMAT_BC2_UNORM: + case DXGI_FORMAT_BC2_UNORM_SRGB: + case DXGI_FORMAT_BC3_TYPELESS: + case DXGI_FORMAT_BC3_UNORM: + case DXGI_FORMAT_BC3_UNORM_SRGB: + case DXGI_FORMAT_BC5_TYPELESS: + case DXGI_FORMAT_BC5_UNORM: + case DXGI_FORMAT_BC5_SNORM: + case DXGI_FORMAT_BC6H_TYPELESS: + case DXGI_FORMAT_BC6H_UF16: + case DXGI_FORMAT_BC6H_SF16: + case DXGI_FORMAT_BC7_TYPELESS: + case DXGI_FORMAT_BC7_UNORM: + case DXGI_FORMAT_BC7_UNORM_SRGB: + return 8; + + default: + return 0; + } +} + + +static TEXTURE_FORMAT DXGIFormatToTexFormat( DXGI_FORMAT TexFormat ) +{ + switch(TexFormat) + { + case DXGI_FORMAT_UNKNOWN: return TEX_FORMAT_UNKNOWN; + + case DXGI_FORMAT_R32G32B32A32_TYPELESS: return TEX_FORMAT_RGBA32_TYPELESS; + case DXGI_FORMAT_R32G32B32A32_FLOAT: return TEX_FORMAT_RGBA32_FLOAT; + case DXGI_FORMAT_R32G32B32A32_UINT: return TEX_FORMAT_RGBA32_UINT; + case DXGI_FORMAT_R32G32B32A32_SINT: return TEX_FORMAT_RGBA32_SINT; + + case DXGI_FORMAT_R32G32B32_TYPELESS: return TEX_FORMAT_RGB32_TYPELESS; + case DXGI_FORMAT_R32G32B32_FLOAT: return TEX_FORMAT_RGB32_FLOAT; + case DXGI_FORMAT_R32G32B32_UINT: return TEX_FORMAT_RGB32_UINT; + case DXGI_FORMAT_R32G32B32_SINT: return TEX_FORMAT_RGB32_SINT; + + case DXGI_FORMAT_R16G16B16A16_TYPELESS: return TEX_FORMAT_RGBA16_TYPELESS; + case DXGI_FORMAT_R16G16B16A16_FLOAT: return TEX_FORMAT_RGBA16_FLOAT; + case DXGI_FORMAT_R16G16B16A16_UNORM: return TEX_FORMAT_RGBA16_UNORM; + case DXGI_FORMAT_R16G16B16A16_UINT: return TEX_FORMAT_RGBA16_UINT; + case DXGI_FORMAT_R16G16B16A16_SNORM: return TEX_FORMAT_RGBA16_SNORM; + case DXGI_FORMAT_R16G16B16A16_SINT: return TEX_FORMAT_RGBA16_SINT; + + case DXGI_FORMAT_R32G32_TYPELESS: return TEX_FORMAT_RG32_TYPELESS; + case DXGI_FORMAT_R32G32_FLOAT: return TEX_FORMAT_RG32_FLOAT; + case DXGI_FORMAT_R32G32_UINT: return TEX_FORMAT_RG32_UINT; + case DXGI_FORMAT_R32G32_SINT: return TEX_FORMAT_RG32_SINT; + + case DXGI_FORMAT_R32G8X24_TYPELESS: return TEX_FORMAT_R32G8X24_TYPELESS; + case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: return TEX_FORMAT_D32_FLOAT_S8X24_UINT; + case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS: return TEX_FORMAT_R32_FLOAT_X8X24_TYPELESS; + case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT: return TEX_FORMAT_X32_TYPELESS_G8X24_UINT; + + case DXGI_FORMAT_R10G10B10A2_TYPELESS: return TEX_FORMAT_RGB10A2_TYPELESS; + case DXGI_FORMAT_R10G10B10A2_UNORM: return TEX_FORMAT_RGB10A2_UNORM; + case DXGI_FORMAT_R10G10B10A2_UINT: return TEX_FORMAT_RGB10A2_UINT; + + case DXGI_FORMAT_R11G11B10_FLOAT: return TEX_FORMAT_R11G11B10_FLOAT; + + case DXGI_FORMAT_R8G8B8A8_TYPELESS: return TEX_FORMAT_RGBA8_TYPELESS; + case DXGI_FORMAT_R8G8B8A8_UNORM: return TEX_FORMAT_RGBA8_UNORM; + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: return TEX_FORMAT_RGBA8_UNORM_SRGB; + case DXGI_FORMAT_R8G8B8A8_UINT: return TEX_FORMAT_RGBA8_UINT; + case DXGI_FORMAT_R8G8B8A8_SNORM: return TEX_FORMAT_RGBA8_SNORM; + case DXGI_FORMAT_R8G8B8A8_SINT: return TEX_FORMAT_RGBA8_SINT; + + case DXGI_FORMAT_R16G16_TYPELESS: return TEX_FORMAT_RG16_TYPELESS; + case DXGI_FORMAT_R16G16_FLOAT: return TEX_FORMAT_RG16_FLOAT; + case DXGI_FORMAT_R16G16_UNORM: return TEX_FORMAT_RG16_UNORM; + case DXGI_FORMAT_R16G16_UINT: return TEX_FORMAT_RG16_UINT; + case DXGI_FORMAT_R16G16_SNORM: return TEX_FORMAT_RG16_SNORM; + case DXGI_FORMAT_R16G16_SINT: return TEX_FORMAT_RG16_SINT; + + case DXGI_FORMAT_R32_TYPELESS: return TEX_FORMAT_R32_TYPELESS; + case DXGI_FORMAT_D32_FLOAT: return TEX_FORMAT_D32_FLOAT; + case DXGI_FORMAT_R32_FLOAT: return TEX_FORMAT_R32_FLOAT; + case DXGI_FORMAT_R32_UINT: return TEX_FORMAT_R32_UINT; + case DXGI_FORMAT_R32_SINT: return TEX_FORMAT_R32_SINT; + + case DXGI_FORMAT_R24G8_TYPELESS: return TEX_FORMAT_R24G8_TYPELESS; + case DXGI_FORMAT_D24_UNORM_S8_UINT: return TEX_FORMAT_D24_UNORM_S8_UINT; + case DXGI_FORMAT_R24_UNORM_X8_TYPELESS: return TEX_FORMAT_R24_UNORM_X8_TYPELESS; + case DXGI_FORMAT_X24_TYPELESS_G8_UINT: return TEX_FORMAT_X24_TYPELESS_G8_UINT; + + case DXGI_FORMAT_R8G8_TYPELESS: return TEX_FORMAT_RG8_TYPELESS; + case DXGI_FORMAT_R8G8_UNORM: return TEX_FORMAT_RG8_UNORM; + case DXGI_FORMAT_R8G8_UINT: return TEX_FORMAT_RG8_UINT; + case DXGI_FORMAT_R8G8_SNORM: return TEX_FORMAT_RG8_SNORM; + case DXGI_FORMAT_R8G8_SINT: return TEX_FORMAT_RG8_SINT; + + case DXGI_FORMAT_R16_TYPELESS: return TEX_FORMAT_R16_TYPELESS; + case DXGI_FORMAT_R16_FLOAT: return TEX_FORMAT_R16_FLOAT; + case DXGI_FORMAT_D16_UNORM: return TEX_FORMAT_D16_UNORM; + case DXGI_FORMAT_R16_UNORM: return TEX_FORMAT_R16_UNORM; + case DXGI_FORMAT_R16_UINT: return TEX_FORMAT_R16_UINT; + case DXGI_FORMAT_R16_SNORM: return TEX_FORMAT_R16_SNORM; + case DXGI_FORMAT_R16_SINT: return TEX_FORMAT_R16_SINT; + + case DXGI_FORMAT_R8_TYPELESS: return TEX_FORMAT_R8_TYPELESS; + case DXGI_FORMAT_R8_UNORM: return TEX_FORMAT_R8_UNORM; + case DXGI_FORMAT_R8_UINT: return TEX_FORMAT_R8_UINT; + case DXGI_FORMAT_R8_SNORM: return TEX_FORMAT_R8_SNORM; + case DXGI_FORMAT_R8_SINT: return TEX_FORMAT_R8_SINT; + case DXGI_FORMAT_A8_UNORM: return TEX_FORMAT_A8_UNORM; + + case DXGI_FORMAT_R1_UNORM : return TEX_FORMAT_R1_UNORM; + case DXGI_FORMAT_R9G9B9E5_SHAREDEXP: return TEX_FORMAT_RGB9E5_SHAREDEXP; + case DXGI_FORMAT_R8G8_B8G8_UNORM: return TEX_FORMAT_RG8_B8G8_UNORM; + case DXGI_FORMAT_G8R8_G8B8_UNORM: return TEX_FORMAT_G8R8_G8B8_UNORM; + + case DXGI_FORMAT_BC1_TYPELESS: return TEX_FORMAT_BC1_TYPELESS; + case DXGI_FORMAT_BC1_UNORM: return TEX_FORMAT_BC1_UNORM; + case DXGI_FORMAT_BC1_UNORM_SRGB: return TEX_FORMAT_BC1_UNORM_SRGB; + case DXGI_FORMAT_BC2_TYPELESS: return TEX_FORMAT_BC2_TYPELESS; + case DXGI_FORMAT_BC2_UNORM: return TEX_FORMAT_BC2_UNORM; + case DXGI_FORMAT_BC2_UNORM_SRGB: return TEX_FORMAT_BC2_UNORM_SRGB; + case DXGI_FORMAT_BC3_TYPELESS: return TEX_FORMAT_BC3_TYPELESS; + case DXGI_FORMAT_BC3_UNORM: return TEX_FORMAT_BC3_UNORM; + case DXGI_FORMAT_BC3_UNORM_SRGB: return TEX_FORMAT_BC3_UNORM_SRGB; + case DXGI_FORMAT_BC4_TYPELESS: return TEX_FORMAT_BC4_TYPELESS; + case DXGI_FORMAT_BC4_UNORM: return TEX_FORMAT_BC4_UNORM; + case DXGI_FORMAT_BC4_SNORM: return TEX_FORMAT_BC4_SNORM; + case DXGI_FORMAT_BC5_TYPELESS: return TEX_FORMAT_BC5_TYPELESS; + case DXGI_FORMAT_BC5_UNORM: return TEX_FORMAT_BC5_UNORM; + case DXGI_FORMAT_BC5_SNORM: return TEX_FORMAT_BC5_SNORM; + + case DXGI_FORMAT_B5G6R5_UNORM: return TEX_FORMAT_B5G6R5_UNORM; + case DXGI_FORMAT_B5G5R5A1_UNORM: return TEX_FORMAT_B5G5R5A1_UNORM; + case DXGI_FORMAT_B8G8R8A8_UNORM: return TEX_FORMAT_BGRA8_UNORM; + case DXGI_FORMAT_B8G8R8X8_UNORM: return TEX_FORMAT_BGRX8_UNORM; + + case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM: return TEX_FORMAT_R10G10B10_XR_BIAS_A2_UNORM; + + case DXGI_FORMAT_B8G8R8A8_TYPELESS: return TEX_FORMAT_BGRA8_TYPELESS; + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: return TEX_FORMAT_BGRA8_UNORM_SRGB; + case DXGI_FORMAT_B8G8R8X8_TYPELESS: return TEX_FORMAT_BGRX8_TYPELESS; + case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: return TEX_FORMAT_BGRX8_UNORM_SRGB; + + case DXGI_FORMAT_BC6H_TYPELESS: return TEX_FORMAT_BC6H_TYPELESS; + case DXGI_FORMAT_BC6H_UF16: return TEX_FORMAT_BC6H_UF16; + case DXGI_FORMAT_BC6H_SF16: return TEX_FORMAT_BC6H_SF16; + case DXGI_FORMAT_BC7_TYPELESS : return TEX_FORMAT_BC7_TYPELESS; + case DXGI_FORMAT_BC7_UNORM: return TEX_FORMAT_BC7_UNORM; + case DXGI_FORMAT_BC7_UNORM_SRGB: return TEX_FORMAT_BC7_UNORM_SRGB; + + default: UNEXPECTED( "Unsupported DXGI formate" ); return TEX_FORMAT_UNKNOWN; + } +} + +//-------------------------------------------------------------------------------------- +// Get surface information for a particular format +//-------------------------------------------------------------------------------------- +static void GetSurfaceInfo( + _In_ size_t width, + _In_ size_t height, + _In_ DXGI_FORMAT fmt, + _Out_opt_ size_t* outNumBytes, + _Out_opt_ size_t* outRowBytes, + _Out_opt_ size_t* outNumRows + ) +{ + size_t numBytes = 0; + size_t rowBytes = 0; + size_t numRows = 0; + + bool bc = false; + bool packed = false; + size_t bcnumBytesPerBlock = 0; + switch (fmt) + { + case DXGI_FORMAT_BC1_TYPELESS: + case DXGI_FORMAT_BC1_UNORM: + case DXGI_FORMAT_BC1_UNORM_SRGB: + case DXGI_FORMAT_BC4_TYPELESS: + case DXGI_FORMAT_BC4_UNORM: + case DXGI_FORMAT_BC4_SNORM: + bc = true; + bcnumBytesPerBlock = 8; + break; + + case DXGI_FORMAT_BC2_TYPELESS: + case DXGI_FORMAT_BC2_UNORM: + case DXGI_FORMAT_BC2_UNORM_SRGB: + case DXGI_FORMAT_BC3_TYPELESS: + case DXGI_FORMAT_BC3_UNORM: + case DXGI_FORMAT_BC3_UNORM_SRGB: + case DXGI_FORMAT_BC5_TYPELESS: + case DXGI_FORMAT_BC5_UNORM: + case DXGI_FORMAT_BC5_SNORM: + case DXGI_FORMAT_BC6H_TYPELESS: + case DXGI_FORMAT_BC6H_UF16: + case DXGI_FORMAT_BC6H_SF16: + case DXGI_FORMAT_BC7_TYPELESS: + case DXGI_FORMAT_BC7_UNORM: + case DXGI_FORMAT_BC7_UNORM_SRGB: + bc = true; + bcnumBytesPerBlock = 16; + break; + + case DXGI_FORMAT_R8G8_B8G8_UNORM: + case DXGI_FORMAT_G8R8_G8B8_UNORM: + packed = true; + break; + } + + if (bc) + { + size_t numBlocksWide = 0; + if (width > 0) + { + numBlocksWide = std::max(1, (width + 3) / 4); + } + size_t numBlocksHigh = 0; + if (height > 0) + { + numBlocksHigh = std::max(1, (height + 3) / 4); + } + rowBytes = numBlocksWide * bcnumBytesPerBlock; + numRows = numBlocksHigh; + } + else if (packed) + { + rowBytes = ((width + 1) >> 1) * 4; + numRows = height; + } + else + { + size_t bpp = BitsPerPixel(fmt); + rowBytes = (width * bpp + 7) / 8; // round up to nearest byte + numRows = height; + } + + numBytes = rowBytes * numRows; + if (outNumBytes) + { + *outNumBytes = numBytes; + } + if (outRowBytes) + { + *outRowBytes = rowBytes; + } + if (outNumRows) + { + *outNumRows = numRows; + } +} + + +//-------------------------------------------------------------------------------------- +#define ISBITMASK(r, g, b, a) (ddpf.RBitMask == r && ddpf.GBitMask == g && ddpf.BBitMask == b && ddpf.ABitMask == a) + +static DXGI_FORMAT GetDXGIFormat(const DDS_PIXELFORMAT& ddpf) +{ + if (ddpf.flags & DDS_RGB) + { + // Note that sRGB formats are written using the "DX10" extended header + + switch (ddpf.RGBBitCount) + { + case 32: + if (ISBITMASK(0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000)) + { + return DXGI_FORMAT_R8G8B8A8_UNORM; + } + + if (ISBITMASK(0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000)) + { + return DXGI_FORMAT_B8G8R8A8_UNORM; + } + + if (ISBITMASK(0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000)) + { + return DXGI_FORMAT_B8G8R8X8_UNORM; + } + + // No DXGI format maps to ISBITMASK(0x000000ff, 0x0000ff00, 0x00ff0000, 0x00000000) aka D3DFMT_X8B8G8R8 + + // Note that many common DDS reader/writers (including D3DX) swap the + // the RED/BLUE masks for 10:10:10:2 formats. We assumme + // below that the 'backwards' header mask is being used since it is most + // likely written by D3DX. The more robust solution is to use the 'DX10' + // header extension and specify the DXGI_FORMAT_R10G10B10A2_UNORM format directly + + // For 'correct' writers, this should be 0x000003ff, 0x000ffc00, 0x3ff00000 for RGB data + if (ISBITMASK(0x3ff00000, 0x000ffc00, 0x000003ff, 0xc0000000)) + { + return DXGI_FORMAT_R10G10B10A2_UNORM; + } + + // No DXGI format maps to ISBITMASK(0x000003ff, 0x000ffc00, 0x3ff00000, 0xc0000000) aka D3DFMT_A2R10G10B10 + + if (ISBITMASK(0x0000ffff, 0xffff0000, 0x00000000, 0x00000000)) + { + return DXGI_FORMAT_R16G16_UNORM; + } + + if (ISBITMASK(0xffffffff, 0x00000000, 0x00000000, 0x00000000)) + { + // Only 32-bit color channel format in D3D9 was R32F + return DXGI_FORMAT_R32_FLOAT; // D3DX writes this out as a FourCC of 114 + } + break; + + case 24: + // No 24bpp DXGI formats aka D3DFMT_R8G8B8 + break; + + case 16: + if (ISBITMASK(0x7c00, 0x03e0, 0x001f, 0x8000)) + { + return DXGI_FORMAT_B5G5R5A1_UNORM; + } + if (ISBITMASK(0xf800, 0x07e0, 0x001f, 0x0000)) + { + return DXGI_FORMAT_B5G6R5_UNORM; + } + + // No DXGI format maps to ISBITMASK(0x7c00, 0x03e0, 0x001f, 0x0000) aka D3DFMT_X1R5G5B5 + 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 3:3:2, 3:3:2:8, or paletted DXGI formats aka D3DFMT_A8R3G3B2, D3DFMT_R3G3B2, D3DFMT_P8, D3DFMT_A8P8, etc. + break; + } + } + else if (ddpf.flags & DDS_LUMINANCE) + { + if (8 == ddpf.RGBBitCount) + { + if (ISBITMASK(0x000000ff, 0x00000000, 0x00000000, 0x00000000)) + { + return DXGI_FORMAT_R8_UNORM; // D3DX10/11 writes this out as DX10 extension + } + + // No DXGI format maps to ISBITMASK(0x0f, 0x00, 0x00, 0xf0) aka D3DFMT_A4L4 + } + + if (16 == ddpf.RGBBitCount) + { + if (ISBITMASK(0x0000ffff, 0x00000000, 0x00000000, 0x00000000)) + { + return DXGI_FORMAT_R16_UNORM; // D3DX10/11 writes this out as DX10 extension + } + if (ISBITMASK(0x000000ff, 0x00000000, 0x00000000, 0x0000ff00)) + { + return DXGI_FORMAT_R8G8_UNORM; // D3DX10/11 writes this out as DX10 extension + } + } + } + else if (ddpf.flags & DDS_ALPHA) + { + if (8 == ddpf.RGBBitCount) + { + return DXGI_FORMAT_A8_UNORM; + } + } + else if (ddpf.flags & DDS_FOURCC) + { + if (MAKEFOURCC('D', 'X', 'T', '1') == ddpf.fourCC) + { + return DXGI_FORMAT_BC1_UNORM; + } + if (MAKEFOURCC('D', 'X', 'T', '3') == ddpf.fourCC) + { + return DXGI_FORMAT_BC2_UNORM; + } + if (MAKEFOURCC('D', 'X', 'T', '5') == ddpf.fourCC) + { + return DXGI_FORMAT_BC3_UNORM; + } + + // While pre-mulitplied alpha isn't directly supported by the DXGI formats, + // they are basically the same as these BC formats so they can be mapped + if (MAKEFOURCC('D', 'X', 'T', '2') == ddpf.fourCC) + { + return DXGI_FORMAT_BC2_UNORM; + } + if (MAKEFOURCC('D', 'X', 'T', '4') == ddpf.fourCC) + { + return DXGI_FORMAT_BC3_UNORM; + } + + if (MAKEFOURCC('A', 'T', 'I', '1') == ddpf.fourCC) + { + return DXGI_FORMAT_BC4_UNORM; + } + if (MAKEFOURCC('B', 'C', '4', 'U') == ddpf.fourCC) + { + return DXGI_FORMAT_BC4_UNORM; + } + if (MAKEFOURCC('B', 'C', '4', 'S') == ddpf.fourCC) + { + return DXGI_FORMAT_BC4_SNORM; + } + + if (MAKEFOURCC('A', 'T', 'I', '2') == ddpf.fourCC) + { + return DXGI_FORMAT_BC5_UNORM; + } + if (MAKEFOURCC('B', 'C', '5', 'U') == ddpf.fourCC) + { + return DXGI_FORMAT_BC5_UNORM; + } + if (MAKEFOURCC('B', 'C', '5', 'S') == ddpf.fourCC) + { + return DXGI_FORMAT_BC5_SNORM; + } + + // BC6H and BC7 are written using the "DX10" extended header + + if (MAKEFOURCC('R', 'G', 'B', 'G') == ddpf.fourCC) + { + return DXGI_FORMAT_R8G8_B8G8_UNORM; + } + if (MAKEFOURCC('G', 'R', 'G', 'B') == ddpf.fourCC) + { + return DXGI_FORMAT_G8R8_G8B8_UNORM; + } + + // Check for D3DFORMAT enums being set here + switch (ddpf.fourCC) + { + case 36: // D3DFMT_A16B16G16R16 + return DXGI_FORMAT_R16G16B16A16_UNORM; + + case 110: // D3DFMT_Q16W16V16U16 + return DXGI_FORMAT_R16G16B16A16_SNORM; + + case 111: // D3DFMT_R16F + return DXGI_FORMAT_R16_FLOAT; + + case 112: // D3DFMT_G16R16F + return DXGI_FORMAT_R16G16_FLOAT; + + case 113: // D3DFMT_A16B16G16R16F + return DXGI_FORMAT_R16G16B16A16_FLOAT; + + case 114: // D3DFMT_R32F + return DXGI_FORMAT_R32_FLOAT; + + case 115: // D3DFMT_G32R32F + return DXGI_FORMAT_R32G32_FLOAT; + + case 116: // D3DFMT_A32B32G32R32F + return DXGI_FORMAT_R32G32B32A32_FLOAT; + } + } + + return DXGI_FORMAT_UNKNOWN; +} + + +//-------------------------------------------------------------------------------------- +static DXGI_FORMAT MakeSRGB(_In_ DXGI_FORMAT format) +{ + switch (format) + { + case DXGI_FORMAT_R8G8B8A8_UNORM: + return DXGI_FORMAT_R8G8B8A8_UNORM_SRGB; + + case DXGI_FORMAT_BC1_UNORM: + return DXGI_FORMAT_BC1_UNORM_SRGB; + + case DXGI_FORMAT_BC2_UNORM: + return DXGI_FORMAT_BC2_UNORM_SRGB; + + case DXGI_FORMAT_BC3_UNORM: + return DXGI_FORMAT_BC3_UNORM_SRGB; + + case DXGI_FORMAT_B8G8R8A8_UNORM: + return DXGI_FORMAT_B8G8R8A8_UNORM_SRGB; + + case DXGI_FORMAT_B8G8R8X8_UNORM: + return DXGI_FORMAT_B8G8R8X8_UNORM_SRGB; + + case DXGI_FORMAT_BC7_UNORM: + return DXGI_FORMAT_BC7_UNORM_SRGB; + + default: + return format; + } +} + + +//-------------------------------------------------------------------------------------- +static void FillInitData( + _In_ size_t width, + _In_ size_t height, + _In_ size_t depth, + _In_ size_t mipCount, + _In_ size_t arraySize, + _In_ DXGI_FORMAT format, + _In_ size_t maxsize, + _In_ size_t bitSize, + _In_ const Uint8* bitData, + _Out_ size_t& twidth, + _Out_ size_t& theight, + _Out_ size_t& tdepth, + _Out_ size_t& skipMip, + _Out_ TextureSubResData *initData + ) +{ + if (!bitData || !initData) + { + LOG_ERROR_AND_THROW( "Invalid arguments" ); + } + + skipMip = 0; + twidth = 0; + theight = 0; + tdepth = 0; + + size_t NumBytes = 0; + size_t RowBytes = 0; + size_t NumRows = 0; + const Uint8* pSrcBits = bitData; + const Uint8* pEndBits = bitData + bitSize; + + size_t index = 0; + for (size_t j = 0; j < arraySize; j++) + { + size_t w = width; + size_t h = height; + size_t d = depth; + for (size_t i = 0; i < mipCount; i++) + { + GetSurfaceInfo(w, h, format, &NumBytes, &RowBytes, &NumRows); + + if ((mipCount <= 1) || !maxsize || (w <= maxsize && h <= maxsize && d <= maxsize)) + { + if (!twidth) + { + twidth = w; + theight = h; + tdepth = d; + } + + VERIFY_EXPR(index < mipCount * arraySize); + initData[index].pData = (const void*)pSrcBits; + initData[index].Stride = static_cast(RowBytes); + initData[index].DepthStride = static_cast(NumBytes); + ++index; + } + else if (!j) + { + // Count number of skipped mipmaps (first item only) + ++skipMip; + } + + if (pSrcBits + (NumBytes*d) > pEndBits) + { + LOG_ERROR_AND_THROW( "Out of bounds" ); + } + + pSrcBits += NumBytes * d; + + w = w >> 1; + h = h >> 1; + d = d >> 1; + if (w == 0) + { + w = 1; + } + if (h == 0) + { + h = 1; + } + if (d == 0) + { + d = 1; + } + } + } + + if (!index) + { + LOG_ERROR_AND_THROW( "Unknown error" ); + } +} + + +//-------------------------------------------------------------------------------------- +static void CreateTexture( + _In_ IRenderDevice* pDevice, + _In_ Uint32 resDim, + _In_ size_t width, + _In_ size_t height, + _In_ size_t depth, + _In_ size_t mipCount, + _In_ size_t arraySize, + _In_ DXGI_FORMAT format, + _In_ USAGE usage, + _In_ unsigned int bindFlags, + _In_ unsigned int cpuAccessFlags, + _In_ unsigned int miscFlags, + _In_ bool forceSRGB, + _In_ bool isCubeMap, + _In_ TextureSubResData* initData, + _Outptr_opt_ ITexture** texture + ) +{ + if (!pDevice || !initData) + { + LOG_ERROR_AND_THROW("Invalid arguments") + } + + + if (forceSRGB) + { + format = MakeSRGB(format); + } + + TextureDesc desc; + desc.Width = static_cast(width); + desc.MipLevels = static_cast(mipCount); + desc.ArraySize = static_cast(arraySize); + desc.Format = DXGIFormatToTexFormat(format); + desc.Usage = usage; + desc.BindFlags = bindFlags; + desc.CPUAccessFlags = cpuAccessFlags; + //desc.MiscFlags = miscFlags & ~D3D11_RESOURCE_MISC_TEXTURECUBE; + + TextureData InitData; + InitData.pSubResources = initData; + InitData.NumSubresources = static_cast(mipCount * arraySize); + + switch (resDim) + { + case D3D11_RESOURCE_DIMENSION_TEXTURE1D: + { + desc.Type = arraySize > 1 ? TEXTURE_TYPE_1D_ARRAY : TEXTURE_TYPE_1D; + pDevice->CreateTexture( desc, InitData, texture ); + + // ID3D11Texture1D* tex = nullptr; + // hr = d3dDevice->CreateTexture1D(&desc, initData, &tex); + + // if (SUCCEEDED(hr) && tex != 0) + // { + // if (textureView != 0) + // { + // D3D11_SHADER_RESOURCE_VIEW_DESC SRVDesc; + // memset(&SRVDesc, 0, sizeof(SRVDesc)); + // SRVDesc.Format = format; + + // if (arraySize > 1) + // { + // SRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURE1DARRAY; + // SRVDesc.Texture1DArray.MipLevels = desc.MipLevels; + // SRVDesc.Texture1DArray.ArraySize = static_cast(arraySize); + // } + // else + // { + // SRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURE1D; + // SRVDesc.Texture1D.MipLevels = desc.MipLevels; + // } + + // hr = d3dDevice->CreateShaderResourceView(tex, &SRVDesc, textureView); + + // if (FAILED(hr)) + // { + // tex->Release(); + // return hr; + // } + // } + + // if (texture != 0) + // { + // *texture = tex; + // } + // else + // { + // tex->Release(); + // } + // } + } + break; + + case TEXTURE_TYPE_2D: + case TEXTURE_TYPE_2D_ARRAY: + case TEXTURE_TYPE_CUBE: + case TEXTURE_TYPE_CUBE_ARRAY: + { + desc.Type = isCubeMap ? + (arraySize > 1 ? TEXTURE_TYPE_CUBE_ARRAY : TEXTURE_TYPE_CUBE) : + (arraySize > 1 ? TEXTURE_TYPE_2D_ARRAY : TEXTURE_TYPE_2D); + desc.Height = static_cast(height); + + //if (isCubeMap) + //{ + // desc.MiscFlags = miscFlags | D3D11_RESOURCE_MISC_TEXTURECUBE; + //} + //else + //{ + // desc.MiscFlags = miscFlags & ~D3D11_RESOURCE_MISC_TEXTURECUBE; + //} + + pDevice->CreateTexture( desc, InitData, texture ); + + //ID3D11Texture2D* tex = nullptr; + //hr = d3dDevice->CreateTexture2D(&desc, initData, &tex); + + //if (SUCCEEDED(hr) && tex != 0) + //{ + // if (textureView != 0) + // { + // D3D11_SHADER_RESOURCE_VIEW_DESC SRVDesc; + // memset(&SRVDesc, 0, sizeof(SRVDesc)); + // SRVDesc.Format = format; + + // if (isCubeMap) + // { + // if (arraySize > 6) + // { + // SRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURECUBEARRAY; + // SRVDesc.TextureCubeArray.MipLevels = desc.MipLevels; + + // // Earlier we set arraySize to (NumCubes * 6) + // SRVDesc.TextureCubeArray.NumCubes = static_cast(arraySize / 6); + // } + // else + // { + // SRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURECUBE; + // SRVDesc.TextureCube.MipLevels = desc.MipLevels; + // } + // } + // else if (arraySize > 1) + // { + // SRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURE2DARRAY; + // SRVDesc.Texture2DArray.MipLevels = desc.MipLevels; + // SRVDesc.Texture2DArray.ArraySize = static_cast(arraySize); + // } + // else + // { + // SRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURE2D; + // SRVDesc.Texture2D.MipLevels = desc.MipLevels; + // } + + // hr = d3dDevice->CreateShaderResourceView(tex, &SRVDesc, textureView); + + // if (FAILED(hr)) + // { + // tex->Release(); + // return hr; + // } + // } + + // if (texture != 0) + // { + // *texture = tex; + // } + // else + // { + // tex->Release(); + // } + //} + } + break; + + case TEXTURE_TYPE_3D: + { + desc.Type = TEXTURE_TYPE_3D; + desc.Height = static_cast(height); + desc.Depth = static_cast(depth); + + //desc.MiscFlags = miscFlags & ~D3D11_RESOURCE_MISC_TEXTURECUBE; + + pDevice->CreateTexture( desc, InitData, texture ); + + //ID3D11Texture3D* tex = nullptr; + //hr = d3dDevice->CreateTexture3D(&desc, initData, &tex); + + //if (SUCCEEDED(hr) && tex != 0) + //{ + // if (textureView != 0) + // { + // D3D11_SHADER_RESOURCE_VIEW_DESC SRVDesc; + // memset(&SRVDesc, 0, sizeof(SRVDesc)); + // SRVDesc.Format = format; + // SRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURE3D; + // SRVDesc.Texture3D.MipLevels = desc.MipLevels; + + // hr = d3dDevice->CreateShaderResourceView(tex, &SRVDesc, textureView); + + // if (FAILED(hr)) + // { + // tex->Release(); + // return hr; + // } + // } + + // if (texture != 0) + // { + // *texture = tex; + // } + // else + // { + // tex->Release(); + // } + //} + } + break; + } +} + +//-------------------------------------------------------------------------------------- +static void CreateTextureFromDDS( + _In_ IRenderDevice* pDevice, + _In_ const DDS_HEADER* header, + _In_ const Uint8* bitData, + _In_ size_t bitSize, + _In_ size_t maxsize, + _In_ USAGE usage, + _In_ unsigned int bindFlags, + _In_ unsigned int cpuAccessFlags, + _In_ unsigned int miscFlags, + _In_ bool forceSRGB, + _Outptr_opt_ ITexture** texture + ) +{ + size_t width = header->width; + size_t height = header->height; + size_t depth = header->depth; + + Uint32 resDim = D3D11_RESOURCE_DIMENSION_UNKNOWN; + size_t arraySize = 1; + DXGI_FORMAT format = DXGI_FORMAT_UNKNOWN; + bool isCubeMap = false; + + size_t mipCount = header->mipMapCount; + if (0 == mipCount) + { + mipCount = 1; + } + + + if ((header->ddspf.flags & DDS_FOURCC) && + (MAKEFOURCC('D', 'X', '1', '0') == header->ddspf.fourCC)) + { + auto d3d10ext = reinterpret_cast((const char*)header + sizeof(DDS_HEADER)); + + arraySize = d3d10ext->arraySize; + if (arraySize == 0) + { + LOG_ERROR_AND_THROW("Array size is zero"); + } + + if (BitsPerPixel(d3d10ext->dxgiFormat) == 0) + { + LOG_ERROR_AND_THROW("Undefined DXGI format"); + } + + format = d3d10ext->dxgiFormat; + + switch (d3d10ext->resourceDimension) + { + case D3D11_RESOURCE_DIMENSION_TEXTURE1D: + // D3DX writes 1D textures with a fixed Height of 1 + if ((header->flags & DDS_HEIGHT) && height != 1) + { + LOG_ERROR_AND_THROW("Unexpected height (", height, ") for texture 1D"); + } + height = depth = 1; + break; + + case D3D11_RESOURCE_DIMENSION_TEXTURE2D: + if (d3d10ext->miscFlag & D3D11_RESOURCE_MISC_TEXTURECUBE) + { + arraySize *= 6; + isCubeMap = true; + } + depth = 1; + break; + + case D3D11_RESOURCE_DIMENSION_TEXTURE3D: + if (!(header->flags & DDS_HEADER_FLAGS_VOLUME)) + { + LOG_ERROR_AND_THROW("DDS_HEADER_FLAGS_VOLUME flag is not set"); + } + + if (arraySize > 1) + { + LOG_ERROR_AND_THROW("Texture3D arrays are not allowed"); + } + break; + + default: + LOG_ERROR_AND_THROW("Unknown resource dimension"); + } + + resDim = d3d10ext->resourceDimension; + } + else + { + format = GetDXGIFormat(header->ddspf); + + if (format == DXGI_FORMAT_UNKNOWN) + { + LOG_ERROR_AND_THROW("Unknown DXGIF format"); + } + + if (header->flags & DDS_HEADER_FLAGS_VOLUME) + { + resDim = D3D11_RESOURCE_DIMENSION_TEXTURE3D; + } + else + { + if (header->caps2 & DDS_CUBEMAP) + { + // We require all six faces to be defined + if ((header->caps2 & DDS_CUBEMAP_ALLFACES) != DDS_CUBEMAP_ALLFACES) + { + LOG_ERROR_AND_THROW("All six faces of a cubemap must be defined"); + } + + arraySize = 6; + isCubeMap = true; + } + + depth = 1; + resDim = D3D11_RESOURCE_DIMENSION_TEXTURE2D; + + // Note there's no way for a legacy Direct3D 9 DDS to express a '1D' texture + } + + VERIFY_EXPR(BitsPerPixel(format) != 0); + } + + // Bound sizes (for security purposes we don't trust DDS file metadata larger than the D3D 11.x hardware requirements) + if (mipCount > D3D11_REQ_MIP_LEVELS) + { + LOG_ERROR_AND_THROW("Too many mip levels specified"); + } + + switch (resDim) + { + case D3D11_RESOURCE_DIMENSION_TEXTURE1D: + if ((arraySize > D3D11_REQ_TEXTURE1D_ARRAY_AXIS_DIMENSION) || + (width > D3D11_REQ_TEXTURE1D_U_DIMENSION)) + { + LOG_ERROR_AND_THROW("Texture1D dimensions are out of bounds"); + } + break; + + case D3D11_RESOURCE_DIMENSION_TEXTURE2D: + if (isCubeMap) + { + // This is the right bound because we set arraySize to (NumCubes*6) above + if ((arraySize > D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION) || + (width > D3D11_REQ_TEXTURECUBE_DIMENSION) || + (height > D3D11_REQ_TEXTURECUBE_DIMENSION)) + { + LOG_ERROR_AND_THROW("TextureCube dimensions are out of bounds"); + } + } + else if ((arraySize > D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION) || + (width > D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION) || + (height > D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION)) + { + LOG_ERROR_AND_THROW("Texture2D dimensions are out of bounds"); + } + break; + + case D3D11_RESOURCE_DIMENSION_TEXTURE3D: + if ((arraySize > 1) || + (width > D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION) || + (height > D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION) || + (depth > D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION)) + { + LOG_ERROR_AND_THROW("Texture3D dimensions are out of bounds"); + } + break; + } + // Create the texture + std::unique_ptr initData(new TextureSubResData[mipCount * arraySize]); + + size_t skipMip = 0; + size_t twidth = 0; + size_t theight = 0; + size_t tdepth = 0; + FillInitData(width, height, depth, mipCount, arraySize, format, maxsize, bitSize, bitData, twidth, theight, tdepth, skipMip, initData.get()); + + CreateTexture(pDevice, resDim, twidth, theight, tdepth, mipCount - skipMip, arraySize, format, usage, bindFlags, cpuAccessFlags, miscFlags, forceSRGB, isCubeMap, initData.get(), texture/*, textureView*/); + +#if 0 + if (FAILED(hr) && !maxsize && (mipCount > 1)) + { + // Retry with a maxsize determined by feature level + switch (d3dDevice->GetFeatureLevel()) + { + case D3D_FEATURE_LEVEL_9_1: + case D3D_FEATURE_LEVEL_9_2: + if (isCubeMap) + { + maxsize = D3D_FL9_1_REQ_TEXTURECUBE_DIMENSION; + } + else + { + maxsize = (resDim == D3D11_RESOURCE_DIMENSION_TEXTURE3D) + ? D3D_FL9_1_REQ_TEXTURE3D_U_V_OR_W_DIMENSION + : D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION; + } + break; + + case D3D_FEATURE_LEVEL_9_3: + maxsize = (resDim == D3D11_RESOURCE_DIMENSION_TEXTURE3D) + ? D3D_FL9_1_REQ_TEXTURE3D_U_V_OR_W_DIMENSION + : 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) + ? D3D10_REQ_TEXTURE3D_U_V_OR_W_DIMENSION + : D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION; + break; + } + + FillInitData(width, height, depth, mipCount, arraySize, format, maxsize, bitSize, bitData, twidth, theight, tdepth, skipMip, initData.get()); + + hr = CreateTexture(d3dDevice, resDim, twidth, theight, tdepth, mipCount - skipMip, arraySize, format, usage, bindFlags, cpuAccessFlags, miscFlags, forceSRGB, isCubeMap, initData.get(), texture, textureView); + } +#endif +} + +#if 0 +//-------------------------------------------------------------------------------------- +static D2D1_ALPHA_MODE GetAlphaMode(_In_ const DDS_HEADER* header) +{ + if (header->ddspf.flags & DDS_FOURCC) + { + if (MAKEFOURCC('D', 'X', '1', '0') == header->ddspf.fourCC) + { + auto d3d10ext = reinterpret_cast((const char*)header + sizeof(DDS_HEADER)); + switch (d3d10ext->miscFlags2 & DDS_MISC_FLAGS2_ALPHA_MODE_MASK) + { + case DDS_ALPHA_MODE_STRAIGHT: + return D2D1_ALPHA_MODE_STRAIGHT; + + case DDS_ALPHA_MODE_PREMULTIPLIED: + return D2D1_ALPHA_MODE_PREMULTIPLIED; + + case DDS_ALPHA_MODE_OPAQUE: + case DDS_ALPHA_MODE_CUSTOM: + // No D2D1_ALPHA_MODE equivalent, so return "Ignore" for now + return D2D1_ALPHA_MODE_IGNORE; + } + } + else if ((MAKEFOURCC('D', 'X', 'T', '2') == header->ddspf.fourCC) + || (MAKEFOURCC('D', 'X', 'T', '4') == header->ddspf.fourCC)) + { + return D2D1_ALPHA_MODE_PREMULTIPLIED; + } + // DXT1, DXT3, and DXT5 legacy files could be straight alpha or something else, so return "Unknown" to leave it up to the app + } + + return D2D1_ALPHA_MODE_UNKNOWN; +} + +#endif + +//-------------------------------------------------------------------------------------- +void CreateDDSTextureFromMemory( + IRenderDevice* pDevice, + const Uint8* ddsData, + size_t ddsDataSize, + ITexture** texture, + size_t maxsize/*, + D2D1_ALPHA_MODE* alphaMode*/ + ) +{ + return CreateDDSTextureFromMemoryEx(pDevice, ddsData, ddsDataSize, maxsize, USAGE_DEFAULT, BIND_SHADER_RESOURCE, 0, 0, false, texture/*, alphaMode*/); +} + + +//-------------------------------------------------------------------------------------- +void CreateDDSTextureFromMemoryEx( + IRenderDevice* pDevice, + const Uint8* ddsData, + size_t ddsDataSize, + size_t maxsize, + USAGE usage, + unsigned int bindFlags, + unsigned int cpuAccessFlags, + unsigned int miscFlags, + bool forceSRGB, + ITexture** texture/*, + D2D1_ALPHA_MODE* alphaMode*/ + ) +{ + if (texture) + { + VERIFY( *texture == nullptr, "Overwriting reference to an existing object is unsafe") + *texture = nullptr; + } + //if (textureView) + //{ + // *textureView = nullptr; + //} + //if (alphaMode) + //{ + // *alphaMode = D2D1_ALPHA_MODE_UNKNOWN; + //} + + if (!pDevice || !ddsData || (!texture /*&& !textureView*/)) + { + LOG_ERROR_AND_THROW("Invalid arguments"); + } + + // Validate DDS file in memory + if (ddsDataSize < (sizeof(Uint32) + sizeof(DDS_HEADER))) + { + LOG_ERROR_AND_THROW("Invalid dds file"); + } + + Uint32 dwMagicNumber = *(const Uint32*)(ddsData); + if (dwMagicNumber != DDS_MAGIC) + { + LOG_ERROR_AND_THROW("Invalid dds file"); + } + + auto header = reinterpret_cast(ddsData + sizeof(Uint32)); + + // Verify header to validate DDS file + if (header->size != sizeof(DDS_HEADER) || + header->ddspf.size != sizeof(DDS_PIXELFORMAT)) + { + LOG_ERROR_AND_THROW("Invalid dds file header"); + } + + // Check for DX10 extension + bool bDXT10Header = false; + if ((header->ddspf.flags & DDS_FOURCC) && + (MAKEFOURCC('D', 'X', '1', '0') == header->ddspf.fourCC)) + { + // Must be long enough for both headers and magic value + if (ddsDataSize < (sizeof(DDS_HEADER) + sizeof(Uint32) + sizeof(DDS_HEADER_DXT10))) + { + LOG_ERROR_AND_THROW("Invalid DX10 extension"); + } + + bDXT10Header = true; + } + + ptrdiff_t offset = sizeof(Uint32) + sizeof(DDS_HEADER) + (bDXT10Header ? sizeof(DDS_HEADER_DXT10) : 0); + + CreateTextureFromDDS(pDevice, header, ddsData + offset, ddsDataSize - offset, maxsize, usage, bindFlags, cpuAccessFlags, miscFlags, forceSRGB, texture/*, textureView*/); + + //if (alphaMode) + // *alphaMode = GetAlphaMode(header); +} diff --git a/TextureLoader/src/Image.cpp b/TextureLoader/src/Image.cpp new file mode 100644 index 0000000..d78f2da --- /dev/null +++ b/TextureLoader/src/Image.cpp @@ -0,0 +1,409 @@ +/* Copyright 2015 Egor Yusov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#include "pch.h" +#include "Image.h" +#include "Errors.h" + +#include "tiffio.h" +#include "png.h" +#include "jpeglib.h" + +#include "DataBlobImpl.h" +#include "DebugUtilities.h" +#include "RefCntAutoPtr.h" + +using namespace Diligent; +using namespace Diligent; + +namespace Diligent +{ + class TIFFClientOpenWrapper + { + public: + TIFFClientOpenWrapper( IDataBlob *pData ) : + m_pData( pData ), + m_Offset( 0 ), + m_Size( pData->GetSize() ) + { + } + + static tmsize_t TIFFReadProc( thandle_t pClientData, void* pBuffer, tmsize_t Size ) + { + auto *pThis = reinterpret_cast(pClientData); + auto *pSrcPtr = reinterpret_cast(pThis->m_pData->GetDataPtr()) + pThis->m_Offset; + memcpy( pBuffer, pSrcPtr, Size ); + pThis->m_Offset += Size; + return Size; + } + + static tmsize_t TIFFWriteProc( thandle_t pClientData, void* pBuffer, tmsize_t Size ) + { + auto *pThis = reinterpret_cast(pClientData); + if( pThis->m_Offset + Size > pThis->m_Size ) + { + pThis->m_Size = pThis->m_Offset + Size; + pThis->m_pData->Resize( pThis->m_Size ); + } + auto *pDstPtr = reinterpret_cast(pThis->m_pData->GetDataPtr()) + pThis->m_Offset; + memcpy( pDstPtr, pBuffer, Size ); + pThis->m_Offset += Size; + return Size; + } + + static toff_t TIFFSeekProc( thandle_t pClientData, toff_t Offset, int Whence ) + { + auto *pThis = reinterpret_cast(pClientData); + switch( Whence ) + { + case SEEK_SET: pThis->m_Offset = static_cast(Offset); break; + case SEEK_CUR: pThis->m_Offset += static_cast(Offset); break; + case SEEK_END: pThis->m_Offset = pThis->m_Size + static_cast(Offset); break; + default: UNEXPECTED( "Unexpected whence" ); + } + + return pThis->m_Offset; + } + + static int TIFFCloseProc( thandle_t pClientData ) + { + auto *pThis = reinterpret_cast(pClientData); + pThis->m_pData.Release(); + pThis->m_Size = 0; + pThis->m_Offset = 0; + return 0; + } + + static toff_t TIFFSizeProc( thandle_t pClientData ) + { + auto *pThis = reinterpret_cast(pClientData); + return pThis->m_Size; + } + + static int TIFFMapFileProc( thandle_t pClientData, void** base, toff_t* size ) + { + UNEXPECTED( "Client file mapping is not implemented. Use \'m\' when opening TIFF file to disable file mapping." ) + return 0; + } + + static void TIFFUnmapFileProc( thandle_t pClientData, void* base, toff_t size ) + { + UNEXPECTED( "Client file mapping is not implemented. Use \'m\' when opening TIFF file to disable file mapping." ) + } + + private: + size_t m_Offset; + size_t m_Size; + RefCntAutoPtr m_pData; + }; + + void Image::LoadTiffFile( IDataBlob *pFileData, const ImageLoadInfo& LoadInfo ) + { + TIFFClientOpenWrapper TiffClientOpenWrpr(pFileData); + + auto TiffFile = TIFFClientOpen("", "rm", &TiffClientOpenWrpr, + TIFFClientOpenWrapper::TIFFReadProc, + TIFFClientOpenWrapper::TIFFWriteProc, + TIFFClientOpenWrapper::TIFFSeekProc, + TIFFClientOpenWrapper::TIFFCloseProc, + TIFFClientOpenWrapper::TIFFSizeProc, + TIFFClientOpenWrapper::TIFFMapFileProc, + TIFFClientOpenWrapper::TIFFUnmapFileProc); + + TIFFGetField(TiffFile, TIFFTAG_IMAGEWIDTH, &m_Desc.Width); + TIFFGetField(TiffFile, TIFFTAG_IMAGELENGTH, &m_Desc.Height); + + Uint16 SamplesPerPixel = 0; + // SamplesPerPixel is usually 1 for bilevel, grayscale, and palette-color images. + // SamplesPerPixel is usually 3 for RGB images. If this value is higher, ExtraSamples + // should give an indication of the meaning of the additional channels. + TIFFGetField(TiffFile, TIFFTAG_SAMPLESPERPIXEL, &SamplesPerPixel); + m_Desc.NumComponents = SamplesPerPixel; + + Uint16 BitsPerSample = 0; + TIFFGetField(TiffFile, TIFFTAG_BITSPERSAMPLE, &BitsPerSample); + m_Desc.BitsPerPixel = m_Desc.NumComponents * BitsPerSample; + + auto ScanlineSize = TIFFScanlineSize(TiffFile); + m_Desc.RowStride = static_cast( ScanlineSize ); + m_pData->Resize(m_Desc.Height * m_Desc.RowStride ); + auto *pDataPtr = reinterpret_cast( m_pData->GetDataPtr() ); + for (Uint32 row = 0; row < m_Desc.Height; row++, pDataPtr += ScanlineSize) + { + TIFFReadScanline(TiffFile, pDataPtr, row); + } + TIFFClose(TiffFile); + } + + + class PNGReadFnHelper + { + public: + PNGReadFnHelper( IDataBlob *pData ) : + m_pData( pData ), + m_Offset( 0 ) + { + } + + static void ReadData( png_structp pngPtr, png_bytep data, png_size_t length ) + { + auto pThis = reinterpret_cast( png_get_io_ptr(pngPtr) ); + memcpy( data, reinterpret_cast(pThis->m_pData->GetDataPtr()) + pThis->m_Offset, length ); + pThis->m_Offset += length; + } + + private: + RefCntAutoPtr m_pData; + size_t m_Offset; + }; + + void Image::LoadPngFile( IDataBlob *pFileData, const ImageLoadInfo& LoadInfo ) + { + // http://www.piko3d.net/tutorials/libpng-tutorial-loading-png-files-from-streams/ + // http://www.libpng.org/pub/png/book/chapter13.html#png.ch13.div.10 + // https://gist.github.com/niw/5963798\ + + PNGReadFnHelper ReadFnHelper(pFileData); + + const size_t PngSigSize = 8; + png_const_bytep pngsig = reinterpret_cast(pFileData->GetDataPtr()); + //Let LibPNG check the signature. If this function returns 0, everything is OK. + if( png_sig_cmp( pngsig, 0, PngSigSize ) != 0 ) + { + LOG_ERROR_AND_THROW( "Invalid png signature" ); + } + + png_structp png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + VERIFY(png, "png_create_read_struct() failed") + + png_infop info = png_create_info_struct(png); + VERIFY(info, "png_create_info_struct() failed") + + if( setjmp( png_jmpbuf( png ) ) ) + { + // When an error occurs during parsing, libPNG will jump to here + png_destroy_read_struct(&png, &info, (png_infopp)0); + LOG_ERROR_AND_THROW( "Failed to read png file" ); + } + + png_set_read_fn(png, (png_voidp)&ReadFnHelper, PNGReadFnHelper::ReadData); + + png_read_info(png, info); + + m_Desc.Width = png_get_image_width(png, info); + m_Desc.Height = png_get_image_height(png, info); + m_Desc.NumComponents = png_get_channels(png, info); + auto bit_depth = png_get_bit_depth(png, info); + m_Desc.BitsPerPixel = bit_depth * m_Desc.NumComponents; + auto color_type = png_get_color_type(png, info); + + // PNG files store 16-bit pixels in network byte order (big-endian, ie + // most significant bytes first). png_set_swap() shall switch the byte-order + // to little-endian (ie, least significant bits first). + if( bit_depth == 16 ) + png_set_swap(png); + +#if 0 + // Read any color_type into 8bit depth, RGBA format. + // See http://www.libpng.org/pub/png/libpng-manual.txt + + if( bit_depth == 16 ) + png_set_strip_16( png ); + + if( color_type == PNG_COLOR_TYPE_PALETTE ) + png_set_palette_to_rgb( png ); + + // PNG_COLOR_TYPE_GRAY_ALPHA is always 8 or 16bit depth. + if( color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8 ) + png_set_expand_gray_1_2_4_to_8( png ); + + if( png_get_valid( png, info, PNG_INFO_tRNS ) ) + png_set_tRNS_to_alpha( png ); + + // These color_type don't have an alpha channel then fill it with 0xff. + if( color_type == PNG_COLOR_TYPE_RGB || + color_type == PNG_COLOR_TYPE_GRAY || + color_type == PNG_COLOR_TYPE_PALETTE ) + png_set_filler( png, 0xFF, PNG_FILLER_AFTER ); + + if( color_type == PNG_COLOR_TYPE_GRAY || + color_type == PNG_COLOR_TYPE_GRAY_ALPHA ) + png_set_gray_to_rgb( png ); + + png_read_update_info( png, info ); +#endif + + //Array of row pointers. One for every row. + std::vector rowPtrs(m_Desc.Height); + + //Alocate a buffer with enough space. + m_Desc.RowStride = m_Desc.Width * bit_depth * m_Desc.NumComponents / 8; + m_pData->Resize( m_Desc.Height * m_Desc.RowStride ); + for( size_t i = 0; i < m_Desc.Height; i++ ) + rowPtrs[i] = reinterpret_cast(m_pData->GetDataPtr()) + i * m_Desc.RowStride; + + //Read the imagedata and write it to the adresses pointed to + //by rowptrs (in other words: our image databuffer) + png_read_image( png, rowPtrs.data() ); + + png_destroy_read_struct(&png, &info, (png_infopp)0); + } + + + + struct my_jpeg_error_mgr { + jpeg_error_mgr pub; + jmp_buf setjmp_buffer;// for return to caller + }; + + // Here's the routine that will replace the standard error_exit method: + METHODDEF(void) + my_error_exit (j_common_ptr cinfo) + { + // cinfo->err really points to a my_jpeg_error_mgr struct, so coerce pointer + my_jpeg_error_mgr* myerr = (my_jpeg_error_mgr*) cinfo->err; + + /* Always display the message. */ + /* We could postpone this until after returning, if we chose. */ + (*cinfo->err->output_message) (cinfo); + + // Return control to the setjmp point + longjmp(myerr->setjmp_buffer, 1); + } + + void Image::LoadJpegFile( IDataBlob *pFileData, const ImageLoadInfo& LoadInfo ) + { + // https://github.com/LuaDist/libjpeg/blob/master/example.c + + // This struct contains the JPEG decompression parameters and pointers to + // working space (which is allocated as needed by the JPEG library). + jpeg_decompress_struct cinfo; + + // We use our private extension JPEG error handler. + // Note that this struct must live as long as the main JPEG parameter + // struct, to avoid dangling-pointer problems. + my_jpeg_error_mgr jerr; + + // Step 1: allocate and initialize JPEG decompression object + + // We set up the normal JPEG error routines, then override error_exit. + cinfo.err = jpeg_std_error( &jerr.pub ); + jerr.pub.error_exit = my_error_exit; + // Establish the setjmp return context for my_error_exit to use. + if( setjmp( jerr.setjmp_buffer ) ) + { + // If we get here, the JPEG code has signaled an error. + // We need to clean up the JPEG object, close the input file, and return. + jpeg_destroy_decompress( &cinfo ); + LOG_ERROR_AND_THROW( "Failed to decompress JPEG image" ) + } + // Now we can initialize the JPEG decompression object. + jpeg_create_decompress( &cinfo ); + + // Step 2: specify data source + jpeg_mem_src( &cinfo, reinterpret_cast(pFileData->GetDataPtr()), static_cast(pFileData->GetSize()) ); + + // Step 3: read file parameters with jpeg_read_header() + jpeg_read_header( &cinfo, TRUE ); + // We can ignore the return value from jpeg_read_header since + // (a) suspension is not possible with the stdio data source, and + // (b) we passed TRUE to reject a tables-only JPEG file as an error. + // See libjpeg.txt for more info. + + + // Step 4: set parameters for decompression + + // In this example, we don't need to change any of the defaults set by + // jpeg_read_header(), so we do nothing here. + + + // Step 5: Start decompressor + + jpeg_start_decompress( &cinfo ); + // We can ignore the return value since suspension is not possible + // with the stdio data source. + + // We may need to do some setup of our own at this point before reading + // the data. After jpeg_start_decompress() we have the correct scaled + // output image dimensions available, as well as the output colormap + // if we asked for color quantization. + + m_Desc.Width = cinfo.output_width; + m_Desc.Height = cinfo.output_height; + m_Desc.NumComponents = cinfo.output_components; + m_Desc.RowStride = m_Desc.Width * m_Desc.NumComponents; + m_Desc.BitsPerPixel = 8 * m_Desc.NumComponents; + + m_pData->Resize(m_Desc.RowStride * m_Desc.Height); + // Step 6: while (scan lines remain to be read) + // jpeg_read_scanlines(...); + + // Here we use the library's state variable cinfo.output_scanline as the + // loop counter, so that we don't have to keep track ourselves. + while( cinfo.output_scanline < cinfo.output_height ) { + // jpeg_read_scanlines expects an array of pointers to scanlines. + // Here the array is only one element long, but you could ask for + // more than one scanline at a time if that's more convenient. + + + auto *pDstScanline = reinterpret_cast( m_pData->GetDataPtr() ) + cinfo.output_scanline * m_Desc.RowStride; + JSAMPROW RowPtrs[] = { reinterpret_cast(pDstScanline) }; + jpeg_read_scanlines( &cinfo, RowPtrs, 1 ); + } + + // Step 7: Finish decompression + + jpeg_finish_decompress( &cinfo ); + // We can ignore the return value since suspension is not possible + // with the stdio data source. + + // Step 8: Release JPEG decompression object + + // This is an important step since it will release a good deal of memory. + jpeg_destroy_decompress( &cinfo ); + + // At this point you may want to check to see whether any corrupt-data + // warnings occurred (test whether jerr.pub.num_warnings is nonzero). + } + + Image::Image( Diligent::IFileStream *pSrcFile, + const ImageLoadInfo& LoadInfo ) : + m_pData( new Diligent::DataBlobImpl ) + { + RefCntAutoPtr pFileData( new Diligent::DataBlobImpl ); + pSrcFile->Read(pFileData); + + if( LoadInfo.Format == EImageFileFormat::tiff ) + { + LoadTiffFile(pFileData, LoadInfo ); + } + else if( LoadInfo.Format == EImageFileFormat::png ) + { + LoadPngFile(pFileData, LoadInfo ); + } + else if( LoadInfo.Format == EImageFileFormat::jpeg ) + { + LoadJpegFile(pFileData, LoadInfo ); + } + } +} diff --git a/TextureLoader/src/TextureLoader.cpp b/TextureLoader/src/TextureLoader.cpp new file mode 100644 index 0000000..63134a4 --- /dev/null +++ b/TextureLoader/src/TextureLoader.cpp @@ -0,0 +1,248 @@ +/* Copyright 2015 Egor Yusov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#include "pch.h" +#include "TextureLoader.h" +#include "GraphicsUtilities.h" +#include +#include +#include "DDSLoader.h" + +using namespace Diligent; + +namespace Diligent +{ + static const float a = 0.055f; + + // https://en.wikipedia.org/wiki/SRGB + float SRGBToLinear(float SRGB) + { + if( SRGB < 0.04045f ) + return SRGB / 12.92f; + else + return powf( (SRGB + a) / (1 + a), 2.4f ); + } + + float LinearToSRGB( float c ) + { + if( c < 0.0031308f ) + return 12.92f * c; + else + return (1+a) * pow(c, 1.f/2.4f) - a; + } + + template + ChannelType SRGBAverage(ChannelType c0, ChannelType c1, ChannelType c2, ChannelType c3) + { + const float NormVal = static_cast(std::numeric_limits::max()); + float fc0 = static_cast(c0) / NormVal; + float fc1 = static_cast(c1) / NormVal; + float fc2 = static_cast(c2) / NormVal; + float fc3 = static_cast(c3) / NormVal; + + float fLinearAverage = (SRGBToLinear( fc0 ) + SRGBToLinear( fc1 ) + SRGBToLinear( fc2 ) + SRGBToLinear( fc3 )) / 4.f; + float fSRGBAverage = LinearToSRGB(fLinearAverage); + Int32 SRGBAverage = static_cast(fSRGBAverage * NormVal); + SRGBAverage = std::min(SRGBAverage, static_cast( std::numeric_limits::max()) ); + SRGBAverage = std::max(SRGBAverage, static_cast( std::numeric_limits::min()) ); + return static_cast(SRGBAverage); + } + + template < typename ChannelType > + void ComputeCoarseMip(Uint32 NumChannels, bool IsSRGB, + const void *pFineMip, Uint32 FineMipStride, + void *pCoarseMip, Uint32 CoarseMipStride, + Uint32 CoarseMipWidth, Uint32 CoarseMipHeight) + { + for( Uint32 row = 0; row < CoarseMipHeight; ++row ) + for( Uint32 col = 0; col < CoarseMipWidth; ++col ) + { + auto FineRow0 = reinterpret_cast( reinterpret_cast(pFineMip) + row * 2 * FineMipStride ); + auto FineRow1 = reinterpret_cast( reinterpret_cast(pFineMip) + (row * 2 + 1 ) * FineMipStride ); + + for( Uint32 c = 0; c < NumChannels; ++c ) + { + auto Col00 = FineRow0[ col*2 * NumChannels + c ]; + auto Col01 = FineRow0[ (col*2+1) * NumChannels + c ]; + auto Col10 = FineRow1[ col*2 * NumChannels + c ]; + auto Col11 = FineRow1[ (col*2+1) * NumChannels + c ]; + auto &DstCol = reinterpret_cast(reinterpret_cast(pCoarseMip) + row * CoarseMipStride)[col * NumChannels + c]; + if( IsSRGB ) + DstCol = SRGBAverage( Col00, Col01, Col10, Col11 ); + else + DstCol = (Col00 + Col01 + Col10 + Col11)/4; + } + } + } + + template < typename ChannelType > + void RGBToRGBA(const void *pRGBData, Uint32 RGBStride, + void *pRGBAData, Uint32 RGBAStride, + Uint32 Width, Uint32 Height) + { + for( Uint32 row = 0; row < Height; ++row ) + for( Uint32 col = 0; col < Width; ++col ) + { + for( int c = 0; c < 3; ++c ) + { + reinterpret_cast( (reinterpret_cast(pRGBAData) + RGBAStride * row) ) [col *4 + c] = + reinterpret_cast( (reinterpret_cast(pRGBData) + RGBStride * row))[col*3 + c]; + } + reinterpret_cast( (reinterpret_cast(pRGBAData) + RGBAStride * row) ) [col *4 + 3] = std::numeric_limits::max(); + } + } + + void CreateTextureFromImage( Image *pSrcImage, + const TextureLoadInfo& TexLoadInfo, + Diligent::IRenderDevice *pDevice, + Diligent::ITexture **ppTexture ) + { + const auto& ImgDesc = pSrcImage->GetDesc(); + TextureDesc TexDesc; + TexDesc.Type = TEXTURE_TYPE_2D; + TexDesc.Width = ImgDesc.Width; + TexDesc.Height = ImgDesc.Height; + TexDesc.MipLevels = ComputeMipLevelsCount( TexDesc.Width, TexDesc.Height ); + if( TexLoadInfo.MipLevels > 0 ) + TexDesc.MipLevels = std::min(TexDesc.MipLevels, TexLoadInfo.MipLevels); + TexDesc.Usage = TexLoadInfo.Usage; + TexDesc.BindFlags = TexLoadInfo.BindFlags; + TexDesc.Format = TexLoadInfo.Format; + TexDesc.CPUAccessFlags = TexLoadInfo.CPUAccessFlags; + auto ChannelDepth = ImgDesc.BitsPerPixel / ImgDesc.NumComponents; + + Uint32 NumComponents = ImgDesc.NumComponents == 3 ? 4 : ImgDesc.NumComponents; + bool IsSRGB = (ImgDesc.NumComponents >= 3 && ChannelDepth == 8) ? TexLoadInfo.IsSRGB : false; + if( TexDesc.Format == TEX_FORMAT_UNKNOWN ) + { + if( ChannelDepth == 8 ) + { + switch( NumComponents ) + { + case 1: TexDesc.Format = TEX_FORMAT_R8_UNORM; break; + case 2: TexDesc.Format = TEX_FORMAT_RG8_UNORM; break; + case 4: TexDesc.Format = IsSRGB ? TEX_FORMAT_RGBA8_UNORM_SRGB : TEX_FORMAT_RGBA8_UNORM; break; + default: LOG_ERROR_AND_THROW( "Unexpected number of color channels (", ImgDesc.NumComponents, ")" ); + } + } + else if( ChannelDepth == 16 ) + { + switch( NumComponents ) + { + case 1: TexDesc.Format = TEX_FORMAT_R16_UNORM; break; + case 2: TexDesc.Format = TEX_FORMAT_RG16_UNORM; break; + case 4: TexDesc.Format = TEX_FORMAT_RGBA16_UNORM; break; + default: LOG_ERROR_AND_THROW( "Unexpected number of color channels (", ImgDesc.NumComponents, ")" ); + } + } + else + LOG_ERROR_AND_THROW( "Unsupported color channel depth (", ChannelDepth, ")" ); + } + else + { + const auto& TexFmtDesc = GetTextureFormatAttribs( TexDesc.Format ); + if( TexFmtDesc.NumComponents != NumComponents ) + LOG_ERROR_AND_THROW( "Incorrect number of components ", ImgDesc.NumComponents, ") for texture format ", TexFmtDesc.Name ); + if( TexFmtDesc.ComponentSize != ChannelDepth / 8 ) + LOG_ERROR_AND_THROW( "Incorrect channel size ", ChannelDepth, ") for texture format ", TexFmtDesc.Name ); + } + + + std::vector pSubResources(TexDesc.MipLevels); + std::vector< std::vector > Mips(TexDesc.MipLevels); + + if( ImgDesc.NumComponents == 3 ) + { + VERIFY_EXPR( NumComponents == 4 ); + auto RGBAStride = ImgDesc.Width * NumComponents * ChannelDepth / 8; + RGBAStride = (RGBAStride + 3) & (-4); + Mips[0].resize(RGBAStride * ImgDesc.Height); + pSubResources[0].pData = Mips[0].data(); + pSubResources[0].Stride = RGBAStride; + if( ChannelDepth == 8 ) + RGBToRGBA( pSrcImage->GetData()->GetDataPtr(), ImgDesc.RowStride, + Mips[0].data(), RGBAStride, + ImgDesc.Width, ImgDesc.Height); + else if( ChannelDepth == 16 ) + RGBToRGBA( pSrcImage->GetData()->GetDataPtr(), ImgDesc.RowStride, + Mips[0].data(), RGBAStride, + ImgDesc.Width, ImgDesc.Height); + } + else + { + pSubResources[0].pData = pSrcImage->GetData()->GetDataPtr(); + pSubResources[0].Stride = ImgDesc.RowStride; + } + + auto MipWidth = TexDesc.Width; + auto MipHeight = TexDesc.Height; + for( Uint32 m = 1; m < TexDesc.MipLevels; ++m ) + { + auto CoarseMipWidth = std::max(MipWidth/2u, 1u); + auto CoarseMipHeight = std::max(MipHeight/2u, 1u); + auto CoarseMipStride = CoarseMipWidth * NumComponents * ChannelDepth / 8; + CoarseMipStride = (CoarseMipStride + 3) & (-4); + Mips[m].resize(CoarseMipStride * CoarseMipHeight); + + if( ChannelDepth == 8 ) + ComputeCoarseMip( NumComponents, IsSRGB, + pSubResources[m-1].pData, pSubResources[m-1].Stride, + Mips[m].data(), CoarseMipStride, + CoarseMipWidth, CoarseMipHeight); + else if( ChannelDepth == 16 ) + ComputeCoarseMip( NumComponents, IsSRGB, + pSubResources[m-1].pData, pSubResources[m-1].Stride, + Mips[m].data(), CoarseMipStride, + CoarseMipWidth, CoarseMipHeight); + + pSubResources[m].pData = Mips[m].data(); + pSubResources[m].Stride = CoarseMipStride; + + MipWidth = CoarseMipWidth; + MipHeight = CoarseMipHeight; + } + + TextureData TexData; + TexData.pSubResources = pSubResources.data(); + TexData.NumSubresources = TexDesc.MipLevels; + + pDevice->CreateTexture( TexDesc, TexData, ppTexture ); + } + + void CreateTextureFromDDS( IDataBlob *pDDSData, + const TextureLoadInfo& TexLoadInfo, + Diligent::IRenderDevice *pDevice, + Diligent::ITexture **ppTexture ) + { + CreateDDSTextureFromMemoryEx(pDevice, + reinterpret_cast(pDDSData->GetDataPtr()), + static_cast(pDDSData->GetSize()), + 0, // maxSize + TexLoadInfo.Usage, + TexLoadInfo.BindFlags, + TexLoadInfo.CPUAccessFlags, + 0, // miscFlags + false, // forceSRGB + ppTexture ); + } +} diff --git a/TextureLoader/src/TextureUtilities.cpp b/TextureLoader/src/TextureUtilities.cpp new file mode 100644 index 0000000..2ee94ba --- /dev/null +++ b/TextureLoader/src/TextureUtilities.cpp @@ -0,0 +1,95 @@ +/* Copyright 2015 Egor Yusov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#include "pch.h" +#include "TextureUtilities.h" +#include "Errors.h" +#include "TextureLoader.h" +#include "Image.h" +#include "BasicFileStream.h" +#include "RefCntAutoPtr.h" +#include "DataBlobImpl.h" +#include + +using namespace Diligent; + +namespace Diligent +{ + +void CreateImageFromFile( const Diligent::Char *FilePath, + Image **ppImage, + IDataBlob **ppDDSData) +{ + auto *pDotPos = strrchr( FilePath, '.' ); + if( pDotPos == nullptr ) + LOG_ERROR_AND_THROW( "File path ", FilePath, " does not contain extension" ); + + auto *pExtension = pDotPos + 1; + if( *pExtension == 0 ) + LOG_ERROR_AND_THROW( "File path ", FilePath, " contains empty extension" ); + + String Extension(pExtension); + std::transform( Extension.begin(), Extension.end(), Extension.begin(), ::tolower ); + + Diligent::RefCntAutoPtr pFileStream( new BasicFileStream( FilePath, EFileAccessMode::Read ) ); + + if( Extension == "dds" ) + { + VERIFY_EXPR(ppDDSData != nullptr); + *ppDDSData = new DataBlobImpl; + pFileStream->Read(*ppDDSData); + (*ppDDSData)->AddRef(); + } + else + { + ImageLoadInfo ImgLoadInfo; + if( Extension == "png" ) + ImgLoadInfo.Format = EImageFileFormat::png; + else if( Extension == "jpeg" || Extension == "jpg" ) + ImgLoadInfo.Format = EImageFileFormat::jpeg; + else if( Extension == "tiff" || Extension == "tif" ) + ImgLoadInfo.Format = EImageFileFormat::tiff; + else + LOG_ERROR_AND_THROW( "Unsupported file format ", Extension ); + + *ppImage = new Image(pFileStream, ImgLoadInfo); + (*ppImage)->AddRef(); + } +} + +void CreateTextureFromFile( const Diligent::Char *FilePath, + const TextureLoadInfo& TexLoadInfo, + IRenderDevice *pDevice, + ITexture **ppTexture ) +{ + RefCntAutoPtr pImage; + RefCntAutoPtr pDDSData; + CreateImageFromFile( FilePath, &pImage, &pDDSData ); + + if( pImage ) + CreateTextureFromImage( pImage, TexLoadInfo, pDevice, ppTexture ); + else if(pDDSData) + CreateTextureFromDDS( pDDSData, TexLoadInfo, pDevice, ppTexture ); +} + +} diff --git a/TextureLoader/src/pch.cpp b/TextureLoader/src/pch.cpp new file mode 100644 index 0000000..4a893f2 --- /dev/null +++ b/TextureLoader/src/pch.cpp @@ -0,0 +1,25 @@ +/* Copyright 2015 Egor Yusov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#include "pch.h" + -- cgit v1.2.3