mirror of
https://github.com/yuzu-emu/FasTC.git
synced 2024-11-30 21:24:17 +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.
|
// implementation has an 4:1 compression ratio.
|
||||||
void CompressImageBC7(const unsigned char *inBuf, unsigned char *outBuf, unsigned int width, unsigned int height)
|
void CompressImageBC7(const unsigned char *inBuf, unsigned char *outBuf, unsigned int width, unsigned int height)
|
||||||
{
|
{
|
||||||
uint32 block[16];
|
|
||||||
BC7CompressionMode::MaxAnnealingIterations = min(BC7CompressionMode::kMaxAnnealingIterations, GetQualityLevel());
|
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);
|
// ExtractBlock(inBuf + i * 4, width, block);
|
||||||
CompressBC7Block((const uint32 *)inBuf, outBuf);
|
CompressBC7Block((const uint32 *)inBuf, outBuf);
|
||||||
@ -1569,12 +1568,11 @@ namespace BC7C
|
|||||||
unsigned int height,
|
unsigned int height,
|
||||||
BlockStatManager &statManager
|
BlockStatManager &statManager
|
||||||
) {
|
) {
|
||||||
uint32 block[16];
|
|
||||||
BC7CompressionMode::MaxAnnealingIterations = min(BC7CompressionMode::kMaxAnnealingIterations, GetQualityLevel());
|
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);
|
// ExtractBlock(inBuf + i * 4, width, block);
|
||||||
CompressBC7Block((const uint32 *)inBuf, outBuf, statManager);
|
CompressBC7Block((const uint32 *)inBuf, outBuf, statManager);
|
||||||
@ -2387,7 +2385,7 @@ namespace BC7C
|
|||||||
|
|
||||||
assert(idxMode < 2);
|
assert(idxMode < 2);
|
||||||
assert(rotMode < 4);
|
assert(rotMode < 4);
|
||||||
assert(shapeIdx < ((mode == 0)? 16 : 64));
|
assert(shapeIdx < uint32((mode == 0)? 16 : 64));
|
||||||
|
|
||||||
uint32 cp = attrs->colorChannelPrecision;
|
uint32 cp = attrs->colorChannelPrecision;
|
||||||
const uint32 shift = 8 - cp;
|
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++) {
|
for(int nTries = 0; nTries < 3; nTries++) {
|
||||||
// !SPEED! Find eigenvectors by using the power method. This is good because the
|
// !SPEED! Find eigenvectors by using the power method. This is good because the
|
||||||
// matrix is only 4x4, which allows us to use SIMD...
|
// matrix is only 4x4, which allows us to use SIMD...
|
||||||
RGBAVector b = RGBAVector(rand());
|
RGBAVector b = RGBAVector(float(rand()));
|
||||||
assert(b.Length() > 0);
|
assert(b.Length() > 0);
|
||||||
b /= b.Length();
|
b /= b.Length();
|
||||||
|
|
||||||
@ -528,7 +528,7 @@ static uint32 PowerIteration(const RGBAMatrix &mat, RGBADir &eigVec, double &eig
|
|||||||
}
|
}
|
||||||
|
|
||||||
eigVal = newB.Length();
|
eigVal = newB.Length();
|
||||||
newB /= eigVal;
|
newB /= float(eigVal);
|
||||||
|
|
||||||
if(fabs(1.0f - (b * newB)) < 1e-5)
|
if(fabs(1.0f - (b * newB)) < 1e-5)
|
||||||
fixed = true;
|
fixed = true;
|
||||||
|
@ -54,6 +54,12 @@ ADD_EXECUTABLE(
|
|||||||
${SOURCES}
|
${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 BPTCEncoder )
|
||||||
TARGET_LINK_LIBRARIES( tc TexCompIO )
|
TARGET_LINK_LIBRARIES( tc TexCompIO )
|
||||||
TARGET_LINK_LIBRARIES( tc TexCompCore )
|
TARGET_LINK_LIBRARIES( tc TexCompCore )
|
||||||
|
@ -40,6 +40,187 @@
|
|||||||
*
|
*
|
||||||
* <http://gamma.cs.unc.edu/FasTC/>
|
* <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)
|
CMAKE_MINIMUM_REQUIRED(VERSION 2.8 FATAL_ERROR)
|
||||||
PROJECT(TexC)
|
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(BPTCEncoder)
|
||||||
ADD_SUBDIRECTORY(IO)
|
ADD_SUBDIRECTORY(IO)
|
||||||
ADD_SUBDIRECTORY(Core)
|
ADD_SUBDIRECTORY(Core)
|
||||||
|
@ -80,7 +80,15 @@ INCLUDE_DIRECTORIES( ${TexC_SOURCE_DIR}/Core/include )
|
|||||||
SET( THREAD_API )
|
SET( THREAD_API )
|
||||||
SET( THREAD_APIS_AVAILABLE "None" )
|
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 )
|
IF( Boost_FOUND )
|
||||||
|
|
||||||
SET( THREAD_APIS_AVAILABLE "Boost" ${THREAD_APIS_AVAILABLE} )
|
SET( THREAD_APIS_AVAILABLE "Boost" ${THREAD_APIS_AVAILABLE} )
|
||||||
@ -90,6 +98,8 @@ IF( Boost_FOUND )
|
|||||||
|
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
|
###### Find PThreads....
|
||||||
|
|
||||||
FIND_PACKAGE( Threads )
|
FIND_PACKAGE( Threads )
|
||||||
IF( CMAKE_USE_PTHREADS_INIT )
|
IF( CMAKE_USE_PTHREADS_INIT )
|
||||||
|
|
||||||
@ -111,7 +121,7 @@ SET_PROPERTY( CACHE THREAD_API PROPERTY STRINGS ${THREAD_APIS_AVAILABLE} )
|
|||||||
IF( THREAD_API MATCHES "Boost")
|
IF( THREAD_API MATCHES "Boost")
|
||||||
INCLUDE_DIRECTORIES( ${Boost_INCLUDE_DIR} )
|
INCLUDE_DIRECTORIES( ${Boost_INCLUDE_DIR} )
|
||||||
SET( SOURCES ${SOURCES} "src/ThreadBoost.cpp" )
|
SET( SOURCES ${SOURCES} "src/ThreadBoost.cpp" )
|
||||||
LINK_DIRECTORIES( ${Boost_LIBRARY_DIR} )
|
LINK_DIRECTORIES( ${Boost_LIBRARY_DIRS} )
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
IF( THREAD_API MATCHES "PThread" )
|
IF( THREAD_API MATCHES "PThread" )
|
||||||
@ -125,7 +135,7 @@ ELSE()
|
|||||||
SET( SOURCES ${SOURCES} "src/ThreadGroup.cpp" )
|
SET( SOURCES ${SOURCES} "src/ThreadGroup.cpp" )
|
||||||
SET( SOURCES ${SOURCES} "src/WorkerQueue.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/ThreadGroup.h" )
|
||||||
SET( HEADERS ${HEADERS} "src/WorkerQueue.h" )
|
SET( HEADERS ${HEADERS} "src/WorkerQueue.h" )
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
@ -46,7 +46,19 @@
|
|||||||
|
|
||||||
#include "TexCompTypes.h"
|
#include "TexCompTypes.h"
|
||||||
#include "ReferenceCounter.h"
|
#include "ReferenceCounter.h"
|
||||||
#include "Thread.h"
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Forward declarations
|
||||||
|
//
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
class TCMutex;
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// class BlockStat
|
||||||
|
//
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
struct BlockStat {
|
struct BlockStat {
|
||||||
friend class BlockStatManager;
|
friend class BlockStatManager;
|
||||||
@ -57,7 +69,7 @@ public:
|
|||||||
BlockStat(const BlockStat &);
|
BlockStat(const BlockStat &);
|
||||||
BlockStat &operator=(const BlockStat &);
|
BlockStat &operator=(const BlockStat &);
|
||||||
|
|
||||||
void ToString(char *buf, int bufSz) const;
|
void ToString(CHAR *buf, int bufSz) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const enum Type {
|
const enum Type {
|
||||||
@ -79,6 +91,8 @@ class BlockStatManager {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
BlockStatManager(int nBlocks);
|
BlockStatManager(int nBlocks);
|
||||||
|
BlockStatManager(const BlockStatManager &);
|
||||||
|
BlockStatManager &operator=(const BlockStatManager &);
|
||||||
~BlockStatManager();
|
~BlockStatManager();
|
||||||
|
|
||||||
uint32 BeginBlock();
|
uint32 BeginBlock();
|
||||||
@ -90,6 +104,7 @@ class BlockStatManager {
|
|||||||
class BlockStatList {
|
class BlockStatList {
|
||||||
public:
|
public:
|
||||||
BlockStatList();
|
BlockStatList();
|
||||||
|
BlockStatList(const BlockStatList &other);
|
||||||
~BlockStatList();
|
~BlockStatList();
|
||||||
|
|
||||||
void AddStat(const BlockStat &stat);
|
void AddStat(const BlockStat &stat);
|
||||||
@ -106,9 +121,12 @@ class BlockStatManager {
|
|||||||
} *m_BlockStatList;
|
} *m_BlockStatList;
|
||||||
uint32 m_BlockStatListSz;
|
uint32 m_BlockStatListSz;
|
||||||
|
|
||||||
TCMutex m_Mutex;
|
TCMutex *m_Mutex;
|
||||||
uint32 m_NextBlock;
|
uint32 m_NextBlock;
|
||||||
ReferenceCounter m_Counter;
|
ReferenceCounter m_Counter;
|
||||||
|
|
||||||
|
// Note: we probably shouldn't call this...
|
||||||
|
void Copy(const BlockStatManager &);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // __BLOCK_STATS_H__
|
#endif // __BLOCK_STATS_H__
|
||||||
|
@ -52,16 +52,17 @@
|
|||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
|
|
||||||
typedef __int16 int16;
|
typedef __int16 int16;
|
||||||
typedef __uint16 uint16;
|
typedef unsigned __int16 uint16;
|
||||||
typedef __int32 int32;
|
typedef __int32 int32;
|
||||||
typedef __uint32 uint32;
|
typedef unsigned __int32 uint32;
|
||||||
typedef __int8 int8;
|
typedef __int8 int8;
|
||||||
typedef __uint8 uint8;
|
typedef unsigned __int8 uint8;
|
||||||
|
|
||||||
typedef __uint64 uint64;
|
typedef unsigned __int64 uint64;
|
||||||
typedef __int64 int64;
|
typedef __int64 int64;
|
||||||
|
|
||||||
typedef __int32_ptr int32_ptr;
|
#include <tchar.h>
|
||||||
|
typedef TCHAR CHAR;
|
||||||
|
|
||||||
// If not, assume GCC, or at least standard defines...
|
// If not, assume GCC, or at least standard defines...
|
||||||
#else
|
#else
|
||||||
@ -78,7 +79,6 @@ typedef uint16_t uint16;
|
|||||||
typedef uint32_t uint32;
|
typedef uint32_t uint32;
|
||||||
typedef uint64_t uint64;
|
typedef uint64_t uint64;
|
||||||
|
|
||||||
typedef uintptr_t int32_ptr;
|
|
||||||
typedef char CHAR;
|
typedef char CHAR;
|
||||||
|
|
||||||
#endif // _MSC_VER
|
#endif // _MSC_VER
|
||||||
|
@ -49,6 +49,7 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
#include "FileStream.h"
|
#include "FileStream.h"
|
||||||
|
#include "Thread.h"
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static T max(const T &a, const T &b) {
|
static T max(const T &a, const T &b) {
|
||||||
@ -65,14 +66,22 @@ BlockStat::BlockStat(const CHAR *statName, int stat)
|
|||||||
: m_IntStat(stat)
|
: m_IntStat(stat)
|
||||||
, m_Type(eType_Int)
|
, m_Type(eType_Int)
|
||||||
{
|
{
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
strncpy_s(m_StatName, statName, kStatNameSz);
|
||||||
|
#else
|
||||||
strncpy(m_StatName, statName, kStatNameSz);
|
strncpy(m_StatName, statName, kStatNameSz);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
BlockStat::BlockStat(const CHAR *statName, double stat)
|
BlockStat::BlockStat(const CHAR *statName, double stat)
|
||||||
: m_FloatStat(stat)
|
: m_FloatStat(stat)
|
||||||
, m_Type(eType_Float)
|
, m_Type(eType_Float)
|
||||||
{
|
{
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
strncpy_s(m_StatName, statName, kStatNameSz);
|
||||||
|
#else
|
||||||
strncpy(m_StatName, statName, kStatNameSz);
|
strncpy(m_StatName, statName, kStatNameSz);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
BlockStat::BlockStat(const BlockStat &other) : m_Type(other.m_Type) {
|
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) {
|
BlockStat &BlockStat::operator=(const BlockStat &other) {
|
||||||
memcpy(this, &other, sizeof(*this));
|
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) {
|
switch(m_Type) {
|
||||||
case BlockStat::eType_Float:
|
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);
|
snprintf(buf, bufSz, "%s,%f", m_StatName, m_FloatStat);
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BlockStat::eType_Int:
|
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);
|
snprintf(buf, bufSz, "%s,%llu", m_StatName, m_IntStat);
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
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)
|
BlockStatManager::BlockStatManager(int nBlocks)
|
||||||
: m_BlockStatListSz(max(nBlocks, 0))
|
: m_BlockStatListSz(max(nBlocks, 0))
|
||||||
, m_NextBlock(0)
|
, m_NextBlock(0)
|
||||||
|
, m_Mutex(new TCMutex)
|
||||||
{
|
{
|
||||||
m_BlockStatList = new BlockStatList[m_BlockStatListSz];
|
m_BlockStatList = new BlockStatList[m_BlockStatListSz];
|
||||||
if(!m_BlockStatList) {
|
if(!m_BlockStatList) {
|
||||||
@ -121,6 +166,12 @@ BlockStatManager::~BlockStatManager() {
|
|||||||
if(m_Counter.GetRefCount() == 0) {
|
if(m_Counter.GetRefCount() == 0) {
|
||||||
delete [] m_BlockStatList;
|
delete [] m_BlockStatList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(m_Mutex)
|
||||||
|
{
|
||||||
|
delete m_Mutex;
|
||||||
|
m_Mutex = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 BlockStatManager::BeginBlock() {
|
uint32 BlockStatManager::BeginBlock() {
|
||||||
@ -130,7 +181,7 @@ uint32 BlockStatManager::BeginBlock() {
|
|||||||
return m_NextBlock-1;
|
return m_NextBlock-1;
|
||||||
}
|
}
|
||||||
|
|
||||||
TCLock lock (m_Mutex);
|
TCLock lock (*m_Mutex);
|
||||||
return m_NextBlock++;
|
return m_NextBlock++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,7 +192,7 @@ void BlockStatManager::AddStat(uint32 blockIdx, const BlockStat &stat) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
TCLock lock (m_Mutex);
|
TCLock lock (*m_Mutex);
|
||||||
m_BlockStatList[blockIdx].AddStat(stat);
|
m_BlockStatList[blockIdx].AddStat(stat);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -149,7 +200,7 @@ void BlockStatManager::ToFile(const CHAR *filename) {
|
|||||||
|
|
||||||
FileStream fstr (filename, eFileMode_Write);
|
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]);
|
const BlockStatList *head = &(m_BlockStatList[i]);
|
||||||
while(head) {
|
while(head) {
|
||||||
BlockStat s = head->GetStat();
|
BlockStat s = head->GetStat();
|
||||||
@ -158,9 +209,13 @@ void BlockStatManager::ToFile(const CHAR *filename) {
|
|||||||
s.ToString(statStr, 256);
|
s.ToString(statStr, 256);
|
||||||
|
|
||||||
CHAR str[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);
|
snprintf(str, 256, "%d,%s\n", i, statStr);
|
||||||
|
#endif
|
||||||
|
|
||||||
int strLen = strlen(str);
|
uint32 strLen = uint32(strlen(str));
|
||||||
if(strLen > 255) {
|
if(strLen > 255) {
|
||||||
str[255] = '\n';
|
str[255] = '\n';
|
||||||
strLen = 256;
|
strLen = 256;
|
||||||
@ -179,7 +234,7 @@ void BlockStatManager::ToFile(const CHAR *filename) {
|
|||||||
//
|
//
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
static const CHAR *kNullBlockString = "NULL_BLOCK_STAT";
|
static const CHAR *kNullBlockString = "NULL_BLOCK_STAT";
|
||||||
static const uint32 kNullBlockStringLength = strlen(kNullBlockString);
|
static const uint32 kNullBlockStringLength = uint32(strlen(kNullBlockString));
|
||||||
|
|
||||||
BlockStatManager::BlockStatList::BlockStatList()
|
BlockStatManager::BlockStatList::BlockStatList()
|
||||||
: m_Tail(0)
|
: m_Tail(0)
|
||||||
@ -190,8 +245,14 @@ BlockStatManager::BlockStatList::BlockStatList(const BlockStat &stat)
|
|||||||
: m_Tail(0)
|
: m_Tail(0)
|
||||||
, m_Stat(stat)
|
, 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() {
|
BlockStatManager::BlockStatList::~BlockStatList() {
|
||||||
if(m_Counter.GetRefCount() == 0 && m_Tail) {
|
if(m_Counter.GetRefCount() == 0 && m_Tail) {
|
||||||
delete m_Tail;
|
delete m_Tail;
|
||||||
|
@ -48,6 +48,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include "TexCompTypes.h"
|
||||||
#include "BC7Compressor.h"
|
#include "BC7Compressor.h"
|
||||||
|
|
||||||
CompressedImage::CompressedImage()
|
CompressedImage::CompressedImage()
|
||||||
@ -109,7 +110,7 @@ CompressedImage::~CompressedImage() {
|
|||||||
bool CompressedImage::DecompressImage(unsigned char *outBuf, unsigned int outBufSz) const {
|
bool CompressedImage::DecompressImage(unsigned char *outBuf, unsigned int outBufSz) const {
|
||||||
|
|
||||||
// First make sure that we have enough data
|
// First make sure that we have enough data
|
||||||
int dataSz = 0;
|
uint32 dataSz = 0;
|
||||||
switch(m_Format) {
|
switch(m_Format) {
|
||||||
case eCompressionFormat_DXT1: dataSz = m_DataSz * 8; break;
|
case eCompressionFormat_DXT1: dataSz = m_DataSz * 8; break;
|
||||||
case eCompressionFormat_DXT5: dataSz = m_DataSz * 4; 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;
|
const double wb = 1.0;
|
||||||
|
|
||||||
double MSE = 0.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 *pixelDataRaw = m_PixelData + i;
|
||||||
const unsigned char *pixelDataUncomp = unCompData + i;
|
const unsigned char *pixelDataUncomp = unCompData + i;
|
||||||
|
@ -67,12 +67,14 @@
|
|||||||
#include "TexCompTypes.h"
|
#include "TexCompTypes.h"
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
#include <Windows.h>
|
||||||
|
|
||||||
class StopWatchImpl {
|
class StopWatchImpl {
|
||||||
|
public:
|
||||||
uint64 frequency;
|
uint64 frequency;
|
||||||
uint64 start;
|
uint64 start;
|
||||||
uint64 stop;
|
uint64 stop;
|
||||||
uintptr affinityMask;
|
uintptr_t affinityMask;
|
||||||
|
|
||||||
StopWatchImpl() :
|
StopWatchImpl() :
|
||||||
start(0), stop(0), affinityMask(0)
|
start(0), stop(0), affinityMask(0)
|
||||||
@ -85,6 +87,8 @@ class StopWatchImpl {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
StopWatch::StopWatch() : impl(new StopWatchImpl) { }
|
||||||
|
|
||||||
StopWatch::StopWatch(const StopWatch &other) {
|
StopWatch::StopWatch(const StopWatch &other) {
|
||||||
impl = new StopWatchImpl();
|
impl = new StopWatchImpl();
|
||||||
memcpy(impl, other.impl, sizeof(StopWatchImpl));
|
memcpy(impl, other.impl, sizeof(StopWatchImpl));
|
||||||
@ -96,6 +100,7 @@ StopWatch &StopWatch::operator=(const StopWatch &other) {
|
|||||||
}
|
}
|
||||||
impl = new StopWatchImpl();
|
impl = new StopWatchImpl();
|
||||||
memcpy(impl, other.impl, sizeof(StopWatchImpl));
|
memcpy(impl, other.impl, sizeof(StopWatchImpl));
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
StopWatch::~StopWatch() {
|
StopWatch::~StopWatch() {
|
||||||
@ -156,7 +161,7 @@ double StopWatch::TimeInSeconds() const
|
|||||||
{
|
{
|
||||||
// Return the elapsed time in seconds.
|
// Return the elapsed time in seconds.
|
||||||
assert((impl->stop - impl->start) > 0);
|
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.
|
// Get the elapsed time in milliseconds.
|
||||||
@ -164,7 +169,7 @@ double StopWatch::TimeInMilliseconds() const
|
|||||||
{
|
{
|
||||||
// Return the elapsed time in milliseconds.
|
// Return the elapsed time in milliseconds.
|
||||||
assert((impl->stop - impl->start) > 0);
|
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.
|
// Get the elapsed time in microseconds.
|
||||||
|
@ -268,7 +268,7 @@ bool CompressImageData(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Allocate data based on the compression method
|
// Allocate data based on the compression method
|
||||||
int cmpDataSzNeeded = 0;
|
uint32 cmpDataSzNeeded = 0;
|
||||||
switch(settings.format) {
|
switch(settings.format) {
|
||||||
case eCompressionFormat_DXT1: cmpDataSzNeeded = dataSz / 8;
|
case eCompressionFormat_DXT1: cmpDataSzNeeded = dataSz / 8;
|
||||||
case eCompressionFormat_DXT5: cmpDataSzNeeded = dataSz / 4;
|
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.
|
// Our implementation is now the same as the other.
|
||||||
m_Impl = other.m_Impl;
|
m_Impl = other.m_Impl;
|
||||||
m_Impl->IncreaseReferenceCount();
|
m_Impl->IncreaseReferenceCount();
|
||||||
|
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
TCThreadBase::~TCThreadBase() {
|
TCThreadBase::~TCThreadBase() {
|
||||||
|
@ -46,6 +46,11 @@
|
|||||||
|
|
||||||
#include "TexCompTypes.h"
|
#include "TexCompTypes.h"
|
||||||
|
|
||||||
|
//!HACK! Apparently MSVC has issues with Yield()...????
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#undef Yield
|
||||||
|
#endif
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// Base implementation
|
// Base implementation
|
||||||
@ -112,8 +117,8 @@ class TCThread : public TCThreadBase {
|
|||||||
public:
|
public:
|
||||||
TCThread(TCCallable &);
|
TCThread(TCCallable &);
|
||||||
|
|
||||||
void Join();
|
|
||||||
static void Yield();
|
static void Yield();
|
||||||
|
void Join();
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
@ -286,6 +286,8 @@ bool ThreadGroup::CleanUpThreads() {
|
|||||||
// Reset active number of threads...
|
// Reset active number of threads...
|
||||||
m_ActiveThreads = 0;
|
m_ActiveThreads = 0;
|
||||||
m_ExitFlag = false;
|
m_ExitFlag = false;
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ThreadGroup::Join() {
|
void ThreadGroup::Join() {
|
||||||
|
@ -191,7 +191,7 @@ void WorkerQueue::Run() {
|
|||||||
|
|
||||||
// Spawn a bunch of threads...
|
// Spawn a bunch of threads...
|
||||||
TCLock lock(m_Mutex);
|
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_Workers[i] = new WorkerThread(this, i);
|
||||||
m_ThreadHandles[m_ActiveThreads] = new TCThread(*m_Workers[i]);
|
m_ThreadHandles[m_ActiveThreads] = new TCThread(*m_Workers[i]);
|
||||||
m_ActiveThreads++;
|
m_ActiveThreads++;
|
||||||
@ -211,7 +211,7 @@ void WorkerQueue::Run() {
|
|||||||
m_StopWatch.Stop();
|
m_StopWatch.Stop();
|
||||||
|
|
||||||
// Join them all together..
|
// Join them all together..
|
||||||
for(int i = 0; i < m_NumThreads; i++) {
|
for(uint32 i = 0; i < m_NumThreads; i++) {
|
||||||
m_ThreadHandles[i]->Join();
|
m_ThreadHandles[i]->Join();
|
||||||
delete m_ThreadHandles[i];
|
delete m_ThreadHandles[i];
|
||||||
delete m_Workers[i];
|
delete m_Workers[i];
|
||||||
@ -274,7 +274,7 @@ WorkerThread::EAction WorkerQueue::AcceptThreadData(uint32 threadIdx) {
|
|||||||
const uint8 *WorkerQueue::GetSrcForThread(const int threadIdx) const {
|
const uint8 *WorkerQueue::GetSrcForThread(const int threadIdx) const {
|
||||||
assert(m_Offsets[threadIdx] >= 0);
|
assert(m_Offsets[threadIdx] >= 0);
|
||||||
assert(threadIdx >= 0);
|
assert(threadIdx >= 0);
|
||||||
assert(threadIdx < m_NumThreads);
|
assert(threadIdx < int(m_NumThreads));
|
||||||
|
|
||||||
const uint32 inBufBlockSz = 16 * 4;
|
const uint32 inBufBlockSz = 16 * 4;
|
||||||
return m_InBuf + m_Offsets[threadIdx] * inBufBlockSz;
|
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 {
|
uint8 *WorkerQueue::GetDstForThread(const int threadIdx) const {
|
||||||
assert(m_Offsets[threadIdx] >= 0);
|
assert(m_Offsets[threadIdx] >= 0);
|
||||||
assert(threadIdx >= 0);
|
assert(threadIdx >= 0);
|
||||||
assert(threadIdx < m_NumThreads);
|
assert(threadIdx < int(m_NumThreads));
|
||||||
|
|
||||||
const uint32 outBufBlockSz = 16;
|
const uint32 outBufBlockSz = 16;
|
||||||
return m_OutBuf + m_Offsets[threadIdx] * outBufBlockSz;
|
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 {
|
uint32 WorkerQueue::GetNumBlocksForThread(const int threadIdx) const {
|
||||||
assert(m_Offsets[threadIdx] >= 0);
|
assert(m_Offsets[threadIdx] >= 0);
|
||||||
assert(threadIdx >= 0);
|
assert(threadIdx >= 0);
|
||||||
assert(threadIdx < m_NumThreads);
|
assert(threadIdx < int(m_NumThreads));
|
||||||
|
|
||||||
return m_NumBlocks[threadIdx];
|
return m_NumBlocks[threadIdx];
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,7 @@ class WorkerQueue;
|
|||||||
#include "Thread.h"
|
#include "Thread.h"
|
||||||
#include "StopWatch.h"
|
#include "StopWatch.h"
|
||||||
|
|
||||||
struct WorkerThread : public TCCallable {
|
class WorkerThread : public TCCallable {
|
||||||
friend class WorkerQueue;
|
friend class WorkerQueue;
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -43,7 +43,6 @@
|
|||||||
SET( SOURCES
|
SET( SOURCES
|
||||||
"src/ImageWriter.cpp"
|
"src/ImageWriter.cpp"
|
||||||
"src/ImageLoader.cpp"
|
"src/ImageLoader.cpp"
|
||||||
"src/FileStream.cpp"
|
|
||||||
"src/ImageFile.cpp"
|
"src/ImageFile.cpp"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -54,6 +53,15 @@ SET( HEADERS
|
|||||||
"include/FileStream.h"
|
"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 )
|
FIND_PACKAGE( PNG )
|
||||||
IF( PNG_FOUND )
|
IF( PNG_FOUND )
|
||||||
INCLUDE_DIRECTORIES( ${PNG_INCLUDE_DIR} )
|
INCLUDE_DIRECTORIES( ${PNG_INCLUDE_DIR} )
|
||||||
|
@ -139,6 +139,8 @@ FileStream &FileStream::operator=(const FileStream &other) {
|
|||||||
|
|
||||||
m_Mode = other.m_Mode;
|
m_Mode = other.m_Mode;
|
||||||
strncpy(m_Filename, other.m_Filename, kMaxFilenameSz);
|
strncpy(m_Filename, other.m_Filename, kMaxFilenameSz);
|
||||||
|
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
FileStream::~FileStream() {
|
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 <stdio.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
#include "ImageWriter.h"
|
#include "ImageWriter.h"
|
||||||
#include "ImageLoader.h"
|
#include "ImageLoader.h"
|
||||||
@ -75,10 +76,10 @@ static inline T abs(const T &a) {
|
|||||||
return a > 0? a : -a;
|
return a > 0? a : -a;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
//!HACK!
|
||||||
static inline T min(const T &a, const T &b) {
|
#ifdef _MSC_VER
|
||||||
return (a < b)? a : b;
|
#define strncpy strncpy_s
|
||||||
}
|
#endif
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
@ -156,7 +157,7 @@ bool ImageFile::Write() {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
WriteImageDataToFile(writer->GetRawFileData(), writer->GetRawFileDataSz(), m_Filename);
|
WriteImageDataToFile(writer->GetRawFileData(), uint32(writer->GetRawFileDataSz()), m_Filename);
|
||||||
|
|
||||||
delete writer;
|
delete writer;
|
||||||
return true;
|
return true;
|
||||||
@ -197,13 +198,13 @@ Image *ImageFile::LoadImage(const unsigned char *rawImageData) const {
|
|||||||
|
|
||||||
EImageFileFormat ImageFile::DetectFileFormat(const CHAR *filename) {
|
EImageFileFormat ImageFile::DetectFileFormat(const CHAR *filename) {
|
||||||
|
|
||||||
int len = strlen(filename);
|
size_t len = strlen(filename);
|
||||||
if(len >= 256) {
|
if(len >= 256) {
|
||||||
// !FIXME! Report Error...
|
// !FIXME! Report Error...
|
||||||
return kNumImageFileFormats;
|
return kNumImageFileFormats;
|
||||||
}
|
}
|
||||||
|
|
||||||
int dotPos = len - 1;
|
size_t dotPos = len - 1;
|
||||||
|
|
||||||
while(dotPos >= 0 && filename[dotPos--] != '.');
|
while(dotPos >= 0 && filename[dotPos--] != '.');
|
||||||
|
|
||||||
@ -242,8 +243,16 @@ unsigned char *ImageFile::ReadFileData(const CHAR *filename) {
|
|||||||
assert(fstr.Tell() == 0);
|
assert(fstr.Tell() == 0);
|
||||||
|
|
||||||
// Read all of the data
|
// Read all of the data
|
||||||
int32 bytesRead = fstr.Read(rawData, fileSize);
|
uint64 totalBytesRead = 0;
|
||||||
if(bytesRead != fileSize) {
|
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!");
|
assert(!"We didn't read as much data as we thought we had!");
|
||||||
fprintf(stderr, "Internal error: Incorrect file size assumption\n");
|
fprintf(stderr, "Internal error: Incorrect file size assumption\n");
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -48,6 +48,12 @@
|
|||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Static helper functions
|
||||||
|
//
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static inline T min(const T &a, const T &b) {
|
static inline T min(const T &a, const T &b) {
|
||||||
return (a > b)? b : a;
|
return (a > b)? b : a;
|
||||||
@ -58,6 +64,11 @@ static inline T abs(const T &a) {
|
|||||||
return (a > 0)? a : -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) {
|
void ReportError(const char *str) {
|
||||||
fprintf(stderr, "ImageLoader.cpp -- ERROR: %s\n", 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];
|
const uint32 val = data[pixelIdx];
|
||||||
|
|
||||||
if(prec < 8) {
|
if(prec < 8) {
|
||||||
uint32 ret = 0;
|
int32 ret = 0;
|
||||||
for(uint32 precLeft = 8; precLeft > 0; precLeft -= min(prec, abs(prec - precLeft))) {
|
for(uint32 precLeft = 8; precLeft > 0; precLeft -= min(prec, sad(prec, precLeft))) {
|
||||||
|
|
||||||
if(prec > precLeft) {
|
if(prec > precLeft) {
|
||||||
const int toShift = prec - precLeft;
|
const int toShift = prec - precLeft;
|
||||||
@ -120,7 +131,7 @@ unsigned int ImageLoader::GetChannelForPixel(uint32 x, uint32 y, uint32 ch) {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
else if(prec > 8) {
|
else if(prec > 8) {
|
||||||
const int toShift = prec - 8;
|
const int32 toShift = prec - 8;
|
||||||
return val >> toShift;
|
return val >> toShift;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -156,12 +167,12 @@ bool ImageLoader::LoadImage() {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
int byteIdx = 0;
|
int byteIdx = 0;
|
||||||
for(int i = 0; i < ah; i+=4) {
|
for(uint32 i = 0; i < ah; i+=4) {
|
||||||
for(int j = 0; j < aw; j+= 4) {
|
for(uint32 j = 0; j < aw; j+= 4) {
|
||||||
|
|
||||||
// For each block, visit the pixels in sequential order
|
// For each block, visit the pixels in sequential order
|
||||||
for(int y = i; y < i+4; y++) {
|
for(uint32 y = i; y < i+4; y++) {
|
||||||
for(int x = j; x < j+4; x++) {
|
for(uint32 x = j; x < j+4; x++) {
|
||||||
|
|
||||||
if(y >= m_Height || x >= m_Width) {
|
if(y >= m_Height || x >= m_Width) {
|
||||||
m_PixelData[byteIdx++] = 0; // r
|
m_PixelData[byteIdx++] = 0; // r
|
||||||
|
@ -150,14 +150,14 @@ bool ImageLoaderPNG::ReadData() {
|
|||||||
m_RedChannelPrecision = bitDepth;
|
m_RedChannelPrecision = bitDepth;
|
||||||
m_RedData = new unsigned char[numPixels];
|
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);
|
png_read_row(png_ptr, rowData, NULL);
|
||||||
|
|
||||||
unsigned int rowOffset = i * m_Width;
|
unsigned int rowOffset = i * m_Width;
|
||||||
|
|
||||||
unsigned int byteIdx = 0;
|
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_RedData[rowOffset + j] = rowData[byteIdx++];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -174,14 +174,14 @@ bool ImageLoaderPNG::ReadData() {
|
|||||||
m_BlueChannelPrecision = bitDepth;
|
m_BlueChannelPrecision = bitDepth;
|
||||||
m_BlueData = new unsigned char[numPixels];
|
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);
|
png_read_row(png_ptr, rowData, NULL);
|
||||||
|
|
||||||
unsigned int rowOffset = i * m_Width;
|
unsigned int rowOffset = i * m_Width;
|
||||||
|
|
||||||
unsigned int byteIdx = 0;
|
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_RedData[rowOffset + j] = rowData[byteIdx++];
|
||||||
m_GreenData[rowOffset + j] = rowData[byteIdx++];
|
m_GreenData[rowOffset + j] = rowData[byteIdx++];
|
||||||
m_BlueData[rowOffset + j] = rowData[byteIdx++];
|
m_BlueData[rowOffset + j] = rowData[byteIdx++];
|
||||||
@ -201,14 +201,14 @@ bool ImageLoaderPNG::ReadData() {
|
|||||||
m_AlphaChannelPrecision = bitDepth;
|
m_AlphaChannelPrecision = bitDepth;
|
||||||
m_AlphaData = new unsigned char[numPixels];
|
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);
|
png_read_row(png_ptr, rowData, NULL);
|
||||||
|
|
||||||
unsigned int rowOffset = i * m_Width;
|
unsigned int rowOffset = i * m_Width;
|
||||||
|
|
||||||
unsigned int byteIdx = 0;
|
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_RedData[rowOffset + j] = rowData[byteIdx++];
|
||||||
m_GreenData[rowOffset + j] = rowData[byteIdx++];
|
m_GreenData[rowOffset + j] = rowData[byteIdx++];
|
||||||
m_BlueData[rowOffset + j] = rowData[byteIdx++];
|
m_BlueData[rowOffset + j] = rowData[byteIdx++];
|
||||||
@ -225,14 +225,14 @@ bool ImageLoaderPNG::ReadData() {
|
|||||||
m_AlphaChannelPrecision = bitDepth;
|
m_AlphaChannelPrecision = bitDepth;
|
||||||
m_AlphaData = new unsigned char[numPixels];
|
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);
|
png_read_row(png_ptr, rowData, NULL);
|
||||||
|
|
||||||
unsigned int rowOffset = i * m_Width;
|
unsigned int rowOffset = i * m_Width;
|
||||||
|
|
||||||
unsigned int byteIdx = 0;
|
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_RedData[rowOffset + j] = rowData[byteIdx++];
|
||||||
m_AlphaData[rowOffset + j] = rowData[byteIdx++];
|
m_AlphaData[rowOffset + j] = rowData[byteIdx++];
|
||||||
}
|
}
|
||||||
|
@ -54,7 +54,7 @@ class ImageLoaderPNG : public ImageLoader {
|
|||||||
virtual bool ReadData();
|
virtual bool ReadData();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
unsigned int m_StreamPosition;
|
uint64 m_StreamPosition;
|
||||||
friend class PNGStreamReader;
|
friend class PNGStreamReader;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -125,13 +125,13 @@ bool ImageWriterPNG::WriteImage() {
|
|||||||
/* Initialize rows of PNG. */
|
/* Initialize rows of PNG. */
|
||||||
|
|
||||||
row_pointers = (png_byte **)png_malloc (png_ptr, m_Height * sizeof (png_byte *));
|
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);
|
png_byte *row = (png_byte *)png_malloc (png_ptr, sizeof (uint8) * m_Width * pixel_size);
|
||||||
|
|
||||||
row_pointers[y] = row;
|
row_pointers[y] = row;
|
||||||
|
|
||||||
for (int x = 0; x < m_Width; ++x) {
|
for (uint32 x = 0; x < m_Width; ++x) {
|
||||||
for(int ch = 0; ch < 4; ch++) {
|
for(uint32 ch = 0; ch < 4; ch++) {
|
||||||
*row++ = GetChannelForPixel(x, y, ch);
|
*row++ = GetChannelForPixel(x, y, ch);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -141,7 +141,7 @@ bool ImageWriterPNG::WriteImage() {
|
|||||||
png_set_rows (png_ptr, info_ptr, row_pointers);
|
png_set_rows (png_ptr, info_ptr, row_pointers);
|
||||||
png_write_png (png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
|
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[y]);
|
||||||
}
|
}
|
||||||
png_free (png_ptr, row_pointers);
|
png_free (png_ptr, row_pointers);
|
||||||
|
@ -55,7 +55,7 @@ class ImageWriterPNG : public ImageWriter {
|
|||||||
|
|
||||||
virtual bool WriteImage();
|
virtual bool WriteImage();
|
||||||
private:
|
private:
|
||||||
uint32 m_StreamPosition;
|
uint64 m_StreamPosition;
|
||||||
uint32 m_TotalBytesWritten;
|
uint32 m_TotalBytesWritten;
|
||||||
friend class PNGStreamWriter;
|
friend class PNGStreamWriter;
|
||||||
};
|
};
|
||||||
|
1
Windows
Submodule
1
Windows
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit 1fad7ec01fd8b3cc88d5346231b5c6a92cfd0325
|
Loading…
Reference in New Issue
Block a user