mirror of
https://github.com/yuzu-emu/FasTC.git
synced 2024-11-28 00:14:16 +01:00
Merge MSVC support into master.
This commit is contained in:
commit
cdbf72b6c0
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
[submodule "Windows"]
|
||||
path = Windows
|
||||
url = git@github.com:Mokosha/FasTC-MSVCLibs.git
|
@ -1526,12 +1526,11 @@ namespace BC7C
|
||||
// implementation has an 4:1 compression ratio.
|
||||
void CompressImageBC7(const unsigned char *inBuf, unsigned char *outBuf, unsigned int width, unsigned int height)
|
||||
{
|
||||
uint32 block[16];
|
||||
BC7CompressionMode::MaxAnnealingIterations = min(BC7CompressionMode::kMaxAnnealingIterations, GetQualityLevel());
|
||||
|
||||
for(int j = 0; j < height; j += 4)
|
||||
for(uint32 j = 0; j < height; j += 4)
|
||||
{
|
||||
for(int i = 0; i < width; i += 4)
|
||||
for(uint32 i = 0; i < width; i += 4)
|
||||
{
|
||||
// ExtractBlock(inBuf + i * 4, width, block);
|
||||
CompressBC7Block((const uint32 *)inBuf, outBuf);
|
||||
@ -1569,12 +1568,11 @@ namespace BC7C
|
||||
unsigned int height,
|
||||
BlockStatManager &statManager
|
||||
) {
|
||||
uint32 block[16];
|
||||
BC7CompressionMode::MaxAnnealingIterations = min(BC7CompressionMode::kMaxAnnealingIterations, GetQualityLevel());
|
||||
|
||||
for(int j = 0; j < height; j += 4)
|
||||
for(uint32 j = 0; j < height; j += 4)
|
||||
{
|
||||
for(int i = 0; i < width; i += 4)
|
||||
for(uint32 i = 0; i < width; i += 4)
|
||||
{
|
||||
// ExtractBlock(inBuf + i * 4, width, block);
|
||||
CompressBC7Block((const uint32 *)inBuf, outBuf, statManager);
|
||||
@ -2387,7 +2385,7 @@ namespace BC7C
|
||||
|
||||
assert(idxMode < 2);
|
||||
assert(rotMode < 4);
|
||||
assert(shapeIdx < ((mode == 0)? 16 : 64));
|
||||
assert(shapeIdx < uint32((mode == 0)? 16 : 64));
|
||||
|
||||
uint32 cp = attrs->colorChannelPrecision;
|
||||
const uint32 shift = 8 - cp;
|
||||
|
@ -505,7 +505,7 @@ static uint32 PowerIteration(const RGBAMatrix &mat, RGBADir &eigVec, double &eig
|
||||
for(int nTries = 0; nTries < 3; nTries++) {
|
||||
// !SPEED! Find eigenvectors by using the power method. This is good because the
|
||||
// matrix is only 4x4, which allows us to use SIMD...
|
||||
RGBAVector b = RGBAVector(rand());
|
||||
RGBAVector b = RGBAVector(float(rand()));
|
||||
assert(b.Length() > 0);
|
||||
b /= b.Length();
|
||||
|
||||
@ -528,7 +528,7 @@ static uint32 PowerIteration(const RGBAMatrix &mat, RGBADir &eigVec, double &eig
|
||||
}
|
||||
|
||||
eigVal = newB.Length();
|
||||
newB /= eigVal;
|
||||
newB /= float(eigVal);
|
||||
|
||||
if(fabs(1.0f - (b * newB)) < 1e-5)
|
||||
fixed = true;
|
||||
|
@ -54,6 +54,12 @@ ADD_EXECUTABLE(
|
||||
${SOURCES}
|
||||
)
|
||||
|
||||
# Make sure that if we're using boost libraries for threading then we add this linker path.
|
||||
# Personally, I believe this is a bug in CMAKE but I'm not exactly sure.
|
||||
#IF( THREAD_API MATCHES "Boost" )
|
||||
# SET_TARGET_PROPERTIES(tc PROPERTIES LINK_FLAGS "/LIBPATH:\"${Boost_LIBRARY_DIRS}\"")
|
||||
#ENDIF()
|
||||
|
||||
TARGET_LINK_LIBRARIES( tc BPTCEncoder )
|
||||
TARGET_LINK_LIBRARIES( tc TexCompIO )
|
||||
TARGET_LINK_LIBRARIES( tc TexCompCore )
|
||||
|
@ -40,6 +40,187 @@
|
||||
*
|
||||
* <http://gamma.cs.unc.edu/FasTC/>
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <SDKDDKVer.h>
|
||||
#include <Windows.h>
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
#include "BlockStats.h"
|
||||
#include "TexComp.h"
|
||||
#include "ImageFile.h"
|
||||
#include "Image.h"
|
||||
|
||||
void PrintUsage() {
|
||||
fprintf(stderr, "Usage: tc [-l] [-q <quality>] [-n <num>] [-simd] [-t <threads> [-j <jobs>]] <imagefile>\n");
|
||||
}
|
||||
|
||||
void ExtractBasename(const char *filename, char *buf, uint32 bufSz) {
|
||||
size_t len = strlen(filename);
|
||||
const char *end = filename + len;
|
||||
while(--end != filename) {
|
||||
if(*end == '.')
|
||||
{
|
||||
uint32 numChars = int32(end - filename + 1);
|
||||
uint32 toCopy = (numChars > bufSz)? bufSz : numChars;
|
||||
memcpy(buf, filename, toCopy);
|
||||
buf[toCopy - 1] = '\0';
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int _tmain(int argc, _TCHAR* argv[])
|
||||
{
|
||||
int fileArg = 1;
|
||||
if(fileArg == argc) {
|
||||
PrintUsage();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int numJobs = 0;
|
||||
int quality = 50;
|
||||
int numThreads = 1;
|
||||
int numCompressions = 1;
|
||||
bool bUseSIMD = false;
|
||||
bool bSaveLog = false;
|
||||
|
||||
bool knowArg = false;
|
||||
do {
|
||||
knowArg = false;
|
||||
|
||||
if(strcmp(argv[fileArg], "-n") == 0) {
|
||||
fileArg++;
|
||||
|
||||
if(fileArg == argc || (numCompressions = atoi(argv[fileArg])) < 0) {
|
||||
PrintUsage();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fileArg++;
|
||||
knowArg = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if(strcmp(argv[fileArg], "-l") == 0) {
|
||||
fileArg++;
|
||||
bSaveLog = true;
|
||||
knowArg = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if(strcmp(argv[fileArg], "-simd") == 0) {
|
||||
fileArg++;
|
||||
bUseSIMD = true;
|
||||
knowArg = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if(strcmp(argv[fileArg], "-t") == 0) {
|
||||
fileArg++;
|
||||
|
||||
if(fileArg == argc || (numThreads = atoi(argv[fileArg])) < 1) {
|
||||
PrintUsage();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fileArg++;
|
||||
knowArg = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if(strcmp(argv[fileArg], "-q") == 0) {
|
||||
fileArg++;
|
||||
|
||||
if(fileArg == argc || (quality = atoi(argv[fileArg])) < 0) {
|
||||
PrintUsage();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fileArg++;
|
||||
knowArg = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if(strcmp(argv[fileArg], "-j") == 0) {
|
||||
fileArg++;
|
||||
|
||||
if(fileArg == argc || (numJobs = atoi(argv[fileArg])) < 0) {
|
||||
PrintUsage();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fileArg++;
|
||||
knowArg = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
} while(knowArg && fileArg < argc);
|
||||
|
||||
if(numThreads > 1 && bSaveLog) {
|
||||
bSaveLog = false;
|
||||
fprintf(stderr, "WARNING: Will not save log because implementation is not thread safe.\n"
|
||||
"If you'd like, send a complaint to pavel@cs.unc.edu to get this done faster.\n");
|
||||
}
|
||||
|
||||
if(fileArg == argc) {
|
||||
PrintUsage();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
char basename[256];
|
||||
ExtractBasename(argv[fileArg], basename, 256);
|
||||
|
||||
ImageFile file (argv[fileArg]);
|
||||
if(!file.Load()) {
|
||||
fprintf(stderr, "Error loading file: %s\n", argv[fileArg]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
const Image *img = file.GetImage();
|
||||
|
||||
int numBlocks = (img->GetWidth() * img->GetHeight())/16;
|
||||
BlockStatManager *statManager = NULL;
|
||||
if(bSaveLog) {
|
||||
statManager = new BlockStatManager(numBlocks);
|
||||
}
|
||||
|
||||
SCompressionSettings settings;
|
||||
settings.bUseSIMD = bUseSIMD;
|
||||
settings.iNumThreads = numThreads;
|
||||
settings.iQuality = quality;
|
||||
settings.iNumCompressions = numCompressions;
|
||||
settings.iJobSize = numJobs;
|
||||
settings.pStatManager = statManager;
|
||||
|
||||
CompressedImage *ci = img->Compress(settings);
|
||||
if(NULL == ci) {
|
||||
fprintf(stderr, "Error compressing image!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
double PSNR = img->ComputePSNR(*ci);
|
||||
if(PSNR > 0.0) {
|
||||
fprintf(stdout, "PSNR: %.3f\n", PSNR);
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "Error computing PSNR\n");
|
||||
}
|
||||
|
||||
if(bSaveLog) {
|
||||
strcat_s(basename, ".log");
|
||||
statManager->ToFile(basename);
|
||||
basename[strlen(basename) - 4] = '\0';
|
||||
}
|
||||
strcat_s(basename, "-bc7.png");
|
||||
Image cImg (*ci);
|
||||
ImageFile cImgFile (basename, eFileFormat_PNG, cImg);
|
||||
cImgFile.Write();
|
||||
|
||||
// Cleanup
|
||||
delete ci;
|
||||
if(statManager)
|
||||
delete statManager;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -43,6 +43,31 @@
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.8 FATAL_ERROR)
|
||||
PROJECT(TexC)
|
||||
|
||||
IF(MSVC)
|
||||
SET(MSVC_INSTALL_PATH "${PROJECT_SOURCE_DIR}/Windows")
|
||||
SET(CMAKE_PREFIX_PATH "${CMAKE_PREFIX_PATH};${MSVC_INSTALL_PATH}")
|
||||
|
||||
IF(MSVC10)
|
||||
SET(MSVC_VERSION_STRING vc100)
|
||||
ELSEIF(MSVC11)
|
||||
SET(MSVC_VERSION_STRING vc110)
|
||||
ELSEIF(MSVC90)
|
||||
SET(MSVC_VERSION_STRING vc90)
|
||||
ELSEIF(MSVC80)
|
||||
SET(MSVC_VERSION_STRING vc80)
|
||||
ENDIF()
|
||||
|
||||
# !FIXME! Actually detect compiler architecture version....
|
||||
IF( CMAKE_SIZEOF_VOID_P EQUAL 8 )
|
||||
SET(MSVC_ARCHITECTURE_STRING x64)
|
||||
ELSE()
|
||||
SET(MSVC_ARCHITECTURE_STRING x86)
|
||||
ENDIF()
|
||||
|
||||
SET(MSVC_LIB_DIR "${MSVC_INSTALL_PATH}/lib/${MSVC_ARCHITECTURE_STRING}/${MSVC_VERSION_STRING}")
|
||||
SET(CMAKE_LIBRARY_PATH "${CMAKE_LIBRARY_PATH};${MSVC_LIB_DIR}")
|
||||
ENDIF(MSVC)
|
||||
|
||||
ADD_SUBDIRECTORY(BPTCEncoder)
|
||||
ADD_SUBDIRECTORY(IO)
|
||||
ADD_SUBDIRECTORY(Core)
|
||||
|
@ -80,7 +80,15 @@ INCLUDE_DIRECTORIES( ${TexC_SOURCE_DIR}/Core/include )
|
||||
SET( THREAD_API )
|
||||
SET( THREAD_APIS_AVAILABLE "None" )
|
||||
|
||||
FIND_PACKAGE( Boost COMPONENTS thread system )
|
||||
###### Find Boost...
|
||||
|
||||
IF( MSVC )
|
||||
SET(ENV{BOOSTLIBDIR} "${MSVC_LIB_DIR}")
|
||||
SET(ENV{BOOSTINCLUDEDIR} "${MSVC_INSTALL_PATH}/include")
|
||||
ENDIF( MSVC )
|
||||
|
||||
SET( Boost_USE_STATIC_LIBS ON )
|
||||
FIND_PACKAGE( Boost COMPONENTS thread system date_time chrono )
|
||||
IF( Boost_FOUND )
|
||||
|
||||
SET( THREAD_APIS_AVAILABLE "Boost" ${THREAD_APIS_AVAILABLE} )
|
||||
@ -90,6 +98,8 @@ IF( Boost_FOUND )
|
||||
|
||||
ENDIF()
|
||||
|
||||
###### Find PThreads....
|
||||
|
||||
FIND_PACKAGE( Threads )
|
||||
IF( CMAKE_USE_PTHREADS_INIT )
|
||||
|
||||
@ -111,7 +121,7 @@ SET_PROPERTY( CACHE THREAD_API PROPERTY STRINGS ${THREAD_APIS_AVAILABLE} )
|
||||
IF( THREAD_API MATCHES "Boost")
|
||||
INCLUDE_DIRECTORIES( ${Boost_INCLUDE_DIR} )
|
||||
SET( SOURCES ${SOURCES} "src/ThreadBoost.cpp" )
|
||||
LINK_DIRECTORIES( ${Boost_LIBRARY_DIR} )
|
||||
LINK_DIRECTORIES( ${Boost_LIBRARY_DIRS} )
|
||||
ENDIF()
|
||||
|
||||
IF( THREAD_API MATCHES "PThread" )
|
||||
@ -125,7 +135,7 @@ ELSE()
|
||||
SET( SOURCES ${SOURCES} "src/ThreadGroup.cpp" )
|
||||
SET( SOURCES ${SOURCES} "src/WorkerQueue.cpp" )
|
||||
|
||||
SET( HEADERS ${HEADERS} "include/Thread.h" )
|
||||
SET( HEADERS ${HEADERS} "src/Thread.h" )
|
||||
SET( HEADERS ${HEADERS} "src/ThreadGroup.h" )
|
||||
SET( HEADERS ${HEADERS} "src/WorkerQueue.h" )
|
||||
ENDIF()
|
||||
|
@ -46,7 +46,19 @@
|
||||
|
||||
#include "TexCompTypes.h"
|
||||
#include "ReferenceCounter.h"
|
||||
#include "Thread.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Forward declarations
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
class TCMutex;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// class BlockStat
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct BlockStat {
|
||||
friend class BlockStatManager;
|
||||
@ -57,7 +69,7 @@ public:
|
||||
BlockStat(const BlockStat &);
|
||||
BlockStat &operator=(const BlockStat &);
|
||||
|
||||
void ToString(char *buf, int bufSz) const;
|
||||
void ToString(CHAR *buf, int bufSz) const;
|
||||
|
||||
private:
|
||||
const enum Type {
|
||||
@ -79,6 +91,8 @@ class BlockStatManager {
|
||||
|
||||
public:
|
||||
BlockStatManager(int nBlocks);
|
||||
BlockStatManager(const BlockStatManager &);
|
||||
BlockStatManager &operator=(const BlockStatManager &);
|
||||
~BlockStatManager();
|
||||
|
||||
uint32 BeginBlock();
|
||||
@ -90,6 +104,7 @@ class BlockStatManager {
|
||||
class BlockStatList {
|
||||
public:
|
||||
BlockStatList();
|
||||
BlockStatList(const BlockStatList &other);
|
||||
~BlockStatList();
|
||||
|
||||
void AddStat(const BlockStat &stat);
|
||||
@ -106,9 +121,12 @@ class BlockStatManager {
|
||||
} *m_BlockStatList;
|
||||
uint32 m_BlockStatListSz;
|
||||
|
||||
TCMutex m_Mutex;
|
||||
TCMutex *m_Mutex;
|
||||
uint32 m_NextBlock;
|
||||
ReferenceCounter m_Counter;
|
||||
|
||||
// Note: we probably shouldn't call this...
|
||||
void Copy(const BlockStatManager &);
|
||||
};
|
||||
|
||||
#endif // __BLOCK_STATS_H__
|
||||
|
@ -52,16 +52,17 @@
|
||||
#ifdef _MSC_VER
|
||||
|
||||
typedef __int16 int16;
|
||||
typedef __uint16 uint16;
|
||||
typedef unsigned __int16 uint16;
|
||||
typedef __int32 int32;
|
||||
typedef __uint32 uint32;
|
||||
typedef unsigned __int32 uint32;
|
||||
typedef __int8 int8;
|
||||
typedef __uint8 uint8;
|
||||
typedef unsigned __int8 uint8;
|
||||
|
||||
typedef __uint64 uint64;
|
||||
typedef unsigned __int64 uint64;
|
||||
typedef __int64 int64;
|
||||
|
||||
typedef __int32_ptr int32_ptr;
|
||||
#include <tchar.h>
|
||||
typedef TCHAR CHAR;
|
||||
|
||||
// If not, assume GCC, or at least standard defines...
|
||||
#else
|
||||
@ -78,7 +79,6 @@ typedef uint16_t uint16;
|
||||
typedef uint32_t uint32;
|
||||
typedef uint64_t uint64;
|
||||
|
||||
typedef uintptr_t int32_ptr;
|
||||
typedef char CHAR;
|
||||
|
||||
#endif // _MSC_VER
|
||||
|
@ -49,6 +49,7 @@
|
||||
#include <assert.h>
|
||||
|
||||
#include "FileStream.h"
|
||||
#include "Thread.h"
|
||||
|
||||
template <typename T>
|
||||
static T max(const T &a, const T &b) {
|
||||
@ -65,14 +66,22 @@ BlockStat::BlockStat(const CHAR *statName, int stat)
|
||||
: m_IntStat(stat)
|
||||
, m_Type(eType_Int)
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
strncpy_s(m_StatName, statName, kStatNameSz);
|
||||
#else
|
||||
strncpy(m_StatName, statName, kStatNameSz);
|
||||
#endif
|
||||
}
|
||||
|
||||
BlockStat::BlockStat(const CHAR *statName, double stat)
|
||||
: m_FloatStat(stat)
|
||||
, m_Type(eType_Float)
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
strncpy_s(m_StatName, statName, kStatNameSz);
|
||||
#else
|
||||
strncpy(m_StatName, statName, kStatNameSz);
|
||||
#endif
|
||||
}
|
||||
|
||||
BlockStat::BlockStat(const BlockStat &other) : m_Type(other.m_Type) {
|
||||
@ -81,16 +90,25 @@ BlockStat::BlockStat(const BlockStat &other) : m_Type(other.m_Type) {
|
||||
|
||||
BlockStat &BlockStat::operator=(const BlockStat &other) {
|
||||
memcpy(this, &other, sizeof(*this));
|
||||
return *this;
|
||||
}
|
||||
|
||||
void BlockStat::ToString(char *buf, int bufSz) const {
|
||||
void BlockStat::ToString(CHAR *buf, int bufSz) const {
|
||||
switch(m_Type) {
|
||||
case BlockStat::eType_Float:
|
||||
#ifdef _MSC_VER
|
||||
_sntprintf_s(buf, bufSz, _TRUNCATE, "%s,%f", m_StatName, m_FloatStat);
|
||||
#else
|
||||
snprintf(buf, bufSz, "%s,%f", m_StatName, m_FloatStat);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case BlockStat::eType_Int:
|
||||
#ifdef _MSC_VER
|
||||
_sntprintf_s(buf, bufSz, _TRUNCATE, "%s,%llu", m_StatName, m_IntStat);
|
||||
#else
|
||||
snprintf(buf, bufSz, "%s,%llu", m_StatName, m_IntStat);
|
||||
#endif
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -105,9 +123,36 @@ void BlockStat::ToString(char *buf, int bufSz) const {
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void BlockStatManager::Copy(const BlockStatManager &other) {
|
||||
// This is a bug. If we copy the manager then all of the lists and pointers
|
||||
// become shared and can cause dereferencing issues. Check to see where you're
|
||||
// copying this class and make sure to actually create a new instance.
|
||||
assert(!"We shouldn't be copying these in this manner!");
|
||||
|
||||
m_BlockStatList = new BlockStatList(*other.m_BlockStatList);
|
||||
m_BlockStatListSz = other.m_BlockStatListSz;
|
||||
m_NextBlock = other.m_NextBlock;
|
||||
|
||||
// If we do copy them, then make sure that we are actually using the exact same
|
||||
// pointers for our synchronization primitives... otherwise we could run into
|
||||
// deadlock issues.
|
||||
m_Mutex = other.m_Mutex;
|
||||
}
|
||||
|
||||
BlockStatManager::BlockStatManager(const BlockStatManager &other) {
|
||||
Copy(other);
|
||||
}
|
||||
|
||||
BlockStatManager &BlockStatManager::operator=(const BlockStatManager &other) {
|
||||
m_Counter = other.m_Counter;
|
||||
Copy(other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
BlockStatManager::BlockStatManager(int nBlocks)
|
||||
: m_BlockStatListSz(max(nBlocks, 0))
|
||||
, m_NextBlock(0)
|
||||
, m_Mutex(new TCMutex)
|
||||
{
|
||||
m_BlockStatList = new BlockStatList[m_BlockStatListSz];
|
||||
if(!m_BlockStatList) {
|
||||
@ -121,6 +166,12 @@ BlockStatManager::~BlockStatManager() {
|
||||
if(m_Counter.GetRefCount() == 0) {
|
||||
delete [] m_BlockStatList;
|
||||
}
|
||||
|
||||
if(m_Mutex)
|
||||
{
|
||||
delete m_Mutex;
|
||||
m_Mutex = 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint32 BlockStatManager::BeginBlock() {
|
||||
@ -130,7 +181,7 @@ uint32 BlockStatManager::BeginBlock() {
|
||||
return m_NextBlock-1;
|
||||
}
|
||||
|
||||
TCLock lock (m_Mutex);
|
||||
TCLock lock (*m_Mutex);
|
||||
return m_NextBlock++;
|
||||
}
|
||||
|
||||
@ -141,7 +192,7 @@ void BlockStatManager::AddStat(uint32 blockIdx, const BlockStat &stat) {
|
||||
return;
|
||||
}
|
||||
|
||||
TCLock lock (m_Mutex);
|
||||
TCLock lock (*m_Mutex);
|
||||
m_BlockStatList[blockIdx].AddStat(stat);
|
||||
}
|
||||
|
||||
@ -149,7 +200,7 @@ void BlockStatManager::ToFile(const CHAR *filename) {
|
||||
|
||||
FileStream fstr (filename, eFileMode_Write);
|
||||
|
||||
for(int i = 0; i < m_BlockStatListSz; i++) {
|
||||
for(uint32 i = 0; i < m_BlockStatListSz; i++) {
|
||||
const BlockStatList *head = &(m_BlockStatList[i]);
|
||||
while(head) {
|
||||
BlockStat s = head->GetStat();
|
||||
@ -158,9 +209,13 @@ void BlockStatManager::ToFile(const CHAR *filename) {
|
||||
s.ToString(statStr, 256);
|
||||
|
||||
CHAR str[256];
|
||||
#ifdef _MSC_VER
|
||||
_sntprintf_s(str, 256, _TRUNCATE, "%d,%s\n", i, statStr);
|
||||
#else
|
||||
snprintf(str, 256, "%d,%s\n", i, statStr);
|
||||
#endif
|
||||
|
||||
int strLen = strlen(str);
|
||||
uint32 strLen = uint32(strlen(str));
|
||||
if(strLen > 255) {
|
||||
str[255] = '\n';
|
||||
strLen = 256;
|
||||
@ -179,7 +234,7 @@ void BlockStatManager::ToFile(const CHAR *filename) {
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
static const CHAR *kNullBlockString = "NULL_BLOCK_STAT";
|
||||
static const uint32 kNullBlockStringLength = strlen(kNullBlockString);
|
||||
static const uint32 kNullBlockStringLength = uint32(strlen(kNullBlockString));
|
||||
|
||||
BlockStatManager::BlockStatList::BlockStatList()
|
||||
: m_Tail(0)
|
||||
@ -190,8 +245,14 @@ BlockStatManager::BlockStatList::BlockStatList(const BlockStat &stat)
|
||||
: m_Tail(0)
|
||||
, m_Stat(stat)
|
||||
{
|
||||
assert(!"If you're copying a block stat list then you're probably not using them properly.");
|
||||
}
|
||||
|
||||
BlockStatManager::BlockStatList::BlockStatList(const BlockStatList &other)
|
||||
: m_Tail(new BlockStatList(*other.m_Tail))
|
||||
, m_Stat(other.m_Stat)
|
||||
{}
|
||||
|
||||
BlockStatManager::BlockStatList::~BlockStatList() {
|
||||
if(m_Counter.GetRefCount() == 0 && m_Tail) {
|
||||
delete m_Tail;
|
||||
|
@ -48,6 +48,7 @@
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "TexCompTypes.h"
|
||||
#include "BC7Compressor.h"
|
||||
|
||||
CompressedImage::CompressedImage()
|
||||
@ -109,7 +110,7 @@ CompressedImage::~CompressedImage() {
|
||||
bool CompressedImage::DecompressImage(unsigned char *outBuf, unsigned int outBufSz) const {
|
||||
|
||||
// First make sure that we have enough data
|
||||
int dataSz = 0;
|
||||
uint32 dataSz = 0;
|
||||
switch(m_Format) {
|
||||
case eCompressionFormat_DXT1: dataSz = m_DataSz * 8; break;
|
||||
case eCompressionFormat_DXT5: dataSz = m_DataSz * 4; break;
|
||||
|
@ -118,7 +118,7 @@ double Image::ComputePSNR(const CompressedImage &ci) const {
|
||||
const double wb = 1.0;
|
||||
|
||||
double MSE = 0.0;
|
||||
for(int i = 0; i < imageSz; i+=4) {
|
||||
for(uint32 i = 0; i < imageSz; i+=4) {
|
||||
|
||||
const unsigned char *pixelDataRaw = m_PixelData + i;
|
||||
const unsigned char *pixelDataUncomp = unCompData + i;
|
||||
|
@ -67,12 +67,14 @@
|
||||
#include "TexCompTypes.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <Windows.h>
|
||||
|
||||
class StopWatchImpl {
|
||||
public:
|
||||
uint64 frequency;
|
||||
uint64 start;
|
||||
uint64 stop;
|
||||
uintptr affinityMask;
|
||||
uintptr_t affinityMask;
|
||||
|
||||
StopWatchImpl() :
|
||||
start(0), stop(0), affinityMask(0)
|
||||
@ -85,6 +87,8 @@ class StopWatchImpl {
|
||||
}
|
||||
};
|
||||
|
||||
StopWatch::StopWatch() : impl(new StopWatchImpl) { }
|
||||
|
||||
StopWatch::StopWatch(const StopWatch &other) {
|
||||
impl = new StopWatchImpl();
|
||||
memcpy(impl, other.impl, sizeof(StopWatchImpl));
|
||||
@ -96,6 +100,7 @@ StopWatch &StopWatch::operator=(const StopWatch &other) {
|
||||
}
|
||||
impl = new StopWatchImpl();
|
||||
memcpy(impl, other.impl, sizeof(StopWatchImpl));
|
||||
return *this;
|
||||
}
|
||||
|
||||
StopWatch::~StopWatch() {
|
||||
@ -156,7 +161,7 @@ double StopWatch::TimeInSeconds() const
|
||||
{
|
||||
// Return the elapsed time in seconds.
|
||||
assert((impl->stop - impl->start) > 0);
|
||||
return double(impl->stop - impl->start) / double(frequency);
|
||||
return double(impl->stop - impl->start) / double(impl->frequency);
|
||||
}
|
||||
|
||||
// Get the elapsed time in milliseconds.
|
||||
@ -164,7 +169,7 @@ double StopWatch::TimeInMilliseconds() const
|
||||
{
|
||||
// Return the elapsed time in milliseconds.
|
||||
assert((impl->stop - impl->start) > 0);
|
||||
return double(impl->stop - impl->start) / double(frequency) * 1000.0;
|
||||
return double(impl->stop - impl->start) / double(impl->frequency) * 1000.0;
|
||||
}
|
||||
|
||||
// Get the elapsed time in microseconds.
|
||||
|
@ -268,7 +268,7 @@ bool CompressImageData(
|
||||
}
|
||||
|
||||
// Allocate data based on the compression method
|
||||
int cmpDataSzNeeded = 0;
|
||||
uint32 cmpDataSzNeeded = 0;
|
||||
switch(settings.format) {
|
||||
case eCompressionFormat_DXT1: cmpDataSzNeeded = dataSz / 8;
|
||||
case eCompressionFormat_DXT5: cmpDataSzNeeded = dataSz / 4;
|
||||
|
@ -77,6 +77,8 @@ TCThreadBase &TCThreadBase::operator=(const TCThreadBase &other) {
|
||||
// Our implementation is now the same as the other.
|
||||
m_Impl = other.m_Impl;
|
||||
m_Impl->IncreaseReferenceCount();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
TCThreadBase::~TCThreadBase() {
|
||||
|
@ -46,6 +46,11 @@
|
||||
|
||||
#include "TexCompTypes.h"
|
||||
|
||||
//!HACK! Apparently MSVC has issues with Yield()...????
|
||||
#ifdef _MSC_VER
|
||||
#undef Yield
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Base implementation
|
||||
@ -112,8 +117,8 @@ class TCThread : public TCThreadBase {
|
||||
public:
|
||||
TCThread(TCCallable &);
|
||||
|
||||
void Join();
|
||||
static void Yield();
|
||||
void Join();
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
@ -286,6 +286,8 @@ bool ThreadGroup::CleanUpThreads() {
|
||||
// Reset active number of threads...
|
||||
m_ActiveThreads = 0;
|
||||
m_ExitFlag = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ThreadGroup::Join() {
|
||||
|
@ -191,7 +191,7 @@ void WorkerQueue::Run() {
|
||||
|
||||
// Spawn a bunch of threads...
|
||||
TCLock lock(m_Mutex);
|
||||
for(int i = 0; i < m_NumThreads; i++) {
|
||||
for(uint32 i = 0; i < m_NumThreads; i++) {
|
||||
m_Workers[i] = new WorkerThread(this, i);
|
||||
m_ThreadHandles[m_ActiveThreads] = new TCThread(*m_Workers[i]);
|
||||
m_ActiveThreads++;
|
||||
@ -211,7 +211,7 @@ void WorkerQueue::Run() {
|
||||
m_StopWatch.Stop();
|
||||
|
||||
// Join them all together..
|
||||
for(int i = 0; i < m_NumThreads; i++) {
|
||||
for(uint32 i = 0; i < m_NumThreads; i++) {
|
||||
m_ThreadHandles[i]->Join();
|
||||
delete m_ThreadHandles[i];
|
||||
delete m_Workers[i];
|
||||
@ -274,7 +274,7 @@ WorkerThread::EAction WorkerQueue::AcceptThreadData(uint32 threadIdx) {
|
||||
const uint8 *WorkerQueue::GetSrcForThread(const int threadIdx) const {
|
||||
assert(m_Offsets[threadIdx] >= 0);
|
||||
assert(threadIdx >= 0);
|
||||
assert(threadIdx < m_NumThreads);
|
||||
assert(threadIdx < int(m_NumThreads));
|
||||
|
||||
const uint32 inBufBlockSz = 16 * 4;
|
||||
return m_InBuf + m_Offsets[threadIdx] * inBufBlockSz;
|
||||
@ -283,7 +283,7 @@ const uint8 *WorkerQueue::GetSrcForThread(const int threadIdx) const {
|
||||
uint8 *WorkerQueue::GetDstForThread(const int threadIdx) const {
|
||||
assert(m_Offsets[threadIdx] >= 0);
|
||||
assert(threadIdx >= 0);
|
||||
assert(threadIdx < m_NumThreads);
|
||||
assert(threadIdx < int(m_NumThreads));
|
||||
|
||||
const uint32 outBufBlockSz = 16;
|
||||
return m_OutBuf + m_Offsets[threadIdx] * outBufBlockSz;
|
||||
@ -292,7 +292,7 @@ uint8 *WorkerQueue::GetDstForThread(const int threadIdx) const {
|
||||
uint32 WorkerQueue::GetNumBlocksForThread(const int threadIdx) const {
|
||||
assert(m_Offsets[threadIdx] >= 0);
|
||||
assert(threadIdx >= 0);
|
||||
assert(threadIdx < m_NumThreads);
|
||||
assert(threadIdx < int(m_NumThreads));
|
||||
|
||||
return m_NumBlocks[threadIdx];
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ class WorkerQueue;
|
||||
#include "Thread.h"
|
||||
#include "StopWatch.h"
|
||||
|
||||
struct WorkerThread : public TCCallable {
|
||||
class WorkerThread : public TCCallable {
|
||||
friend class WorkerQueue;
|
||||
public:
|
||||
|
||||
|
@ -43,7 +43,6 @@
|
||||
SET( SOURCES
|
||||
"src/ImageWriter.cpp"
|
||||
"src/ImageLoader.cpp"
|
||||
"src/FileStream.cpp"
|
||||
"src/ImageFile.cpp"
|
||||
)
|
||||
|
||||
@ -54,6 +53,15 @@ SET( HEADERS
|
||||
"include/FileStream.h"
|
||||
)
|
||||
|
||||
IF( WIN32 )
|
||||
SET( SOURCES ${SOURCES} "src/FileStreamWin32.cpp" )
|
||||
ELSE()
|
||||
SET( SOURCES ${SOURCES} "src/FileStreamUnix.cpp" )
|
||||
|
||||
# Assume compiler is GCC
|
||||
SET( LINK_FLAGS -lrt ${LINK_FLAGS} )
|
||||
ENDIF()
|
||||
|
||||
FIND_PACKAGE( PNG )
|
||||
IF( PNG_FOUND )
|
||||
INCLUDE_DIRECTORIES( ${PNG_INCLUDE_DIR} )
|
||||
|
@ -139,6 +139,8 @@ FileStream &FileStream::operator=(const FileStream &other) {
|
||||
|
||||
m_Mode = other.m_Mode;
|
||||
strncpy(m_Filename, other.m_Filename, kMaxFilenameSz);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
FileStream::~FileStream() {
|
253
IO/src/FileStreamWin32.cpp
Executable file
253
IO/src/FileStreamWin32.cpp
Executable file
@ -0,0 +1,253 @@
|
||||
#include "FileStream.h"
|
||||
|
||||
#include <Windows.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
class FileStreamImpl {
|
||||
|
||||
private:
|
||||
// Track the number of references to this filestream so
|
||||
// that we know whether or not we need to close it when
|
||||
// the object gets destroyed.
|
||||
uint32 m_ReferenceCount;
|
||||
|
||||
HANDLE m_Handle;
|
||||
|
||||
public:
|
||||
FileStreamImpl(const CHAR *filename, EFileMode mode)
|
||||
: m_ReferenceCount(1)
|
||||
{
|
||||
|
||||
DWORD dwDesiredAccess = GENERIC_READ;
|
||||
DWORD dwShareMode = 0;
|
||||
switch(mode) {
|
||||
default:
|
||||
case eFileMode_ReadBinary:
|
||||
case eFileMode_Read:
|
||||
// Do nothing.
|
||||
break;
|
||||
|
||||
case eFileMode_Write:
|
||||
case eFileMode_WriteBinary:
|
||||
dwDesiredAccess = GENERIC_WRITE;
|
||||
break;
|
||||
|
||||
case eFileMode_WriteAppend:
|
||||
case eFileMode_WriteBinaryAppend:
|
||||
dwDesiredAccess = FILE_APPEND_DATA;
|
||||
break;
|
||||
}
|
||||
|
||||
m_Handle = CreateFile(filename, dwDesiredAccess, dwShareMode, NULL, 0, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
assert(m_Handle != INVALID_HANDLE_VALUE);
|
||||
}
|
||||
|
||||
~FileStreamImpl() {
|
||||
CloseHandle(m_Handle);
|
||||
}
|
||||
|
||||
void IncreaseReferenceCount() { m_ReferenceCount++; }
|
||||
void DecreaseReferenceCount() { m_ReferenceCount--; }
|
||||
|
||||
uint32 GetReferenceCount() { return m_ReferenceCount; }
|
||||
|
||||
HANDLE GetFileHandle() const { return m_Handle; }
|
||||
};
|
||||
|
||||
FileStream::FileStream(const CHAR *filename, EFileMode mode)
|
||||
: m_Impl(new FileStreamImpl(filename, mode))
|
||||
, m_Mode(mode)
|
||||
{
|
||||
strncpy_s(m_Filename, filename, kMaxFilenameSz);
|
||||
m_Filename[kMaxFilenameSz - 1] = CHAR('\0');
|
||||
}
|
||||
|
||||
FileStream::FileStream(const FileStream &other)
|
||||
: m_Impl(other.m_Impl)
|
||||
, m_Mode(other.m_Mode)
|
||||
{
|
||||
m_Impl->IncreaseReferenceCount();
|
||||
strncpy_s(m_Filename, other.m_Filename, kMaxFilenameSz);
|
||||
}
|
||||
|
||||
FileStream &FileStream::operator=(const FileStream &other) {
|
||||
|
||||
// We no longer reference this implementation.
|
||||
m_Impl->DecreaseReferenceCount();
|
||||
|
||||
// If we're the last ones to reference it, then it should be destroyed.
|
||||
if(m_Impl->GetReferenceCount() <= 0) {
|
||||
assert(m_Impl->GetReferenceCount() == 0);
|
||||
delete m_Impl;
|
||||
m_Impl = 0;
|
||||
}
|
||||
|
||||
m_Impl = other.m_Impl;
|
||||
m_Impl->IncreaseReferenceCount();
|
||||
|
||||
m_Mode = other.m_Mode;
|
||||
strncpy_s(m_Filename, other.m_Filename, kMaxFilenameSz);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
FileStream::~FileStream() {
|
||||
// We no longer reference this implementation.
|
||||
m_Impl->DecreaseReferenceCount();
|
||||
|
||||
// If we're the last ones to reference it, then it should be destroyed.
|
||||
if(m_Impl->GetReferenceCount() <= 0) {
|
||||
assert(m_Impl->GetReferenceCount() == 0);
|
||||
delete m_Impl;
|
||||
m_Impl = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int32 FileStream::Read(uint8 *buf, uint32 bufSz) {
|
||||
|
||||
if(
|
||||
m_Mode == eFileMode_Write ||
|
||||
m_Mode == eFileMode_WriteBinary ||
|
||||
m_Mode == eFileMode_WriteAppend ||
|
||||
m_Mode == eFileMode_WriteBinaryAppend
|
||||
) {
|
||||
CHAR errStr[256];
|
||||
_sntprintf_s(errStr, 256, "Cannot read from file '%s': File opened for reading.", m_Filename);
|
||||
OutputDebugString(errStr);
|
||||
return -2;
|
||||
}
|
||||
|
||||
HANDLE fp = m_Impl->GetFileHandle();
|
||||
if(INVALID_HANDLE_VALUE == fp)
|
||||
return -1;
|
||||
|
||||
DWORD oldPosition = SetFilePointer(fp, 0, NULL, FILE_CURRENT);
|
||||
if(INVALID_SET_FILE_POINTER == oldPosition) {
|
||||
CHAR errStr[256];
|
||||
_sntprintf_s(errStr, 256, "Error querying the file position before reading from file '%s'(0x%x).", m_Filename, GetLastError());
|
||||
OutputDebugString(errStr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
DWORD amtRead;
|
||||
BOOL success = ReadFile(fp, buf, bufSz, &amtRead, NULL);
|
||||
if(!success) {
|
||||
CHAR errStr[256];
|
||||
_sntprintf_s(errStr, 256, "Error reading from file '%s'.", m_Filename);
|
||||
OutputDebugString(errStr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
DWORD newPosition = SetFilePointer(fp, 0, NULL, FILE_CURRENT);
|
||||
if(INVALID_SET_FILE_POINTER == newPosition) {
|
||||
CHAR errStr[256];
|
||||
_sntprintf_s(errStr, 256, "Error querying the file position after reading from file '%s'(0x%x).", m_Filename, GetLastError());
|
||||
OutputDebugString(errStr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return newPosition - oldPosition;
|
||||
}
|
||||
|
||||
int32 FileStream::Write(const uint8 *buf, uint32 bufSz) {
|
||||
if(
|
||||
m_Mode == eFileMode_Read ||
|
||||
m_Mode == eFileMode_ReadBinary
|
||||
) {
|
||||
CHAR errStr[256];
|
||||
_sntprintf_s(errStr, 256, "Cannot write to file '%s': File opened for writing.", m_Filename);
|
||||
OutputDebugString(errStr);
|
||||
return -2;
|
||||
}
|
||||
|
||||
HANDLE fp = m_Impl->GetFileHandle();
|
||||
if(NULL == fp)
|
||||
return -1;
|
||||
|
||||
DWORD dwPos;
|
||||
if(m_Mode == eFileMode_WriteBinaryAppend || m_Mode == eFileMode_WriteAppend) {
|
||||
dwPos = SetFilePointer(fp, 0, NULL, FILE_END);
|
||||
}
|
||||
else {
|
||||
dwPos = SetFilePointer(fp, 0, NULL, FILE_CURRENT);
|
||||
}
|
||||
|
||||
if(INVALID_SET_FILE_POINTER == dwPos) {
|
||||
CHAR errStr[256];
|
||||
_sntprintf_s(errStr, 256, "Error querying the file position before reading to file '%s'(0x%x).", m_Filename, GetLastError());
|
||||
OutputDebugString(errStr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
while(!LockFile(fp, dwPos, 0, bufSz, 0)) Sleep(1);
|
||||
|
||||
DWORD amtWritten;
|
||||
BOOL success = WriteFile(fp, buf, bufSz, &amtWritten, NULL);
|
||||
|
||||
UnlockFile(fp, dwPos, 0, bufSz, 0);
|
||||
|
||||
if(!success) {
|
||||
CHAR errStr[256];
|
||||
_sntprintf_s(errStr, 256, "Error writing to file '%s'.", m_Filename);
|
||||
OutputDebugString(errStr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return amtWritten;
|
||||
}
|
||||
|
||||
int64 FileStream::Tell() {
|
||||
HANDLE fp = m_Impl->GetFileHandle();
|
||||
if(NULL == fp) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
DWORD pos = SetFilePointer(fp, 0, NULL, FILE_CURRENT);
|
||||
if(INVALID_SET_FILE_POINTER == pos) {
|
||||
CHAR errStr[256];
|
||||
_sntprintf_s(errStr, 256, "Error querying the file position before reading to file '%s'(0x%x).", m_Filename, GetLastError());
|
||||
OutputDebugString(errStr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
bool FileStream::Seek(uint32 offset, ESeekPosition pos) {
|
||||
|
||||
// We cannot seek in append mode.
|
||||
if(m_Mode == eFileMode_WriteAppend || m_Mode == eFileMode_WriteBinaryAppend)
|
||||
return false;
|
||||
|
||||
HANDLE fp = m_Impl->GetFileHandle();
|
||||
if(NULL == fp) return false;
|
||||
|
||||
DWORD origin = FILE_BEGIN;
|
||||
switch(pos) {
|
||||
default:
|
||||
case eSeekPosition_Beginning:
|
||||
// Do nothing
|
||||
break;
|
||||
|
||||
case eSeekPosition_Current:
|
||||
origin = FILE_CURRENT;
|
||||
break;
|
||||
|
||||
case eSeekPosition_End:
|
||||
origin = FILE_END;
|
||||
break;
|
||||
}
|
||||
|
||||
if(SetFilePointer(fp, offset, NULL, origin) == INVALID_SET_FILE_POINTER)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void FileStream::Flush() {
|
||||
HANDLE fp = m_Impl->GetFileHandle();
|
||||
if(NULL == fp) return;
|
||||
|
||||
FlushFileBuffers(fp);
|
||||
}
|
@ -48,6 +48,7 @@
|
||||
#include <stdio.h>
|
||||
#include <limits.h>
|
||||
#include <assert.h>
|
||||
#include <algorithm>
|
||||
|
||||
#include "ImageWriter.h"
|
||||
#include "ImageLoader.h"
|
||||
@ -75,10 +76,10 @@ static inline T abs(const T &a) {
|
||||
return a > 0? a : -a;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static inline T min(const T &a, const T &b) {
|
||||
return (a < b)? a : b;
|
||||
}
|
||||
//!HACK!
|
||||
#ifdef _MSC_VER
|
||||
#define strncpy strncpy_s
|
||||
#endif
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
@ -156,7 +157,7 @@ bool ImageFile::Write() {
|
||||
return false;
|
||||
}
|
||||
|
||||
WriteImageDataToFile(writer->GetRawFileData(), writer->GetRawFileDataSz(), m_Filename);
|
||||
WriteImageDataToFile(writer->GetRawFileData(), uint32(writer->GetRawFileDataSz()), m_Filename);
|
||||
|
||||
delete writer;
|
||||
return true;
|
||||
@ -197,13 +198,13 @@ Image *ImageFile::LoadImage(const unsigned char *rawImageData) const {
|
||||
|
||||
EImageFileFormat ImageFile::DetectFileFormat(const CHAR *filename) {
|
||||
|
||||
int len = strlen(filename);
|
||||
size_t len = strlen(filename);
|
||||
if(len >= 256) {
|
||||
// !FIXME! Report Error...
|
||||
return kNumImageFileFormats;
|
||||
}
|
||||
|
||||
int dotPos = len - 1;
|
||||
size_t dotPos = len - 1;
|
||||
|
||||
while(dotPos >= 0 && filename[dotPos--] != '.');
|
||||
|
||||
@ -242,8 +243,16 @@ unsigned char *ImageFile::ReadFileData(const CHAR *filename) {
|
||||
assert(fstr.Tell() == 0);
|
||||
|
||||
// Read all of the data
|
||||
int32 bytesRead = fstr.Read(rawData, fileSize);
|
||||
if(bytesRead != fileSize) {
|
||||
uint64 totalBytesRead = 0;
|
||||
uint64 totalBytesLeft = fileSize;
|
||||
uint32 bytesToRead = uint32(std::min(totalBytesLeft, uint64(1 << 31)));
|
||||
int32 bytesRead;
|
||||
while((bytesRead = fstr.Read(rawData, uint32(fileSize))) > 0) {
|
||||
totalBytesRead += bytesRead;
|
||||
totalBytesLeft -= bytesRead;
|
||||
}
|
||||
|
||||
if(totalBytesRead != fileSize) {
|
||||
assert(!"We didn't read as much data as we thought we had!");
|
||||
fprintf(stderr, "Internal error: Incorrect file size assumption\n");
|
||||
return 0;
|
||||
|
@ -48,6 +48,12 @@
|
||||
#include <limits.h>
|
||||
#include <assert.h>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Static helper functions
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename T>
|
||||
static inline T min(const T &a, const T &b) {
|
||||
return (a > b)? b : a;
|
||||
@ -58,6 +64,11 @@ static inline T abs(const T &a) {
|
||||
return (a > 0)? a : -a;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static inline T sad(const T &a, const T &b) {
|
||||
return (a > b)? a - b : b - a;
|
||||
}
|
||||
|
||||
void ReportError(const char *str) {
|
||||
fprintf(stderr, "ImageLoader.cpp -- ERROR: %s\n", str);
|
||||
}
|
||||
@ -102,8 +113,8 @@ unsigned int ImageLoader::GetChannelForPixel(uint32 x, uint32 y, uint32 ch) {
|
||||
const uint32 val = data[pixelIdx];
|
||||
|
||||
if(prec < 8) {
|
||||
uint32 ret = 0;
|
||||
for(uint32 precLeft = 8; precLeft > 0; precLeft -= min(prec, abs(prec - precLeft))) {
|
||||
int32 ret = 0;
|
||||
for(uint32 precLeft = 8; precLeft > 0; precLeft -= min(prec, sad(prec, precLeft))) {
|
||||
|
||||
if(prec > precLeft) {
|
||||
const int toShift = prec - precLeft;
|
||||
@ -120,7 +131,7 @@ unsigned int ImageLoader::GetChannelForPixel(uint32 x, uint32 y, uint32 ch) {
|
||||
return ret;
|
||||
}
|
||||
else if(prec > 8) {
|
||||
const int toShift = prec - 8;
|
||||
const int32 toShift = prec - 8;
|
||||
return val >> toShift;
|
||||
}
|
||||
|
||||
@ -156,12 +167,12 @@ bool ImageLoader::LoadImage() {
|
||||
#endif
|
||||
|
||||
int byteIdx = 0;
|
||||
for(int i = 0; i < ah; i+=4) {
|
||||
for(int j = 0; j < aw; j+= 4) {
|
||||
for(uint32 i = 0; i < ah; i+=4) {
|
||||
for(uint32 j = 0; j < aw; j+= 4) {
|
||||
|
||||
// For each block, visit the pixels in sequential order
|
||||
for(int y = i; y < i+4; y++) {
|
||||
for(int x = j; x < j+4; x++) {
|
||||
for(uint32 y = i; y < i+4; y++) {
|
||||
for(uint32 x = j; x < j+4; x++) {
|
||||
|
||||
if(y >= m_Height || x >= m_Width) {
|
||||
m_PixelData[byteIdx++] = 0; // r
|
||||
|
@ -150,14 +150,14 @@ bool ImageLoaderPNG::ReadData() {
|
||||
m_RedChannelPrecision = bitDepth;
|
||||
m_RedData = new unsigned char[numPixels];
|
||||
|
||||
for(int i = 0; i < m_Height; i++) {
|
||||
for(uint32 i = 0; i < m_Height; i++) {
|
||||
|
||||
png_read_row(png_ptr, rowData, NULL);
|
||||
|
||||
unsigned int rowOffset = i * m_Width;
|
||||
|
||||
unsigned int byteIdx = 0;
|
||||
for(int j = 0; j < m_Width; j++) {
|
||||
for(uint32 j = 0; j < m_Width; j++) {
|
||||
m_RedData[rowOffset + j] = rowData[byteIdx++];
|
||||
}
|
||||
|
||||
@ -174,14 +174,14 @@ bool ImageLoaderPNG::ReadData() {
|
||||
m_BlueChannelPrecision = bitDepth;
|
||||
m_BlueData = new unsigned char[numPixels];
|
||||
|
||||
for(int i = 0; i < m_Height; i++) {
|
||||
for(uint32 i = 0; i < m_Height; i++) {
|
||||
|
||||
png_read_row(png_ptr, rowData, NULL);
|
||||
|
||||
unsigned int rowOffset = i * m_Width;
|
||||
|
||||
unsigned int byteIdx = 0;
|
||||
for(int j = 0; j < m_Width; j++) {
|
||||
for(uint32 j = 0; j < m_Width; j++) {
|
||||
m_RedData[rowOffset + j] = rowData[byteIdx++];
|
||||
m_GreenData[rowOffset + j] = rowData[byteIdx++];
|
||||
m_BlueData[rowOffset + j] = rowData[byteIdx++];
|
||||
@ -201,14 +201,14 @@ bool ImageLoaderPNG::ReadData() {
|
||||
m_AlphaChannelPrecision = bitDepth;
|
||||
m_AlphaData = new unsigned char[numPixels];
|
||||
|
||||
for(int i = 0; i < m_Height; i++) {
|
||||
for(uint32 i = 0; i < m_Height; i++) {
|
||||
|
||||
png_read_row(png_ptr, rowData, NULL);
|
||||
|
||||
unsigned int rowOffset = i * m_Width;
|
||||
|
||||
unsigned int byteIdx = 0;
|
||||
for(int j = 0; j < m_Width; j++) {
|
||||
for(uint32 j = 0; j < m_Width; j++) {
|
||||
m_RedData[rowOffset + j] = rowData[byteIdx++];
|
||||
m_GreenData[rowOffset + j] = rowData[byteIdx++];
|
||||
m_BlueData[rowOffset + j] = rowData[byteIdx++];
|
||||
@ -225,14 +225,14 @@ bool ImageLoaderPNG::ReadData() {
|
||||
m_AlphaChannelPrecision = bitDepth;
|
||||
m_AlphaData = new unsigned char[numPixels];
|
||||
|
||||
for(int i = 0; i < m_Height; i++) {
|
||||
for(uint32 i = 0; i < m_Height; i++) {
|
||||
|
||||
png_read_row(png_ptr, rowData, NULL);
|
||||
|
||||
unsigned int rowOffset = i * m_Width;
|
||||
|
||||
unsigned int byteIdx = 0;
|
||||
for(int j = 0; j < m_Width; j++) {
|
||||
for(uint32 j = 0; j < m_Width; j++) {
|
||||
m_RedData[rowOffset + j] = rowData[byteIdx++];
|
||||
m_AlphaData[rowOffset + j] = rowData[byteIdx++];
|
||||
}
|
||||
|
@ -54,7 +54,7 @@ class ImageLoaderPNG : public ImageLoader {
|
||||
virtual bool ReadData();
|
||||
|
||||
private:
|
||||
unsigned int m_StreamPosition;
|
||||
uint64 m_StreamPosition;
|
||||
friend class PNGStreamReader;
|
||||
};
|
||||
|
||||
|
@ -125,13 +125,13 @@ bool ImageWriterPNG::WriteImage() {
|
||||
/* Initialize rows of PNG. */
|
||||
|
||||
row_pointers = (png_byte **)png_malloc (png_ptr, m_Height * sizeof (png_byte *));
|
||||
for (int y = 0; y < m_Height; ++y) {
|
||||
for (uint32 y = 0; y < m_Height; ++y) {
|
||||
png_byte *row = (png_byte *)png_malloc (png_ptr, sizeof (uint8) * m_Width * pixel_size);
|
||||
|
||||
row_pointers[y] = row;
|
||||
|
||||
for (int x = 0; x < m_Width; ++x) {
|
||||
for(int ch = 0; ch < 4; ch++) {
|
||||
for (uint32 x = 0; x < m_Width; ++x) {
|
||||
for(uint32 ch = 0; ch < 4; ch++) {
|
||||
*row++ = GetChannelForPixel(x, y, ch);
|
||||
}
|
||||
}
|
||||
@ -141,7 +141,7 @@ bool ImageWriterPNG::WriteImage() {
|
||||
png_set_rows (png_ptr, info_ptr, row_pointers);
|
||||
png_write_png (png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
|
||||
|
||||
for (int y = 0; y < m_Height; y++) {
|
||||
for (uint32 y = 0; y < m_Height; y++) {
|
||||
png_free (png_ptr, row_pointers[y]);
|
||||
}
|
||||
png_free (png_ptr, row_pointers);
|
||||
|
@ -55,7 +55,7 @@ class ImageWriterPNG : public ImageWriter {
|
||||
|
||||
virtual bool WriteImage();
|
||||
private:
|
||||
uint32 m_StreamPosition;
|
||||
uint64 m_StreamPosition;
|
||||
uint32 m_TotalBytesWritten;
|
||||
friend class PNGStreamWriter;
|
||||
};
|
||||
|
1
Windows
Submodule
1
Windows
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 1fad7ec01fd8b3cc88d5346231b5c6a92cfd0325
|
Loading…
Reference in New Issue
Block a user