From dd31103d8fb549c3be80d33304a20f512702981b Mon Sep 17 00:00:00 2001 From: Olli Kallioinen Date: Sat, 8 Jul 2017 07:46:01 +0300 Subject: [PATCH 1/5] Build fixes: - Fixes to allow building with MinGW (and clion) - CMake cleanup - Changed cmake root project name to Etc2Comp from confusing EtcTest --- .gitignore | 1 + CMakeLists.txt | 42 ++++++++++++++++++++++++++++-------------- EtcLib/CMakeLists.txt | 2 +- EtcTool/CMakeLists.txt | 6 +++++- EtcTool/EtcTool.cpp | 3 +++ EtcTool/EtcTool.h | 3 +++ README.md | 6 +++--- 7 files changed, 44 insertions(+), 19 deletions(-) diff --git a/.gitignore b/.gitignore index 4100db6..36146ac 100755 --- a/.gitignore +++ b/.gitignore @@ -17,6 +17,7 @@ Debug/ ipch/ *.sdf .vs/ +.idea/ *Debug/ *Release/ *debug*/ diff --git a/CMakeLists.txt b/CMakeLists.txt index 6a6392b..4cc4191 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,18 +12,32 @@ # See the License for the specific language governing permissions and # limitations under the License. -cmake_minimum_required(VERSION 2.8.9) -project(EtcTest) +cmake_minimum_required(VERSION 3.1) +project(Etc2Comp) -set (CMAKE_CXX_STANDARD 11) -IF (APPLE) - set (CMAKE_CXX_FLAGS "-I/usr/include/i386-linux-gnu/c++/4.8 -I/usr/include/c++/4.8 -std=c++11 -g3 -Wall -O3") -ELSE () - IF (WIN32) - set (CMAKE_CXX_FLAGS "-I/usr/include/i386-linux-gnu/c++/4.8 -I/usr/include/c++/4.8 -W4 /EHsc") - ELSE() - set (CMAKE_CXX_FLAGS "-I/usr/include/i386-linux-gnu/c++/4.8 -I/usr/include/c++/4.8 -std=c++11 -pthread -g3 -Wall -O2") - ENDIF() -ENDIF () -ADD_SUBDIRECTORY(EtcLib) -ADD_SUBDIRECTORY(EtcTool) +set(CMAKE_CXX_STANDARD 11) +set(CXX_STANDARD_REQUIRED ON) + +if(CMAKE_COMPILER_IS_GNUCC) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread -Wall") + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g3") + + if(APPLE) + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O2") + else() + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3") + endif() + + if(MINGW) + # Including c and c++ runtime libs in the exe to reduce clutter. + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-libgcc -static-libstdc++") + # Strip release executable to make it smaller. + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -s") + endif() + +elseif(MSVC) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -W4 /EHsc") +endif() + +add_subdirectory(EtcLib) +add_subdirectory(EtcTool) diff --git a/EtcLib/CMakeLists.txt b/EtcLib/CMakeLists.txt index b584b88..12073e9 100644 --- a/EtcLib/CMakeLists.txt +++ b/EtcLib/CMakeLists.txt @@ -21,4 +21,4 @@ file(GLOB SOURCES ${PROJECT_SOURCE_DIR}/EtcCodec/*.h ${PROJECT_SOURCE_DIR}/Etc/*.cpp ${PROJECT_SOURCE_DIR}/EtcCodec/*.cpp) -ADD_LIBRARY(EtcLib ${SOURCES}) +add_library(EtcLib ${SOURCES}) diff --git a/EtcTool/CMakeLists.txt b/EtcTool/CMakeLists.txt index ef79cb0..f01c569 100644 --- a/EtcTool/CMakeLists.txt +++ b/EtcTool/CMakeLists.txt @@ -24,5 +24,9 @@ file(GLOB SOURCES ../third_party/lodepng/*.cpp) add_executable(EtcTool ${SOURCES}) -target_link_libraries (EtcTool EtcLib) +set(LIBRARIES EtcTool EtcLib) +if(WIN32) + set(LIBRARIES ${LIBRARIES} psapi) +endif() +target_link_libraries(${LIBRARIES}) diff --git a/EtcTool/EtcTool.cpp b/EtcTool/EtcTool.cpp index 1b52778..d875401 100644 --- a/EtcTool/EtcTool.cpp +++ b/EtcTool/EtcTool.cpp @@ -51,10 +51,13 @@ using namespace Etc; #if ETC_WINDOWS const char *ETC_MKDIR_COMMAND = "mkdir"; +#ifndef __MINGW32__ int strcasecmp(const char *s1, const char *s2) { return _stricmp(s1, s2); } +#endif + #else const char *ETC_MKDIR_COMMAND = "mkdir -p"; #endif diff --git a/EtcTool/EtcTool.h b/EtcTool/EtcTool.h index 67cfccd..8006365 100644 --- a/EtcTool/EtcTool.h +++ b/EtcTool/EtcTool.h @@ -25,7 +25,10 @@ extern const char *ETC_MKDIR_COMMAND; extern const char *ETC_IF_DIR_NOT_EXIST_COMMAND; +#ifndef __MINGW32__ int strcasecmp(const char *s1, const char *s2); +#endif + #else const char ETC_PATH_SLASH = '/'; const char ETC_BAD_PATH_SLASH = '\\'; diff --git a/README.md b/README.md index 1c70ae9..2cfdb92 100644 --- a/README.md +++ b/README.md @@ -42,14 +42,14 @@ To build the Etc2Comp binary: 1. Run `mkdir build_xcode` 1. Run `cd build_xcode` 1. Run `cmake -G Xcode ../` - 1. Open *Xcode* and import the `build_xcode/EtcTest.xcodeproj` file. + 1. Open *Xcode* and import the `build_xcode/Etc2Comp.xcodeproj` file. 1. Open the Product menu and choose Build For -> Running. 1. Once the build succeeds the binary located at `build_xcode/EtcTool/Debug/EtcTool` can be executed. Optional Xcode EtcTool ‘Run’ preferences -note: if the build_xcode/EtcTest.xcodeproj is manually deleted then some Xcode preferences +note: if the build_xcode/Etc2Comp.xcodeproj is manually deleted then some Xcode preferences will need to be set by hand after cmake is run (these prefs are retained across cmake updates if the .xcodeproj is not deleted/removed) @@ -68,7 +68,7 @@ Add this launch argument: ‘-argfile ../../EtcTool/args.txt’ For VS 2013 : `cmake -G "Visual Studio 12 2013 Win64" ../` For VS 2015 : `cmake -G "Visual Studio 14 2015 Win64" ../` NOTE: To see what supported Visual Studio outputs there are, run `cmake -G` -1. open the 'EtcTest' solution +1. open the 'Etc2Comp' solution 1. make the 'EtcTool' project the start up project 1. (optional) in the project properties, under 'Debugging ->command arguments' add the argfile textfile thats included in the EtcTool directory. From d81be5a94d0d1fee00c9541190856999e20b664c Mon Sep 17 00:00:00 2001 From: Olli Kallioinen Date: Sat, 8 Jul 2017 07:58:44 +0300 Subject: [PATCH 2/5] - Fixed crashing when parsing the command line due to illegal memory access - Also now allowing output paths without a '/' or '\' - Fixed a crash when trying to use analyze on windows (when creating directories) --- EtcTool/EtcTool.cpp | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/EtcTool/EtcTool.cpp b/EtcTool/EtcTool.cpp index d875401..2bdd00c 100644 --- a/EtcTool/EtcTool.cpp +++ b/EtcTool/EtcTool.cpp @@ -654,7 +654,7 @@ bool Commands::ProcessCommandLineArguments(int a_iArgs, const char *a_apstrArgs[ if (pstrOutputFilename[c] == ETC_PATH_SLASH) { c++; - ptrOutputDir = new char[c]; + ptrOutputDir = new char[c + 1]; strncpy(ptrOutputDir, pstrOutputFilename, c); ptrOutputDir[c] = '\0'; CreateNewDir(ptrOutputDir); @@ -662,11 +662,6 @@ bool Commands::ProcessCommandLineArguments(int a_iArgs, const char *a_apstrArgs[ } } - if (ptrOutputDir == nullptr) - { - printf("couldnt find a place to put converted images\n"); - exit(1); - } } } else if (strcmp(a_apstrArgs[iArg], "-verbose") == 0 || @@ -819,7 +814,7 @@ void Commands::PrintUsageMessage(void) char strCommand[300]; #if ETC_WINDOWS - sprintf_s(strCommand, "if not exist %s %s %s", path, ETC_MKDIR_COMMAND, path); + sprintf(strCommand, "if not exist %s %s %s", path, ETC_MKDIR_COMMAND, path); #else sprintf(strCommand, "%s %s", ETC_MKDIR_COMMAND, path); #endif From 6a1c8bcfba568410d3b8f011754398587623dcc9 Mon Sep 17 00:00:00 2001 From: Olli Kallioinen Date: Sat, 8 Jul 2017 08:00:59 +0300 Subject: [PATCH 3/5] Documentation fixes - Fixed typos - More info on some features --- EtcTool/EtcTool.cpp | 4 ++-- README.md | 12 +++++++----- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/EtcTool/EtcTool.cpp b/EtcTool/EtcTool.cpp index 2bdd00c..531a93e 100644 --- a/EtcTool/EtcTool.cpp +++ b/EtcTool/EtcTool.cpp @@ -444,7 +444,7 @@ bool Commands::ProcessCommandLineArguments(int a_iArgs, const char *a_apstrArgs[ if (iArg >= (a_iArgs)) { - printf("Error: missing comprison_image parameter for -compare\n"); + printf("Error: missing comparison_image parameter for -compare\n"); return true; } else @@ -800,7 +800,7 @@ void Commands::PrintUsageMessage(void) printf(" -normalizexyz normalize RGB to have a length of 1\n"); printf(" -verbose or -v shows status information during the encoding\n"); printf(" process\n"); - printf(" -mipmaps or -m sets the maximum number of mipaps to generate (default=1)\n"); + printf(" -mipmaps or -m sets the maximum number of mipmaps to generate (default=1)\n"); printf(" -mipwrap or -w sets the mipmap filter wrap mode (default=clamp)\n"); printf("\n"); diff --git a/README.md b/README.md index 2cfdb92..64d87b2 100644 --- a/README.md +++ b/README.md @@ -120,23 +120,25 @@ Options: -normalizexyz normalize RGB to have a length of 1 -verbose or -v shows status information during the encoding process - -mipmaps or -m sets the maximum number of mipaps to generate (default=1) - -mipwrap or -w sets the mipmap filter wrap mode (default=clamp) + -mipmaps or -m sets the maximum number of mipmaps to generate (default=1) + -mipwrap or -w sets the mipmap filter wrap mode (default=clamp) * -analyze will run an analysis of the encoding and place it in folder "analysis_folder" (e.g. ../analysis/kodim05). within the analysis_folder, a folder will be created with a name of the current date/time (e.g. 20151204_153306). this date/time folder is used to compare encodings of the same texture over time. within the date/time folder is a text file with several encoding stats and a 2x png -image showing the encoding mode for each 4x4 block. +image showing the encoding mode for each 4x4 block. Analyze only works if generating +mipmaps is disabled. * -argfile allows additional command line arguments to be placed in a text file * -blockAtHV selects the 4x4 pixel subset of the source image at position (H,V). This is mainly used for debugging -* -compare compares the source image to the created encoded image. The encoding -will dictate what error analysis is used in the comparison. +* -compare compares the image given as the parameter to the newly created encoded image. +The encoding will dictate what error analysis is used in the comparison. Currently only +supports .ktx as the file format. * -effort uses an "amount" between 0 and 100 to determine how much additional effort to apply during the encoding. From efc0c5f88cdfb05de09486e837ebaa3c719b6d19 Mon Sep 17 00:00:00 2001 From: Olli Kallioinen Date: Sat, 8 Jul 2017 15:05:08 +0300 Subject: [PATCH 4/5] Cmake: Prevent in-source builds. Use release configuration by default. --- CMakeLists.txt | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4cc4191..8ff64bf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,6 +13,16 @@ # limitations under the License. cmake_minimum_required(VERSION 3.1) + +if(${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_BINARY_DIR}) + message(FATAL_ERROR "Please create a separate build directory and call cmake from there.") +endif() + +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE Release CACHE STRING "Choose the type of build. Supported options are: Debug, Release" FORCE) + message("CMAKE_BUILD_TYPE was not specified. Defaulting to ${CMAKE_BUILD_TYPE}") +endif() + project(Etc2Comp) set(CMAKE_CXX_STANDARD 11) From 3f07b3e5ff094b3d4b4ef8c8d9ec7c6ae69779ed Mon Sep 17 00:00:00 2001 From: Olli Kallioinen Date: Tue, 11 Jul 2017 17:55:47 +0300 Subject: [PATCH 5/5] Allow generating mipmaps all the way to 1x1 size even when the image is not square. --- EtcLib/Etc/Etc.cpp | 38 +++++++++++++++++++++++++------------- EtcTool/EtcTool.cpp | 2 +- 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/EtcLib/Etc/Etc.cpp b/EtcLib/Etc/Etc.cpp index 0fe4961..89b0448 100644 --- a/EtcLib/Etc/Etc.cpp +++ b/EtcLib/Etc/Etc.cpp @@ -70,12 +70,12 @@ namespace Etc auto mipWidth = a_uiSourceWidth; auto mipHeight = a_uiSourceHeight; int totalEncodingTime = 0; - for(unsigned int mip = 0; mip < a_uiMaxMipmaps && mipWidth >= 1 && mipHeight >= 1; mip++) + for (unsigned int mip = 0; mip < a_uiMaxMipmaps; mip++) { float* pImageData = nullptr; float* pMipImage = nullptr; - if(mip == 0) + if (mip == 0) { pImageData = a_pafSourceRGBA; } @@ -88,23 +88,23 @@ namespace Etc } } - if ( pImageData ) + if (pImageData) { Image image(pImageData, mipWidth, mipHeight, a_eErrMetric); - image.m_bVerboseOutput = a_bVerboseOutput; - image.Encode(a_format, a_eErrMetric, a_fEffort, a_uiJobs, a_uiMaxJobs); + image.m_bVerboseOutput = a_bVerboseOutput; + image.Encode(a_format, a_eErrMetric, a_fEffort, a_uiJobs, a_uiMaxJobs); - a_pMipmapImages[mip].paucEncodingBits = std::shared_ptr(image.GetEncodingBits(), [](unsigned char *p) { delete[] p; }); - a_pMipmapImages[mip].uiEncodingBitsBytes = image.GetEncodingBitsBytes(); - a_pMipmapImages[mip].uiExtendedWidth = image.GetExtendedWidth(); - a_pMipmapImages[mip].uiExtendedHeight = image.GetExtendedHeight(); + a_pMipmapImages[mip].paucEncodingBits = std::shared_ptr(image.GetEncodingBits(), [](unsigned char *p) { delete[] p; }); + a_pMipmapImages[mip].uiEncodingBitsBytes = image.GetEncodingBitsBytes(); + a_pMipmapImages[mip].uiExtendedWidth = image.GetExtendedWidth(); + a_pMipmapImages[mip].uiExtendedHeight = image.GetExtendedHeight(); - totalEncodingTime += image.GetEncodingTimeMs(); + totalEncodingTime += image.GetEncodingTimeMs(); } - if(pMipImage) + if (pMipImage) { delete[] pMipImage; } @@ -114,8 +114,20 @@ namespace Etc break; } - mipWidth >>= 1; - mipHeight >>= 1; + if (mipWidth == 1 && mipHeight == 1) + { + break; + } + + if (mipWidth > 1) + { + mipWidth >>= 1; + } + + if (mipHeight > 1) + { + mipHeight >>= 1; + } } *a_piEncodingTime_ms = totalEncodingTime; diff --git a/EtcTool/EtcTool.cpp b/EtcTool/EtcTool.cpp index 531a93e..55c2215 100644 --- a/EtcTool/EtcTool.cpp +++ b/EtcTool/EtcTool.cpp @@ -165,7 +165,7 @@ int main(int argc, const char * argv[]) // Calculate the maximum number of possible mipmaps { - int dim = (uiSourceWidth < uiSourceHeight)?uiSourceWidth:uiSourceHeight; + int dim = (uiSourceWidth > uiSourceHeight)?uiSourceWidth:uiSourceHeight; int maxMips = 0; while(dim >= 1) {